1% Part of Scheme 48 1.9. See file COPYING for notices and license. 2 3% Authors: Richard Kelsey, Jonathan Rees, Mike Sperber, Robert Ransom 4 5\chapter{Threads} 6 7% safety (and the lack thereof) 8 9This chapter describes Scheme~48's thread system: Scheme~48 threads 10are fully preemptive; all threads (currently) run within a single 11operating system process. Scheme~48 allows writing customized, nested 12schedulers, and provides numerous facilities for the synchronization 13of shared-memory programs, most importantly \textit{proposals} for 14optimistic concurrency. 15 16\section{Creating and controlling threads} 17 18The bindings described in this section are part of the \code{threads} 19structure. 20% 21\begin{protos} 22\proto{spawn}{ thunk}{thread} 23\proto{spawn}{ thunk name}{thread} 24\end{protos} 25% 26\code{Spawn} creates a new thread, passes that thread to the current 27scheduler, and instructs the scheduler to run \cvar{thunk} in that 28thread. The \cvar{name} argument (a symbol) associates a symbolic 29name with the thread; it is purely for debugging purposes. 30% 31\begin{protos} 32\protonoresult{relinquish-timeslice}{} 33\protonoresult{sleep}{ time-in-milliseconds} 34\protonoresult{terminate-current-thread}{} 35\end{protos} 36% 37\code{Relinquish-timeslice} instructs the scheduler to run another 38thread, thus relinquishing the timeslice of the current thread. 39\code{Sleep} does the same and asks the scheduler to suspend the 40current thread for at least \cvar{time-in-milliseconds} milliseconds 41before resuming it. Finally, \code{terminate-current-thread} 42terminates the current thread. 43 44Each thread is represented by a thread object. The following 45procedures operate on that object: 46% 47\begin{protos} 48\proto{current-thread}{}{thread} 49\proto{thread?}{ thing}{boolean} 50\proto{thread-name}{ thread}{name} 51\proto{thread-uid}{ thread}{integer} 52\end{protos} 53% 54\code{Current-thread} returns the thread object associated with the 55currently running thread. 56\code{Thread?} is the predicate for thread objects. 57\code{Thread-name} extracts the name of the thread, if one was 58specified in the call to \code{spawn}, \code{\#f} otherwise. 59\code{Thread-uid} returns the \textit{uid} of the thread, a unique 60integer assigned by the thread system. 61 62\section{Advanced thread handling} 63 64The following bindings are part of the \code{threads-internal} structure: 65% 66\begin{protos} 67\protonoresultnoindex{terminate-thread!}{ thread}\mainschindex{terminate-thread"!} 68\protonoresultnoindex{kill-thread!}{ thread}\mainschindex{kill-thread"!} 69\end{protos} 70% 71\code{Terminate-thread!} unwinds the thread 72associated with \cvar{thread}, running any pending \code{dynamic-wind} 73\cvar{after} thunks (in that thread), after which the thread 74terminates. \code{Kill-thread!} causes the thread associated with 75\cvar{thread} to terminate immediately without unwinding its continuation. 76% 77 78 79\section{Debugging multithreaded programs} 80 81Debugging multithreaded programs can be difficult. 82 83As described in section~\ref{command-threads}, when any thread signals an 84 error, Scheme~48 stops running all of the threads at that command level. 85 86 The following procedure (exported by the structure 87 \code{debug-messages}) is useful in debugging multi-threaded 88 programs. 89\begin{protos} 90\protonoresult{debug-message}{ element$_0$ \ldots} 91\end{protos} 92\code{Debug-message} prints the elements to `\code{stderr}', followed by a 93 newline. 94The only types of values that \code{debug-message} prints in full are small 95 integers (fixnums), strings, characters, symbols, booleans, and the empty list. 96Values of other types are abbreviated as follows: 97% 98\begin{center} 99\begin{tabular}{ll} 100 pair & \code{(...)}\\ 101 vector & \code{\#(...)}\\ 102 procedure & \code{\#\{procedure\}}\\ 103 record & \code{\#\{<name of record type>\}}\\ 104 all others & \code{???}\\ 105\end{tabular} 106\end{center} 107% 108The great thing about \code{debug-message} is that it bypasses Scheme~48's 109 I/O and thread handling. 110The message appears immediately, with no delays or errors. 111 112\section{Optimistic concurrency} 113\label{sec:optimistic-concurrency} 114 115Most of the bindings described in this section are part of the \code{proposals} 116structure---the low-level bindings described at the very end of the 117section are part of the \code{low-proposals} structure. 118 119A \cvar{proposal} is a record of reads from and and writes to locations in 120 memory. Each thread has an associated \textit{current proposal} 121 (which may be \code{\#f}). 122The \cvar{logging} operations listed below record any values read or 123 written in the current proposal. 124A reading operation, such as \code{provisional-vector-ref}, first checks to 125 see if the current proposal contains a value for the relevant location. 126If so, that value is returned as the result of the read. 127If not, the current contents of the location are stored in the proposal and 128 then returned as the result of the read. 129A logging write to a location stores the new value as the current contents of 130 the location in the current proposal; the contents of the location itself 131 remain unchanged. 132 133\cvar{Committing} to a proposal verifies that any reads logged in 134 the proposal are still valid and, if so, performs any writes that 135 the proposal contains. 136A logged read is valid if, at the time of the commit, the location contains 137 the same value it had at the time of the original read (note that this does 138 not mean that no change occurred, simply that the value now is the same as 139 the value then). 140If a proposal has an invalid read then the effort to commit fails; no change 141 is made to the value of any location. 142The verifications and subsequent writes to memory are performed atomically 143 with respect to other proposal commit attempts. 144% Explain better? 145 146The \code{queues} structure (with source in \code{scheme/big/queue.scm}) 147 is a thoroughly commented example of a moderately complex data structure 148 made thread-safe using optimistic concurrency. 149 150\begin{protos} 151\proto{call-ensuring-atomicity}{ thunk}{value \ldots} 152\protonoresultnoindex{call-ensuring-atomicity!}{ thunk}\mainschindex{call-ensuring-atomicity"!} 153\syntaxproto{ensure-atomicity}{ \cvar{exp} \ldots}{value \ldots} 154\syntaxprotonoresultnoindex{ensure-atomicity!}{ \cvar{exp} \ldots}\mainschindex{ensure-atomicity"!} 155\end{protos} 156\noindent 157If there is a proposal in place 158 \code{call-ensuring-atomicity} and \code{call-ensuring-atomicity!} 159 simply make a (tail-recursive) call to \cvar{thunk}. 160If the current proposal is \code{\#f} they create a new proposal, 161 install it, call \cvar{thunk}, and then try to commit to the proposal. 162This process repeats, with a new proposal on each iteration, until 163 the commit succeeds. 164\code{Call-ensuring-atomicity} returns whatever values are returned by \cvar{thunk} 165 on its final invocation, while \code{ensure-atomicity!} discards any such 166 values and returns nothing. 167 168\code{Ensure-atomicity} and \code{ensure-atomicity!} are macro versions of 169\code{call-ensuring-atomicity} and \code{call-ensuring-atomicity!}: 170\code{(ensure-atomicity \cvar{exp} \ldots)} expands into 171\code{(call-ensuring-atomicity (lambda () \cvar{exp} \ldots))}; likewise for 172\code{ensure-atomicity!} and \code{call-ensuring-atomicity!}. 173 174\begin{protos} 175\proto{provisional-car}{ pair}{value} 176\proto{provisional-cdr}{ pair}{value} 177\protonoresultnoindex{provisional-set-car!}{ pair value}\mainschindex{provisional-set-car"!} 178\protonoresultnoindex{provisional-set-cdr!}{ pair value}\mainschindex{provisional-set-cdr"!} 179\proto{provisional-cell-ref}{ cell}{value} 180\protonoresultnoindex{provisional-cell-set!}{ cell value}\mainschindex{provisional-cell-set"!} 181\proto{provisional-vector-ref}{ vector i}{value} 182\protonoresultnoindex{provisional-vector-set!}{ vector i value}\mainschindex{provisional-vector-set"!} 183\proto{provisional-string-ref}{ vector i}{char} 184\protonoresultnoindex{provisional-string-set!}{ vector i char}\mainschindex{provisional-string-set"!} 185\proto{provisional-byte-vector-ref}{ vector i}{k} 186\protonoresultnoindex{provisional-byte-vector-set!}{ vector i k}\mainschindex{provisional-byte-vector-set"!} 187\end{protos} 188\noindent 189These are all logging versions of their Scheme counterparts. 190Reads are checked when the current proposal is committed and writes are 191 delayed until the commit succeeds. 192If the current proposal is \code{\#f} these perform exactly as their Scheme 193 counterparts. 194 195The following implementation of a simple counter may not function properly 196 when used by multiple threads. 197\begin{example} 198(define (make-counter) 199 (let ((value 0)) 200 (lambda () 201 (set! value (+ value 1)) 202 value))) 203\end{example} 204 205Here is the same procedure using a proposal to ensure that each 206 increment operation happens atomically. 207The value of the counter is kept in a 208cell (see section~\ref{cells}) 209 to allow the use of 210 logging operations. 211\begin{example} 212(define (make-counter) 213 (let ((value (make-cell 0))) 214 (lambda () 215 (ensure-atomicity 216 (lambda () 217 (let ((v (+ (provisional-cell-ref value) 218 1))) 219 (provisional-cell-set! value v) 220 v)))))) 221\end{example} 222 223Because \code{ensure-atomicity} creates a new proposal only if there is 224 no existing proposal in place, multiple atomic actions can be merged 225 into a single atomic action. 226For example, the following procedure increments an arbitrary number of 227 counters at the same time. 228This works even if the same counter appears multiple times; 229 \code{(step-counters! c0 c0)} would add two to the value of counter \code{c0}. 230\begin{example} 231(define (step-counters! . counters) 232 (ensure-atomicity 233 (lambda () 234 (for-each (lambda (counter) 235 (counter)) 236 counters)))) 237\end{example} 238 239\begin{example} 240(define-synchronized-record-type \cvar{tag} \cvar{type-name} 241 (\cvar{constructor-name} \cvar{field-tag} \ldots) 242 [(\cvar \cvar{field-tag} \ldots)] 243 \cvar{predicate-name} 244 (\cvar{field-tag} \cvar{accessor-name} [\cvar{modifier-name}]) 245 \ldots) 246\end{example} 247This is the same as \code{define-record-type} 248 except all field reads and 249 writes are logged in the current proposal. 250If the optional list of field tags is present then only those fields will 251 be logged. 252 253\begin{protos} 254\proto{call-atomically}{ thunk}{value(s)} 255\protonoresultnoindex{call-atomically!}{ thunk}\mainschindex{call-atomically"!} 256\syntaxproto{atomically}{ \cvar{exp} \ldots}{value(s)} 257\syntaxprotonoresultnoindex{atomically!}{ \cvar{exp} \ldots}\mainschindex{atomically"!} 258\end{protos} 259\noindent 260\code{Call-atomically} and \code{call-atomically!} are identical 261 to \code{call-ensuring-atomicity} and \code{call-ensuring-atomicity!} except that they 262 always install a new proposal before calling \code{thunk}. 263The current proposal is saved and then restored after \code{thunk} returns. 264\code{Call-atomically} and \code{call-atomically!} are useful if \code{thunk} contains 265 code that is not to be combined with any other operation. 266 267\code{Atomically} and \code{atomically!} are macro versions of 268\code{call-atomically} and \code{call-atomically!}: 269\code{(atomically \cvar{exp} \ldots)} expands into 270\code{(call-atomically (lambda () \cvar{exp} \ldots))}; likewise for 271\code{atomically!} and \code{call-atomically!}. 272 273% example? 274 275The following procedures and macro are intended primarily for use in 276 implementing new synchronization primitives or complex thread-safe data 277 structures. 278\begin{protos} 279\syntaxproto{with-new-proposal}{ (\cvar{lose}) \cvar{exp} \ldots}{value \ldots} 280\proto{maybe-commit}{}{boolean} 281\proto{proposal-active?}{}{boolean} 282\protonoresultnoindex{remove-current-proposal!}{}\mainschindex{remove-current-proposal"!} 283\protonoresultnoindex{invalidate-current-proposal!}{}\mainschindex{invalidate-current-proposal"!} 284\end{protos} 285\noindent 286\code{With-new-proposal} saves the current proposal, installs a new one, 287 executes the forms in the body, reinstalls the formerly current proposal, 288 and returns whatever the last body form returned. 289It also binds \cvar{lose} to a thunk repeating the procedure of installing 290 a new procedure and running the body. 291Typically, the body will call \code{maybe-commit} and, if that fails, 292 tail-call \cvar{lose} to try again. 293If \cvar{lose} is called from a non-tail position of the body, the results 294 are unspecified (and probably harmful). 295 296\code{Maybe-commit} verifies that any reads logged in the current proposal are 297 still valid and, if so, performs any writes that it contains. 298A logged read is valid if, at the time of the commit, the location read contains 299 the same value it had at the time of the original read (note that this does 300 not mean that no change occurred, simply that the value now is the same as 301 the value then). 302\code{Maybe-commit} returns \code{\#t} if the commit succeeds and \code{\#f} 303 if it fails. 304 305\code{Proposal-active?} returns \code{\#t} if a proposal is active, and 306 \code{\#f} otherwise. 307\code{Remove-current-proposal!} removes and discards the current proposal; 308 this can be used to clean up before raising an error. 309\code{Invalidate-current-proposal!} ensures that any attempt to commit the 310 current proposal will fail; this can be used if an operation on a 311 thread-safe data structure detects that it has seen the data structure in an 312 inconsistent state. 313 314 315 316The following procedures give access to the low-level proposal 317mechanism. They are defined in the \code{low-proposals} structure. 318\begin{protos} 319\proto{make-proposal}{}{proposal} 320\proto{current-proposal}{}{proposal} 321\protonoresultnoindex{set-current-proposal!}{ proposal}\mainschindex{set-current-proposal"!} 322\end{protos} 323\noindent 324 325\code{Make-proposal} creates a new proposal. 326\code{Current-proposal} and \code{set-current-proposal} access and set 327 the current thread's proposal. 328It is an error to pass to \code{set-current-proposal!} a proposal that 329 is already in use. 330 331 332\section{Condition variables} 333\label{sec:condition-variables} 334% these require proposals 335 336\textit{Condition variables} (defined in the \code{condvars} 337structure) allow threads perform condition synchronization: It allows 338threads to block, waiting for a specified condition---associated with a 339condition variable---to occur, and other threads to wake up the waiting 340threads when the condition is fulfilled. 341 342Note that, in Scheme~48, condition variables work in conjunction with 343proposals, not with mutex locks or semaphores, as in most other 344implementations of this concept. 345 346\begin{protos} 347\proto{make-condvar}{}{condvar} 348\proto{make-condvar}{ id}{condvar} 349\proto{condvar?}{ thing}{boolean} 350\protonoresultnoindex{set-condvar-has-value?!}{ condvar boolean}\mainschindex{set-condvar-has-value?"!} 351\proto{condvar-has-value?}{ condvar}{boolean} 352\protonoresultnoindex{set-condvar-value!}{ condvar value}\mainschindex{set-condvar-value"!} 353\proto{condvar-value}{ condvar}{value} 354\proto{maybe-commit-and-wait-for-condvar}{ condvar}{boolean} 355\protonoindex{maybe-commit-and-set-condvar!}{ condvar value}{boolean}\mainschindex{maybe-commit-and-set-condvar"!} 356\end{protos} 357% 358\code{Make-condvar} creates a condition variable. (The optional 359\cvar{id} argument is only for debugging purposes; the discloser for 360condition variables prints it out if present.) \code{Condvar?} is the 361predicate for condition variables. 362 363Each condition variable has an associated value and a flag 364\code{has-value?} signalling if the condition has already occured. 365The accessor for flag is \code{condvar-has-value?}; 366\code{set-condvar-has-value?!} sets it. Both are provisional 367operations and go through the current proposal. 368\code{Set-condvar-value!} sets the value of the condition variable 369(provisionally), and \code{condvar-value} extracts it. 370 371\code{Maybe-commit-and-wait-for-condvar} attempts to commit the 372current proposal. If the commit succeeds, it suspends the current 373thread and registers it with the \cvar{condvar} condition variable. 374Upon waking up again \code{maybe-commit-and-wait-for-condvar} returns 375\code{\#t}, If the commit fails, \code{maybe-commit-and-set-condvar} 376returns \code{\#f}. 377 378\code{Maybe-commit-and-set-condvar!} sets the value of the 379\cvar{condvar} condition variable to \cvar{value}, (provisionally) 380sets the \code{has-value?} flag to \code{\#t}, and then attempt to 381commit the current proposal. Upon success, it wakes up all suspended 382threads registered with \cvar{condvar} and returns \code{\#t}, 383otherwise, it returns \code{\#f}. 384 385\section{Mutual exclusion} 386 387Scheme~48 also has more traditional mutual-exclusion synchronization 388abstractions, specifically mutex locks and placeholders. Note that 389typically synchronization via optimistic concurrency is usually 390preferable: Mutual exclusion often puts the running program into an 391inconsistent state for the time of the inclusion, which has adverse 392effects on modularity and interruptibility. 393 394\subsection{Locks} 395 396The \code{locks} structure contains bindings that implement standard 397mutex locks: 398% 399\begin{protos} 400\proto{make-lock}{}{lock} 401\proto{lock?}{ thing}{boolean} 402\protonoresult{obtain-lock}{ lock} 403\proto{maybe-obtain-lock}{ lock}{boolean} 404\protonoresult{release-lock}{ lock} 405\end{protos} 406% 407\code{Make-lock} creates a lock in the ``released'' state. 408\code{Lock?} is the predicate for locks. 409 410\code{Obtain-lock} atomically checks if \cvar{lock} is in the 411``released'' state. If it is, the lock is put into the ``obtained'' 412state, and \code{obtain-lock} returns immediately. If the lock is in 413the ``obtained'' state, the current thread is suspended and registered 414with the lock. 415\code{Maybe-obtain-lock}, like \code{obtain-lock}, checks the state of 416\cvar{lock}: if it is ``released,'' the lock is put into the 417``obtained'' state, if it is ``obtained,'' \code{maybe-obtain-lock} 418returns immediately. \code{Maybe-obtain-lock} returns \code{\#t} if 419it was able to obtain the lock, and \code{\#f} otherwise. 420 421\code{Release-lock} does nothing if \cvar{lock} is in the ``released'' 422state. If it is in the ``obtained'' state, \code{release-lock} 423causes one of the threads suspended on an \code{obtain-lock} lock 424operation to continue execution. If that thread is the last thread 425registered with the lock, the lock is transferred to the ``released'' 426state. In any case, \code{release-lock} returns immediately. 427 428\subsection{Placeholders} 429\label{placeholders} 430 431The \code{placeholders} structure contains bindings for 432\textit{placeholders}---thread-safe, write-once variables, akin to 433ID-90 I-structures or CML I-variables. 434 435The typical scenario for placeholders is that, say, a thread~A 436computes a value needed by another thread~B at some unspecified time. 437Both threads share access to a placeholder; when A has computed the 438value, it places it into the placeholder. When B needs the value, it 439extracts it from placeholder, blocking if necessary. 440% 441\begin{protos} 442\proto{make-placeholder}{}{placeholder} 443\proto{make-placeholder}{ id}{placeholder} 444\proto{placeholder?}{ thing}{boolean} 445\protonoresultnoindex{placeholder-set!}{ placeholder value}\mainschindex{placeholder-set"!} 446\proto{placeholder-value}{ placeholder}{value} 447\end{protos} 448% 449\code{Make-placeholder} creates an empty placeholder. (The optional 450\cvar{id} argument is only for debugging purposes; the discloser for 451placeholders prints it out if present.) \code{Placeholder?} is the 452predicate for placeholders. 453 454\code{Placeholder-set!} places a value into a placeholder. Doing this 455more than once signals an error. \code{Placeholder-value} extracts 456the value from the placeholder and returns it. If the placeholder is 457empty, it blocks the current thread until it becomes full. 458 459 460 461\section{Writing custom synchronization abstractions} 462 463The bindings explained in this section are part of the 464\code{threads-internal} structure. They are concerned with suspending 465threads and making them runnable again upon some later event. 466 467Typically, a suspended thread needs to be recorded in a queue 468somewhere for later waking-up. To allow a thread to be recorded in 469multiple queues (say, when it waits for one of a number of events), 470such \textit{thread queues} are ordinary queues containing cells that, 471in turn, contain the thread objects themselves. Each thread has at 472most one such cell associated with it which is shared among all queues 473(or other data structures) holding on to the suspended thread. The 474cell is cleared when the thread is woken up. 475% 476\begin{protos} 477\proto{thread-queue-empty?}{ thread-queue}{boolean} 478\protonoindex{maybe-dequeue-thread!}{ thread-queue}{boolean}\mainschindex{maybe-dequeue-thread"!} 479\end{protos} 480% 481\code{Thread-queue-empty?} atomically checks whether the 482\cvar{thread-queue} thread queue is empty, i.e., if it does not 483contain non-empty cells. \code{Maybe-dequeue-thread!} provisionally 484dequeues a thread from \cvar{thread-queue} if it contains one. It 485returns the dequeued thread or \code{\#f} if the queue is empty. 486% 487\begin{protos} 488\proto{maybe-commit-and-block}{ cell}{boolean} 489\proto{maybe-commit-and-block-on-queue}{ thread-queue}{boolean} 490\proto{maybe-commit-and-make-ready}{ thread-or-queue}{boolean} 491\end{protos} 492% 493\code{Maybe-commit-and-block} attempts to commit the current proposal. 494If this succeeds, the current thread is blocked, the thread's cell is 495set to \cvar{cell}, and \code{\#t} is returned. Otherwise, \code{\#f} 496is returned. \code{Maybe-commit-and-block-on-queue} is like 497\code{maybe-commit-and-block}, excepts that it creates a fresh cell 498for the thread and enqueues it in \cvar{thread-queue} if the commit 499succeeds. 500 501\code{Maybe-commit-and-make-ready} accepts either a thread object or a 502thread queue as an argument. In either case, 503\code{maybe-commit-and-make-ready} tries to commit the current 504proposal. If that succeeds, \code{maybe-commit-and-make-ready} 505makes its argument runnable: if \cvar{thread-or-queue} is a thread, 506that thread is made runnable, if it is a thread queue, all threads on 507the queue are made runnable. (In the latter case, none of the threads 508actually runs until all have been made runnable.) 509\code{Maybe-commit-and-make-ready} returns \code{\#t} if it succeeded, 510and \code{\#f} otherwise. 511 512% \section{Writing your own schedulers} 513 514\section{Concurrent ML abstractions} 515 516The interface to the Concurrent ML abstractions in Scheme~48 is 517mostly analogous to the original implementation shipped with 518SML/NJ~\cite{Reppy:CML-book}. Note that both the interface and 519implementation are new and may change in future releases. 520 521The main terminological difference is that CML events are called 522\textit{rendezvous} in Scheme~48. For more information on programming 523with the CML abstractions, Reppy's book~\cite{Reppy:CML-book} is 524recommended. 525 526\subsection{Basic rendezvous combinators} 527 528The basic rendezvous combinators live in the \code{rendezvous} 529structure. 530% 531\begin{protos} 532\constproto{never-rv}{rendezvous} 533\proto{always-rv}{ value}{rendezvous} 534\end{protos} 535% 536\code{Never-rv} is a rendezvous that is never enabled for 537synchronization. (It is the same as the \code{never} event in CML.) 538\code{Always-rv} returns a rendezvous that is always enabled for 539synchronization, and always yields the same value \cvar{value}. (This 540is the same as the \code{alwaysEvt} function in CML.) 541% 542\begin{protos} 543\proto{choose}{ rendezvous \ldots}{rendezvous} 544\end{protos} 545% 546\code{Choose} creates a rendezvous representing the choice of its 547arguments: Synchronization on the resulting rendezvous will 548synchronize on one of the arguments to \code{choose}, depending on 549which becomes enabled first. (This is the same as the \code{choose} 550function in CML.) 551% 552\begin{protos} 553\proto{wrap}{ rendezvous proc}{rendezvous} 554\end{protos} 555% 556\code{Wrap} wraps a post-synchronization procedure around \cvar{rendezvous}: 557When the resulting rendezvous is synchronized, \cvar{rendezvous} is 558synchronized, and the value it yields is passed to \cvar{proc}; the 559value returned by \cvar{proc} then is the result of the 560synchronization. (This is the same as the CML \code{wrap} function.) 561% 562\begin{protos} 563\proto{guard}{ thunk}{rendezvous} 564\end{protos} 565% 566\code{Guard} delays the creation of a rendezvous until synchronization 567time: It returns a rendezvous that will, upon synchronization, turn 568into the rendezvous returned by \cvar{thunk}. \code{Guard} can be 569used to perform pre-synchronization actions such as resource 570allocation. (This is the same as the CML \code{guard} function.) 571% 572\begin{protos} 573\proto{with-nack}{ proc}{rendezvous} 574\end{protos} 575% 576\code{With-nack}, like \code{guard}, creates a delayed rendezvous: Upon 577synchronization, the rendezvous actually used is the one returned by 578\cvar{proc}. In addition to the functionality offered by 579\code{guard}, \cvar{proc} receives, as an argument, another rendezvous 580which becomes enabled when \emph{another} rendezvous involved in the 581synchronization (via \code{choose}) is picked instead of the one 582produced by \cvar{proc}. (This is the same as the CML \code{withNack} 583function.) 584% 585\begin{protos} 586\proto{sync}{ rendezvous}{value} 587\proto{select}{ rendezvous \ldots}{value} 588\end{protos} 589% 590\code{Sync} synchronizes the current thread on rendezvous 591\cvar{rendezvous}, returning the value it yields. \code{Select} 592synchronizes on the choice of its argument; \code{(select $r_1$ \ldots 593 $r_n$)} is semantically equivalent to \code{(sync (choose select $r_1$ \ldots 594 $r_n$))}, but may be implemented more efficiently. (These are the 595same as the CML functions \code{sync} and \code{select}.) 596 597\subsection{Synchronous channels} 598 599The \code{rendezvous-channels} structure contains abstractions for 600bidirectional, synchronous channels for communicating between two 601threads. 602% 603\begin{protos} 604\proto{make-channel}{}{channel} 605\proto{channel?}{ x}{boolean} 606\end{protos} 607% 608\code{Make-channel} creates a new synchronous channel. (This is the 609same as the CML \code{channel} function.) \code{Channel?} is the 610predicate for synchronous channels. 611% 612\begin{protos} 613\proto{send-rv}{ channel value}{rendezvous} 614\protonoresult{send}{ channel value} 615\end{protos} 616% 617\code{Send-rv} creates a rendezvous that, upon synchronization, sends 618message \cvar{value} on the synchronous channel \cvar{channel}. The 619synchronization suceeds only when another thread attempts to receive a 620message from \cvar{channel}. (This is the same as the CML 621\code{sendEvt} function.) \code{Send} directly sends a message 622\cvar{value} on channel \cvar{channel}; \code{(send $c$ $v$)} is 623equivalent to \code{(sync (send-rv $c$ $v$))}. (\code{Send} is the 624same as the CML \code{send} function.) 625% 626\begin{protos} 627\proto{receive-rv}{ channel}{rendezvous} 628\protonoresult{receive}{ channel} 629\end{protos} 630% 631\code{Receive-rv} creates a rendezvous which, upon synchronization, 632receives a message on channel \cvar{channel}. (This is the same as 633the CML \code{recEvt} function.) \code{Receive} directly 634receives a message on channel \cvar{channel}; \code{(receive $c$ $v$)} is 635equivalent to \code{(sync (receive-rv $c$ $v$))}. (\code{Receive} is 636the same as the CML \code{recv} function.) 637 638\subsection{Synchronous variables} 639 640Two structures contain abstractions for synchronous variables: the 641\code{rendezvous-placeholders} structure for so-called 642\textit{placeholders} (write-once variables), and the 643\code{rendezvous-jars} structure for \textit{jars} (which allow 644multiple updates.) 645 646\subsubsection{Placeholders} 647% 648Placeholders are write-once variables. The placeholders implemented 649by the \code{rendezvous-placeholders} structure offer equivalent 650functionality to the placeholders implemented by the 651\code{placeholders} structure (see Section~\ref{placeholders}), but 652additionally allow converting a placeholder into a rendezvous. Note, 653however, that placeholders from \code{placeholders} are different from 654and not interchangeable with placeholders from 655\code{rendezvous-placeholders}. 656% 657\begin{protos} 658\proto{make-placeholder}{}{placeholder} 659\proto{make-placeholder}{ id}{placeholder} 660\proto{placeholder?}{ x}{boolean} 661\end{protos} 662% 663\code{Make-placeholder} creates an empty placeholder. (The optional 664\cvar{id} argument is only for debugging purposes; the discloser for 665placeholders prints it out if present.) (This is the same as the CML 666\code{iVar} function.) \code{Placeholder?} is the predicate for 667placeholders. 668% 669\begin{protos} 670\protonoresultnoindex{placeholder-set!}{ placeholder value}\mainschindex{placeholder-set"!} 671\end{protos} 672% 673\code{Placeholder-set!} places a value into a placeholder. Doing this 674more than once signals an error. (This is the same as the CML 675\code{iPut} function.) 676% 677\begin{protos} 678\proto{placeholder-value-rv}{ placeholder}{rendezvous} 679\proto{placeholder-value}{ placeholder}{value} 680\end{protos} 681% 682\code{Placeholder-value} extracts the value from the placeholder and 683returns it. If the placeholder is empty, it blocks the current thread 684until it becomes full. (This is the same as the CML \code{iGet} 685function.) \code{Placeholder-value-rv} creates a rendezvous that 686will, upon synchronization, extract the value from the placeholder 687and yield it as a result. (This is the same as the CML \code{iGetEvt} 688function.) 689 690\subsubsection{Jars} 691 692A jar is a synchronous variable which can have two states: full and 693empty. It becomes full when a value it put into it; putting a value 694into a full jar is an error. Conversely, it becomes empty when a 695value is taken out of it. Trying to take a value out of an empty jar 696blocks until it becomes full. (Jars are similar to ID-90 697M-structures.) Jars live in the \code{rendezvous-jars} structure. 698% 699\begin{protos} 700\proto{make-jar}{}{jar} 701\proto{make-jar}{ id}{jar} 702\proto{jar?}{ x}{boolean} 703\end{protos} 704% 705\code{Make-jar} creates an empty jar. (The optional \cvar{id} 706argument is only for debugging purposes; the discloser for jars prints 707it out if present.) (This is the same as the CML \code{mVar} 708function.) \code{Jar?} is the predicate for jars. 709 710\begin{protos} 711\protonoresultnoindex{jar-put!}{ jar value}\mainschindex{jar-put"!} 712\end{protos} 713% 714\code{Jar-put!} places a value into a jar if it is empty. Applying 715\code{jar-put!} to a full jar is an error. (This is the same as the 716CML \code{mPut} function.) 717% 718\begin{protos} 719\proto{jar-take-rv}{ placeholder}{rendezvous} 720\proto{jar-take}{ placeholder}{value} 721\end{protos} 722% 723\code{Jar-take} takes a value from a full jar, emptying it in the 724process. If the jar is empty, \code{jar-take} blocks until it becomes 725full. (This is the same as the CML \code{mTake} function.) 726\code{Jar-take-rv} creates a rendezvous that, upon synchronization, 727will extract the value from a jar and empty it in the process. (This 728is the same as the CML \code{mTakeEvt} function.) 729 730\subsection{Timeouts} 731 732The \code{rendezvous-time} structure allows creating rendezvous for 733alarms and timeouts: 734% 735\begin{protos} 736\proto{after-time-rv}{ milliseconds}{rendezvous} 737\proto{at-real-time-rv}{ time}{rendezvous} 738\end{protos} 739% 740\code{After-time-rv} creates a rendezvous that becomes enabled at time 741interval \cvar{milliseconds} after synchronization. (Actually, 742\cvar{milliseconds} is a minimum waiting time; the actual delay may be 743longer.) (This is the same as the CML \code{timeOutEvt} function.) 744\code{At-real-time-rv} creates a rendezvous that becomes enabled at an 745absolute time specified by \cvar{time}; this absolute time is 746specified in the same way as the return value \code{real-time} from 747the \code{time} structure. (This is the same as the CML 748\code{atTimeEvt} function.) 749 750\subsection{CML to Scheme correspondence} 751 752The following table lists the Scheme names that correspond to 753particular CML names. 754 755\texonly\begin{longtable}{ll}\endtexonly 756\htmlonly\begin{tabular}{ll}\endhtmlonly 757 CML name & Scheme name\\\hline 758 \multicolumn{2}{c}{\code{rendezvous}}\\ 759 \code{never} & \code{never-rv}\\ 760 \code{alwaysEvt} & \code{always-rv}\\ 761 \code{choose} & \code{choose}\\ 762 \code{wrap} & \code{wrap}\\ 763 \code{guard} & \code{guard}\\ 764 \code{withNack} & \code{with-nack}\\ 765 \code{sync} & \code{sync}\\ 766 \code{select} & \code{select}\\[1ex] 767 \multicolumn{2}{c}{\code{rendezvous-channels}}\\ 768 \code{channel} & \code{make-channel}\\ 769 \code{sendEvt} & \code{send-rv}\\ 770 \code{send} & \code{send}\\ 771 \code{recEvt} & \code{receive-rv}\\ 772 \code{rec} & \code{receive}\\[1ex] 773 \multicolumn{2}{c}{\code{rendezvous-placeholders}}\\ 774 \code{iVar} & \code{make-placeholder}\\ 775 \code{iPut} & \code{placeholder-set!}\\ 776 \code{iGet} & \code{placeholder-value}\\ 777 \code{iGetEvt} & \code{placeholder-value-rv}\\[1ex] 778 \multicolumn{2}{c}{\code{rendezvous-jars}}\\ 779 \code{mVar} & \code{make-jar}\\ 780 \code{mTake} & \code{jar-take}\\ 781 \code{mTakeEvt} & \code{jar-take-rv}\\ 782 \code{mPut} & \code{jar-put!}\\[1ex] 783 \multicolumn{2}{c}{\code{rendezvous-time}}\\ 784 \code{timeOutEvt} & \code{after-time-rv}\\ 785 \code{atTimeEvt} & \code{at-real-time-rv} 786\texonly\end{longtable}\endtexonly 787\htmlonly\end{tabular}\endhtmlonly 788 789 790%%% Local Variables: 791%%% mode: latex 792%%% TeX-master: "manual" 793%%% End: 794