Higher-level synchronization
============================

This section details the various higher-level thread synchronization devices that Scheme48 provides.

Condition variables
-------------------

Condition variables are multiple-assignment cells on which readers block.  Threads may wait on condition variables; when some other thread assigns a condition variable, all threads waiting on it are revived.  The condvars structure exports all of these condition-variable-related names.

In many concurrency systems, condition variables are operated in conjunction with mutual exclusion locks.  On the other hand, in Scheme48, they are used in conjunction with its optimistic concurrency devices.

 -- procedure: make-condvar [id] returns condvar
 -- procedure: condvar? object returns boolean
     Condition variable constructor & disjoint type predicate.  ID is used purely for debugging.

 -- procedure: maybe-commit-and-wait-for-condvar condvar returns boolean
 -- procedure: maybe-commit-and-set-condvar! condvar value returns boolean
     Maybe-commit-and-wait-for-condvar attempts to commit the current proposal.  If the commit succeeded, the current thread is blocked on CONDVAR, and when the current thread is woken up, maybe-commit-and-wait-for-condvar returns #t.  If the commit did not succeed, maybe-commit-and-wait-for-condvar immediately returns #f.  Maybe-commit-and-set-condvar! attempts to commit the current proposal as well.  If it succeeds, it is noted that CONDVAR has a value, CONDVAR's value is set to be VALUE, and all threads waiting on CONDVAR are woken up.

     Note: Do not use these in atomic transactions as delimited by call-ensuring-atomicity etc; see the note in Optimistic concurrency on this matter for details.

 -- procedure: condvar-has-value? condvar returns boolean
 -- procedure: condvar-value condvar returns value
     Condvar-has-value? tells whether or not CONDVAR has been assigned.  If it has been assigned, condvar-value accesses the value to which it was assigned.

 -- procedure: set-condvar-has-value?! condvar boolean returns unspecified
 -- procedure: set-condvar-value! condvar value returns unspecified
     Set-condvar-has-value?! is used to tell whether or not CONDVAR is assigned.  Set-condvar-value! sets CONDVAR's value.

     Note: Set-condvar-has-value?! should be used only with a second argument of #f.  Set-condvar-value! is a very dangerous routine, and maybe-commit-and-set-condvar! is what one should almost always use, except if one wishes to clean up after unassigning a condition variable.

Placeholders
------------

Placeholders are similar to condition variables, except that they may be assigned only once; they are in general a much simpler mechanism for throw-away temporary synchronization devices.  They are provided by the placeholders structure.

 -- procedure: make-placeholder [id] returns placeholder
 -- procedure: placeholder? object returns boolean
     Placeholder constructor & disjoint type predicate.  ID is used only for debugging purposes when printing placeholders.

 -- procedure: placeholder-value placeholder returns value
 -- procedure: placeholder-set! placeholder value returns unspecified
     Placeholder-value blocks until PLACEHOLDER is assigned, at which point it returns the value assigned.  Placeholder-set! assigns PLACEHOLDER's value to VALUE, awakening all threads waiting for PLACEHOLDER.  It is an error to assign a placeholder with placeholder-set! that has already been assigned.

Value pipes
-----------

Value pipes are asynchronous communication pipes between threads. The value-pipes structure exports these value pipe operations.

 -- procedure: make-pipe [size [id]] returns value-pipe
 -- procedure: pipe? object returns boolean
     Make-pipe is the value pipe constructor.  SIZE is a limit on the number of elements the pipe can hold at one time.  ID is used for debugging purposes only in printing pipes.  Pipe? is the disjoint type predicate for value pipes.

 -- procedure: empty-pipe? pipe returns boolean
 -- procedure: empty-pipe! pipe returns unspecified
     Empty-pipe? returns #t if PIPE has no elements in it and #f if not.  Empty-pipe! removes all elements from pipe.

 -- procedure: pipe-read! pipe returns value
 -- procedure: pipe-maybe-read! pipe returns value or #f
 -- procedure: pipe-maybe-read?! pipe returns [boolean value]
     Pipe-read! reads a value from PIPE, removing it from the queue.  It blocks if there are no elements available in the queue. Pipe-maybe-read! attempts to read & return a single value from PIPE; if no elements are available in its queue, it instead returns #f.  Pipe-maybe-read?! does similarly, but it returns two values: a boolean, signifying whether or not a value was read; and the value, or #f if no value was read. Pipe-maybe-read?! is useful when PIPE may contain the value #f.

 -- procedure: pipe-write! pipe value returns unspecified
 -- procedure: pipe-push! pipe value returns unspecified
 -- procedure: pipe-maybe-write! pipe value returns boolean
     Pipe-write! attempts to add VALUE to PIPE's queue. If PIPE's maximum size, as passed to make-pipe when constructing the pipe, is either #f or greater than the number of elements in PIPE's queue, pipe-write! will not block; otherwise it will block until a space has been made available in the pipe's queue by another thread reading from it.  Pipe-push! does similarly, but, in the case where the pipe is full, it pushes the first element to be read out of the pipe.  Pipe-maybe-write! is also similar to pipe-write!, but it returns #t if the pipe was not full, and it immediately returns #f if the pipe was full.