diff --git a/doc/scsh-manual/man.tex b/doc/scsh-manual/man.tex index aa5418b..4083a2e 100644 --- a/doc/scsh-manual/man.tex +++ b/doc/scsh-manual/man.tex @@ -47,6 +47,7 @@ \include{sre} \include{rdelim} \include{awk} +\include{threads} \include{miscprocs} \include{running} \include{todo} diff --git a/doc/scsh-manual/threads.tex b/doc/scsh-manual/threads.tex new file mode 100644 index 0000000..e4abde1 --- /dev/null +++ b/doc/scsh-manual/threads.tex @@ -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. + + + + + + + +