Next: , Previous: Optimistic concurrency, Up: Multithreading


5.3 Higher-level synchronization

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

5.3.1 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] –> condvar
— procedure: condvar? object –> boolean

Condition variable constructor & disjoint type predicate. Id is used purely for debugging.

— procedure: maybe-commit-and-wait-for-condvar condvar –> boolean
— procedure: maybe-commit-and-set-condvar! condvar value –> 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 &c.; see the note in Optimistic concurrency on this matter for details.

— procedure: condvar-has-value? condvar –> boolean
— procedure: condvar-value condvar –> 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 –> unspecified
— procedure: set-condvar-value! condvar value –> 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.

5.3.2 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] –> placeholder
— procedure: placeholder? object –> boolean

Placeholder constructor & disjoint type predicate. Id is used only for debugging purposes when printing placeholders.

— procedure: placeholder-value placeholder –> value
— procedure: placeholder-set! placeholder value –> 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.

5.3.3 Value pipes

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

— procedure: make-pipe [size [id]] –> value-pipe
— procedure: pipe? object –> 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 –> boolean
— procedure: empty-pipe! pipe –> 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 –> value
— procedure: pipe-maybe-read! pipe –> value or #f
— procedure: pipe-maybe-read?! pipe –> [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 –> unspecified
— procedure: pipe-push! pipe value –> unspecified
— procedure: pipe-maybe-write! pipe value –> 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.