Next: Concurrent ML, Previous: Optimistic concurrency, Up: Multithreading
This section details the various higher-level thread synchronization devices that Scheme48 provides.
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.
Condition variable constructor & disjoint type predicate. Id is used purely for debugging.
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
&c.; see the note in Optimistic concurrency on this matter for details.
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.
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, andmaybe-commit-and-set-condvar!
is what one should almost always use, except if one wishes to clean up after unassigning a condition variable.
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.
Placeholder constructor & disjoint type predicate. Id is used only for debugging purposes when printing placeholders.
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 withplaceholder-set!
that has already been assigned.
Value pipes are asynchronous communication pipes between threads.
The value-pipes
structure exports these value pipe operations.
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.
Empty-pipe?
returns#t
if pipe has no elements in it and#f
if not.Empty-pipe!
removes all elements frompipe
.
#f
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
.
Pipe-write!
attempts to add value to pipe's queue. If pipe's maximum size, as passed tomake-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 topipe-write!
, but it returns#t
if the pipe was not full, and it immediately returns#f
if the pipe was full.