Added initial documentation for threads. Most of this is just like

Scheme 48's doc/threads.txt.
This commit is contained in:
mainzelm 2001-07-13 07:12:36 +00:00
parent 0af8a890a8
commit 70198b58f2
2 changed files with 159 additions and 0 deletions

View File

@ -47,6 +47,7 @@
\include{sre} \include{sre}
\include{rdelim} \include{rdelim}
\include{awk} \include{awk}
\include{threads}
\include{miscprocs} \include{miscprocs}
\include{running} \include{running}
\include{todo} \include{todo}

158
doc/scsh-manual/threads.tex Normal file
View File

@ -0,0 +1,158 @@
%latex -*- latex -*-
\chapter{Concurrent system programming}
The Scheme Shell provides you with support for concurrent programming.
Its interface for concurrent programming consists of several parts:
\begin{itemize}
\item The thread system
\item Synchronization vehicles
\item Process state abstractions
\end{itemize}
Whereas the user deals with threads and synchronization explicitly, the
process state abstractions are built into the rest of the system
transparent for the user. Section \ref{sec:ps_interac} describes the
interaction between process state and threads.
\section{Threads}
A thread can be thought of as a procedure that can run independently of
and concurrent to the rest of the system. The calling procedure fires
the thread up and forgets about it.
The current thread interface is completely taken from Scheme\ 48. This
documentation is an extension of the file \texttt{doc/threads.txt}.
The thread package is named \texttt{threads}, it has to be opened explicitly.
\defun {spawn} {thunk [name]} \undefined
Create and schedule a new thread that will execute \var{thunk}, a
procedure with no arguments. Note that Scsh's \ex{spawn} does
\textbf{not} return a reference to a thread object. The optional
argument \var{name} is used when printing the thread.
\defun {relinquish-timeslice} {} \undefined
Let other threads run for a while.
\defun {sleep} {time} \undefined
Puts the current thread into sleep for \var{time} milliseconds. The
time at which the thread is run again may be longer of course.
\defun {terminate-current-thread} {} {does-not-return}
Kill the current thread.
Mainly for debugging purposes, there is also an interface to the
internal representation of thread objects:
\defun {current-thread} {} {thread-object}
Return the object to which the current thread internally corresponds.
Note that this procedure is exported by the package
\texttt{threads-internal} only.
\defun {thread?} {thing} {\boolean}
Returns true iff \var{thing} is a thread object.
\defun {thread-name} {thread} {name}
\var{Name} corresponds to the second parameter that was given to
\ex{spawn} when \var{thread} was created.
\defun{thread-uid} {thread} {\integer}
Returns a unique identifier for the current thread.
\section{Locks}
Locks are a simple mean for mutual exclusion. They implement a concept
commonly known as \textit{semaphores}. Threads can obtain and release
locks. If a thread tries to obtain a lock which is held by another
thread, the first thread is blocked.
\defun{make-lock} {} {lock}
Creates a lock.
\defun{lock?} {thing} {\boolean}
Returns true iff \var{thing} is a lock.
\defun{obtain-lock} {lock} {\undefined}
Obtain \var{lock}. Causes the thread to block if the lock is held by
another thread.
\defun{maybe-obtain-lock} {lock} {\boolean}
Tries to obtain \var{lock}, but returns false if the lock cannot be
obtained.
\defun{release-lock} {lock} {\boolean}
Releases \var{lock}. Returns true if the lock immediately got a new
owner, false otherwise.
\defun{lock-owner-uid} {lock} {\integer}
Returns the uid of the thread that currently holds \var{lock} or false
if the lock is free.
\section{Placeholders}
Placeholers combine synchronization with value delivery. They can be
thought of as special variables. After creation the value of the
placeholder is undefined. If a thread tries to read the placeholders
value this thread is blocked. Multiple threads are allowed to block on
a single placeholder. They will continue running after another thread
sets the value of the placeholder. Now all reading threads receive the
value and continue executing. Setting a placeholder to two different
values causes an error.
\defun {make-placeholder} {} {placeholder}
Creates a new placeholder.
\defun {placeholder?} {thing} {\boolean}
Returns true iff \var{thing} is a placeholder.
\defun {placeholder-set!} {placeholder value} {\undefined}
Sets the placeholders value to \var{value}. If the placeholder is
already set to a \textit{different} value an exception is risen.
\defun {placeholder-value} {placeholder} {value}
Returns the value of the placeholder. If the placeholder is yet unset,
the current thread is blocked until another thread sets the value by
means of \ex{placeholder-set!}.
\section{Interaction between threads and process state}
\label{sec:ps_interac}
Global process state is a bad thing: it undermines modularity. In the
case of concurrency however things get even worse. The simplest
example for this it the current working directory. If this is global
state, no thread can ever reliably dereference a relative link.
Scsh addresses the problem of process state in a uniform way for
almost all resources. For every global resource there is a
procedure \ex{with-}\textit{resource}\ex{*} \var{thunk} which guarantees that
during the execution of \var{thunk} the resource is
set to the desired value. There is only one exception: The uid under
which the current process is running. The superuser may change to an
arbitrary user without being prompted for a password, but the way back
is blocked.