# (lispkit thread shared-queue)

Library `(lispkit thread shared-queue)` implements thread-safe queues for which all operations are done atomically. Such *shared queues* optionally have a maximum length. They start out in state "open", which means they allow elements to be added. Once a *shared queue* has been closed, new elements cannot be added anymore, but existing ones can still be dequeued.

With this functionality, shared queues provide a good basis for synchronizing threads. For example, you can let a consumer thread block if a shared queue is empty, or a producer thread block if the number of items in the shared queue reaches a specified limit. Thus, *shared queues* constitute a more conventional alternative to *channels* as provided by library `(lispkit thread channel)`.

Inspired by the `mtqueue` abstraction of the Scheme implementation *Gauche*, this library not only supports `enqueue!` for adding items to the end of the queue and `dequeue!` for taking items from the front of the queue, but also `queue-push!` for putting items at the front of the queue. Therefore, *shared queues* can also be used for use cases where stack semantics (LIFO) is needed.

**shared-queue-type-tag** <img src="/files/viHiVHsCY8Wn2TeCgWJj" alt="" data-size="line">

Symbol representing the `shared-queue` type. The `type-for` procedure of library `(lispkit type)` returns this symbol for all shared queue objects.

**(shared-queue?&#x20;*****obj*****)**     <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

Returns `#t` if *obj* is a shared queue object; `#f` otherwise.

**(make-shared-queue)**     <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">\
\&#xNAN;**(make-shared-queue&#x20;*****maxlen*****)**\
\&#xNAN;**(make-shared-queue&#x20;*****maxlen capacity*****)**

Returns a new empty shared queue with maximum length *maxlen* and a given initial *capacity*. If *maxlen* is not provided, there is no maximum length and inserting an element never blocks.

**(shared-queue-copy&#x20;*****sq*****)**     <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

Returns a copy of shared queue *sq*. The copy has the same maximum length like *sq* and all elements currently in the queue are copied over.

**(list->shared-queue&#x20;*****xs*****)**     <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">\
\&#xNAN;**(list->shared-queue&#x20;*****xs maxlen*****)**\
\&#xNAN;**(list->shared-queue&#x20;*****xs maxlen capacity*****)**

Returns a new shared queue with maximum length *maxlen* and a given initial *capacity*. The new queue contains the elements from list *xs*. If *maxlen* is not provided, there is no maximum length and inserting an element never blocks.

**(shared-queue->list&#x20;*****sq*****)**     <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

Returns the elements currently in the shared queue *sq* as a list. The elements remain in *sq*.

**(shared-queue-empty?&#x20;*****sq*****)**     <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

Returns `#t` if shared queue *sq* does not have any items queued up; returns `#f` otherwise.

**(shared-queue-closed?&#x20;*****sq*****)**     <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

Returns `#t` if shared queue *sq* has been closed, i.e. it does not allow to enqueue more items; returns `#f` otherwise.

**(shared-queue-max-length&#x20;*****sq*****)**     <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

Returns the maximum number of items the shared queue *sq* can hold.

**(shared-queue-length&#x20;*****sq*****)**     <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

Returns the number of items in the shared queue *sq*.

**(shared-queue-room&#x20;*****sq*****)**     <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

Returns the number of items the shared queue *sq* can accept at this moment to reach its maximum length. For example, if the shared queue has the maximum number of items already, 0 is returned.

**(shared-queue-num-waiting&#x20;*****sq*****)**     <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

Returns two values: the first value is the number of threads waiting on the shared queue *sq* to read at this moment; the second value is the number of threads waiting on *sq* to write at this moment.

**(shared-queue-front&#x20;*****sq*****)**     <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">\
\&#xNAN;**(shared-queue-front&#x20;*****sq default*****)**

Returns the first item in the shared queue *sq*. This is the item that `shared-queue-dequeue!` would remove if called. `shared-queue-front` does not modify *sq* itself. If *sq* is empty, *default* is returned if it is given, otherwise an error is signaled.

**(shared-queue-rear&#x20;*****sq*****)**     <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">\
\&#xNAN;**(shared-queue-rear&#x20;*****sq default*****)**

Returns the last item in the shared queue *sq*. `shared-queue-rear` does not modify *sq* itself. If *sq* is empty, *default* is returned if it is given, otherwise an error is signaled.

**(shared-queue-enqueue!&#x20;*****sq x ...*****)**     <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

Inserts the elements *x ...* at the end of the shared queue *sq* in the order they are given.

```scheme
(define sq (make-shared-queue))
(shared-queue-front sq #f)  ⇒  #f
(shared-queue-enqueue! sq 1)
(shared-queue-front sq #f)  ⇒  1
(shared-queue-enqueue! sq 2 3 4)
(shared-queue-front sq #f)  ⇒  1
(shared-queue->list sq)  ⇒  (1 2 3 4)
```

**(shared-queue-push!&#x20;*****sq x ...*****)**     <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

Inserts the elements *x ...* at the start of the shared queue *sq* in the order they are given.

```scheme
(define sq (make-shared-queue))
(shared-queue-push! sq 1)
(shared-queue-front sq #f)  ⇒  1
(shared-queue-push! sq 2 3 4)
(shared-queue-front sq #f)  ⇒  4
(shared-queue->list sq)  ⇒  (4 3 2 1)
```

**(shared-queue-dequeue!&#x20;*****sq*****)**     <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">\
\&#xNAN;**(shared-queue-dequeue!&#x20;*****sq default*****)**

Returns and removes the first element of the shared queue *sq*. If the queue is empty, an error is signaled unless the *default* parameter is provided. In this case, *default* is returned.

**(shared-queue-pop!&#x20;*****sq*****)**     <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">\
\&#xNAN;**(shared-queue-pop!&#x20;*****sq default*****)**

Returns and removes the first element of the shared queue *sq*. If the queue is empty, an error is signaled unless the *default* parameter is provided. In this case, *default* is returned. This procedure is functionally equivalent with `shared-queue-dequeue!`. It is provided to help emphasizing that the queue is used like a stack together with `shared-queue-push!`.

**(shared-queue-dequeue-all!&#x20;*****sq*****)**     <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">\
\&#xNAN;**(shared-queue-dequeue-all!&#x20;*****sq close?*****)**

Removes all items from the shared queue *sq* and returns them as a list. If argument *close?* is provided and set to true, the shared queue *sq* will be closed. The whole operation is done atomically.

**(shared-queue-enqueue/wait!&#x20;*****sq x*****)**     <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">\
\&#xNAN;**(shared-queue-enqueue/wait!&#x20;*****sq x timeout*****)**\
\&#xNAN;**(shared-queue-enqueue/wait!&#x20;*****sq x timeout default*****)**\
\&#xNAN;**(shared-queue-enqueue/wait!&#x20;*****sq x timeout default close?*****)**

Inserts the element *x* at the end of the shared queue *sq*. This procedure blocks if *sq* has reached its maximum length until *x* was eventually inserted successfully. The optional *timeout* argument specifies the maximum time to wait in seconds. If it is set to `\#f`, `shared-queue-enqueue/wait!` will wait indefinitely. In case the call is timing out, the value of *default* is returned (`#f` is the default). If the operation succeeds without timing out, `#t` is returned. If *sq* is already closed, `shared-queue-enqueue/wait!` raises an error without modifying *sq*. The whole check and insert operation is performed atomically.

If the last optional argument *close?* is given and true, `shared-queue-enqueue/wait!` closes the shared queue *sq*. The close operation is done atomically and it is guaranteed that *x* is the last item put into the queue.

**(shared-queue-push/wait!&#x20;*****sq x*****)**     <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">\
\&#xNAN;**(shared-queue-push/wait!&#x20;*****sq x timeout*****)**\
\&#xNAN;**(shared-queue-push/wait!&#x20;*****sq x timeout default*****)**\
\&#xNAN;**(shared-queue-push/wait!&#x20;*****sq x timeout default close?*****)**

Inserts the element *x* at the start of the shared queue *sq*. This procedure blocks if *sq* has reached its maximum length until *x* was eventually inserted successfully. The optional *timeout* argument specifies the maximum time to wait in seconds. If it is set to `\#f`, `shared-queue-push/wait!` will wait indefinitely. In case the call is timing out, the value of *default* is returned (`#f` is the default). If the operation succeeds without timing out, `#t` is returned. If *sq* is already closed, `shared-queue-push/wait!` raises an error without modifying *sq*. The whole check and insert operation is performed atomically.

If the last optional argument *close?* is given and true, `shared-queue-push/wait!` closes the shared queue *sq*. The close operation is done atomically and it is guaranteed that *x* is the last item put into the queue.

**(shared-queue-dequeue/wait!&#x20;*****sq*****)**     <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">\
\&#xNAN;**(shared-queue-dequeue/wait!&#x20;*****sq timeout*****)**\
\&#xNAN;**(shared-queue-dequeue/wait!&#x20;*****sq timeout default*****)**\
\&#xNAN;**(shared-queue-dequeue/wait!&#x20;*****sq timeout default close?*****)**

Returns and removes the first element of the shared queue *sq* independent of the queue being closed. This procedure blocks if *sq* is empty waiting until an item has been inserted and can successfully be dequeued. The optional *timeout* argument specifies the maximum time to wait in seconds. If it is set to `\#f`, `shared-queue-dequeue/wait!` will wait indefinitely. In case the call is timing out, the value of *default* is returned (`#f` is the default). If the operation succeeds without timing out, the dequeued item is returned. The whole check and dequeue operation is performed atomically.

If the last optional argument *close?* is given and true, `shared-queue-dequeue/wait!` closes the shared queue *sq*.

**(shared-queue-pop/wait!&#x20;*****sq*****)**     <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">\
\&#xNAN;**(shared-queue-pop/wait!&#x20;*****sq timeout*****)**\
\&#xNAN;**(shared-queue-pop/wait!&#x20;*****sq timeout default*****)**\
\&#xNAN;**(shared-queue-pop/wait!&#x20;*****sq timeout default close?*****)**

This procedure is functionally equivalent with `shared-queue-dequeue/wait!`. It is provided to help emphasizing that the queue is used like a stack together with `shared-queue-push/wait!`.

**(shared-queue-close!&#x20;*****sq*****)**     <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">\
\&#xNAN;**(shared-queue-close!&#x20;*****sq force?*****)**

Closes the shared queue *sq*. As a consequence, no new items can be inserted. It is still possible to dequeue items until the queue is empty. If argument *force?* is provided and set to true, then even dequeuing is not possible anymore and attempts to do that result in errors to be signaled.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://www.lisppad.app/libraries/lispkit/lispkit-thread-shared-queue.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
