📄 sync-var.tex
字号:
\maybeclearpage\section{The {\cf Sync\-Var} structure}The {\cf \small Sync\-Var}\marginref{SyncVar}{str-SyncVar}{strSyncVar} structure provides \textbf{Id}-style synchronous variables (or memory cells). These variables have two states: \textit{empty} and \textit{full}. An attempt to read a value from an empty variable blocks the calling thread until there is a value available. An attempt to put a value into a variable that is full results in the {\cf \small Put}\marginref{Put}{exn-SYNC_VAR.Put}{exnSYNCVARPut} exception being raised. There are two kinds of synchronous variables: I-variables are write-once, while M-variables are mutable. \begin{synopsis}\item {\kw{signature}} \textcf{SYNC\_\linebreak[0]VAR}\label{sig-SYNC_VAR}\item {\STRUCTURE} \textcf{SyncVar: SYNC\_\linebreak[0]VAR}\label{str-SyncVar}\end{synopsis}\begin{interface}\Nopagebreak\item {\index{Put@Put!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{exception}} \textcf{Put}\Nopagebreak\item {\index{ivar@ivar!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{type}} \(\alpha\)~\textcf{ivar}\Nopagebreak\item {\index{iVar@iVar!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{val}} {\cf iVar: \(\mbox{\cf{}unit}\rightarrow \alpha\mtoksep{}\mbox{\cf{}ivar}\)}\Nopagebreak\item {\index{iPut@iPut!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{val}} {\cf iPut: \((\alpha\mtoksep{}\mbox{\cf{}ivar}\mtoksep{}\verb,*,\mtoksep{}\alpha)\rightarrow \mbox{\cf{}unit}\)}\Nopagebreak\item {\index{iGet@iGet!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{val}} {\cf iGet: \(\alpha\mtoksep{}\mbox{\cf{}ivar}\rightarrow \alpha\)}\Nopagebreak\item {\index{iGetEvt@iGetEvt!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{val}} {\cf iGetEvt: \(\alpha\mtoksep{}\mbox{\cf{}ivar}\rightarrow \alpha\mtoksep{}\mbox{\cf{}event}\)}\Nopagebreak\item {\index{iGetPoll@iGetPoll!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{val}} {\cf iGetPoll: \(\alpha\mtoksep{}\mbox{\cf{}ivar}\rightarrow \alpha\mtoksep{}\mbox{\cf{}option}\)}\Nopagebreak\item {\index{sameIVar@sameIVar!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{val}} {\cf sameIVar: \((\alpha\mtoksep{}\mbox{\cf{}ivar}\mtoksep{}\verb,*,\mtoksep{}\alpha\mtoksep{}\mbox{\cf{}ivar})\rightarrow \mbox{\cf{}bool}\)}\Nopagebreak\item {\index{mvar@mvar!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{type}} \(\alpha\)~\textcf{mvar}\Nopagebreak\item {\index{mVar@mVar!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{val}} {\cf mVar: \(\mbox{\cf{}unit}\rightarrow \alpha\mtoksep{}\mbox{\cf{}mvar}\)}\Nopagebreak\item {\index{mVarInit@mVarInit!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{val}} {\cf mVarInit: \(\alpha\rightarrow \alpha\mtoksep{}\mbox{\cf{}mvar}\)}\Nopagebreak\item {\index{mPut@mPut!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{val}} {\cf mPut: \((\alpha\mtoksep{}\mbox{\cf{}mvar}\mtoksep{}\verb,*,\mtoksep{}\alpha)\rightarrow \mbox{\cf{}unit}\)}\Nopagebreak\item {\index{mTake@mTake!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{val}} {\cf mTake: \(\alpha\mtoksep{}\mbox{\cf{}mvar}\rightarrow \alpha\)}\Nopagebreak\item {\index{mTakeEvt@mTakeEvt!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{val}} {\cf mTakeEvt: \(\alpha\mtoksep{}\mbox{\cf{}mvar}\rightarrow \alpha\mtoksep{}\mbox{\cf{}event}\)}\Nopagebreak\item {\index{mGet@mGet!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{val}} {\cf mGet: \(\alpha\mtoksep{}\mbox{\cf{}mvar}\rightarrow \alpha\)}\Nopagebreak\item {\index{mGetEvt@mGetEvt!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{val}} {\cf mGetEvt: \(\alpha\mtoksep{}\mbox{\cf{}mvar}\rightarrow \alpha\mtoksep{}\mbox{\cf{}event}\)}\Nopagebreak\item {\index{mTakePoll@mTakePoll!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{val}} {\cf mTakePoll: \(\alpha\mtoksep{}\mbox{\cf{}mvar}\rightarrow \alpha\mtoksep{}\mbox{\cf{}option}\)}\item {\index{mGetPoll@mGetPoll!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{val}} {\cf mGetPoll: \(\alpha\mtoksep{}\mbox{\cf{}mvar}\rightarrow \alpha\mtoksep{}\mbox{\cf{}option}\)}\Nopagebreak\item {\index{mSwap@mSwap!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{val}} {\cf mSwap: \((\alpha\mtoksep{}\mbox{\cf{}mvar}\mtoksep{}\verb,*,\mtoksep{}\alpha)\rightarrow \alpha\)}\Nopagebreak\item {\index{mSwapEvt@mSwapEvt!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{val}} {\cf mSwapEvt: \((\alpha\mtoksep{}\mbox{\cf{}mvar}\mtoksep{}\verb,*,\mtoksep{}\alpha)\rightarrow \alpha\mtoksep{}\mbox{\cf{}event}\)}\Nopagebreak\item {\index{sameMVar@sameMVar!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{val}} {\cf sameMVar: \((\alpha\mtoksep{}\mbox{\cf{}mvar}\mtoksep{}\verb,*,\mtoksep{}\alpha\mtoksep{}\mbox{\cf{}mvar})\rightarrow \mbox{\cf{}bool}\)}\end{interface}\begin{descr}\item {\index{Put@Put!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{exception}} \textcf{Put}\label{exn-SYNC_VAR.Put}\begin{speccomment}\item This exception is raised when an attempt is made to put a value into a value that is already full (see {\cf \small i\-Put} and {\cf \small m\-Put}). \end{speccomment}\item {\index{ivar@ivar!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{type}} \(\alpha\)~\textcf{ivar}\label{ty-SYNC_VAR.ivar}\begin{speccomment}\item This is the type constructor for I-structured variables. I-structured variables are write-once variables that provide synchronization on read operations. They are especially useful for one-shot communications, such as reply messages in client/server protocols. \end{speccomment}\item {\index{iVar@iVar!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{val}} {\cf iVar: \(\mbox{\cf{}unit}\rightarrow \alpha\mtoksep{}\mbox{\cf{}ivar}\)}\label{val-SYNC_VAR.iVar}\begin{speccomment}\item {\cf \small i\-Var () } creates a new empty I-variable. \end{speccomment}\item {\index{iPut@iPut!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{val}} {\cf iPut: \((\alpha\mtoksep{}\mbox{\cf{}ivar}\mtoksep{}\verb,*,\mtoksep{}\alpha)\rightarrow \mbox{\cf{}unit}\)}\label{val-SYNC_VAR.iPut}\linebreak[3]\hspace*{\fill}\mbox{~~~~\textrm{raises}~{\cf Put}}\begin{speccomment}\item {\cf \small i\-Put (\mbox{\cf \small \textit{iv}}, \mbox{\cf \small \textit{x}}) } fills the I-variable \mbox{\cf \small \textit{iv}} with the value \mbox{\cf \small \textit{x}}. Any threads that are blocked on \mbox{\cf \small \textit{iv}} will be resumed. If \mbox{\cf \small \textit{iv}} already has a value in it, then the {\cf \small Put} exception is raised. \end{speccomment}\item {\index{iGet@iGet!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{val}} {\cf iGet: \(\alpha\mtoksep{}\mbox{\cf{}ivar}\rightarrow \alpha\)}\label{val-SYNC_VAR.iGet}\begin{speccomment}\item {\cf \small i\-Get \mbox{\cf \small \textit{iv}} } returns the contents of the I-variable \mbox{\cf \small \textit{iv}}. If the variable is empty, then the calling thread blocks until the variable becomes full. \end{speccomment}\item {\index{iGetEvt@iGetEvt!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{val}} {\cf iGetEvt: \(\alpha\mtoksep{}\mbox{\cf{}ivar}\rightarrow \alpha\mtoksep{}\mbox{\cf{}event}\)}\label{val-SYNC_VAR.iGetEvt}\begin{speccomment}\item {\cf \small i\-Get\-Evt \mbox{\cf \small \textit{iv}} } returns an event-value that represents the {\cf \small i\-Get} operation on \mbox{\cf \small \textit{iv}}. \end{speccomment}\item {\index{iGetPoll@iGetPoll!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{val}} {\cf iGetPoll: \(\alpha\mtoksep{}\mbox{\cf{}ivar}\rightarrow \alpha\mtoksep{}\mbox{\cf{}option}\)}\label{val-SYNC_VAR.iGetPoll}\begin{speccomment}\item This is a non-blocking version of {\cf \small i\-Get}. If the corresponding blocking form would block, then it returns {\cf \small NONE}; otherwise it returns {\cf \small SOME} of the variable's contents. \end{speccomment}\item {\index{sameIVar@sameIVar!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{val}} {\cf sameIVar: \((\alpha\mtoksep{}\mbox{\cf{}ivar}\mtoksep{}\verb,*,\mtoksep{}\alpha\mtoksep{}\mbox{\cf{}ivar})\rightarrow \mbox{\cf{}bool}\)}\label{val-SYNC_VAR.sameIVar}\begin{speccomment}\item {\cf \small same\-IVar (\mbox{\cf \small \textit{iv1}}, \mbox{\cf \small \textit{iv2}}) } returns {\cf \small true}, if the \mbox{\cf \small \textit{iv1}} and \mbox{\cf \small \textit{iv2}} are the same I-variable. \end{speccomment}\item {\index{mvar@mvar!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{type}} \(\alpha\)~\textcf{mvar}\label{ty-SYNC_VAR.mvar}\begin{speccomment}\item This is the type constructor for M-structured variables. Unlike {\cf \small ivar} values, M-structured variables may be updated multiple times. Like I-variables, however, they may only be written if they are empty. \end{speccomment}\item {\index{mVar@mVar!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{val}} {\cf mVar: \(\mbox{\cf{}unit}\rightarrow \alpha\mtoksep{}\mbox{\cf{}mvar}\)}\label{val-SYNC_VAR.mVar}\begin{speccomment}\item {\cf \small m\-Var () } creates a new empty M-variable. \end{speccomment}\item {\index{mVarInit@mVarInit!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{val}} {\cf mVarInit: \(\alpha\rightarrow \alpha\mtoksep{}\mbox{\cf{}mvar}\)}\label{val-SYNC_VAR.mVarInit}\begin{speccomment}\item {\cf \small m\-Var x } creates a new M-variable initialized to \mbox{\cf \small \textit{x}}. \end{speccomment}\item {\index{mPut@mPut!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{val}} {\cf mPut: \((\alpha\mtoksep{}\mbox{\cf{}mvar}\mtoksep{}\verb,*,\mtoksep{}\alpha)\rightarrow \mbox{\cf{}unit}\)}\label{val-SYNC_VAR.mPut}\linebreak[3]\hspace*{\fill}\mbox{~~~~\textrm{raises}~{\cf Put}}\begin{speccomment}\item {\cf \small m\-Put (\mbox{\cf \small \textit{mv}}, \mbox{\cf \small \textit{x}}) } fills the M-variable \mbox{\cf \small \textit{mv}} with the value \mbox{\cf \small \textit{x}}. Any threads that are blocked on \mbox{\cf \small \textit{mv}} will be resumed. If \mbox{\cf \small \textit{mv}} already has a value in it, then the {\cf \small Put} exception is raised. \end{speccomment}\item {\index{mTake@mTake!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{val}} {\cf mTake: \(\alpha\mtoksep{}\mbox{\cf{}mvar}\rightarrow \alpha\)}\label{val-SYNC_VAR.mTake}\begin{speccomment}\item {\cf \small m\-Take \mbox{\cf \small \textit{mv}} } removes and returns the contents of the M-variable \mbox{\cf \small \textit{mv}} making it empty. If the variable is already empty, then the calling thread is blocked until a value is available. \end{speccomment}\item {\index{mTakeEvt@mTakeEvt!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{val}} {\cf mTakeEvt: \(\alpha\mtoksep{}\mbox{\cf{}mvar}\rightarrow \alpha\mtoksep{}\mbox{\cf{}event}\)}\label{val-SYNC_VAR.mTakeEvt}\begin{speccomment}\item {\cf \small m\-Take\-Evt \mbox{\cf \small \textit{mv}} } returns an event-value that represents the {\cf \small m\-Take} operation on \mbox{\cf \small \textit{mv}}. \end{speccomment}\item {\index{mGet@mGet!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{val}} {\cf mGet: \(\alpha\mtoksep{}\mbox{\cf{}mvar}\rightarrow \alpha\)}\label{val-SYNC_VAR.mGet}\begin{speccomment}\item {\cf \small m\-Get \mbox{\cf \small \textit{mv}} } returns the contents of the M-variable \mbox{\cf \small \textit{mv}} without emptying the variable; if the variable is empty, then the thread blocks until a value is available. It is equivalent to the code: \begin{code}let val x = mTake \mbox{\cf \small \textit{mv}} in mPut(\mbox{\cf \small \textit{mv}}, x); x end \end{code} \end{speccomment}\item {\index{mGetEvt@mGetEvt!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{val}} {\cf mGetEvt: \(\alpha\mtoksep{}\mbox{\cf{}mvar}\rightarrow \alpha\mtoksep{}\mbox{\cf{}event}\)}\label{val-SYNC_VAR.mGetEvt}\begin{speccomment}\item {\cf \small m\-Get\-Evt \mbox{\cf \small \textit{mv}} } returns an event-value that represents the {\cf \small m\-Get} operation on \mbox{\cf \small \textit{mv}}. \end{speccomment}\item {\index{mTakePoll@mTakePoll!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{val}} {\cf mTakePoll: \(\alpha\mtoksep{}\mbox{\cf{}mvar}\rightarrow \alpha\mtoksep{}\mbox{\cf{}option}\)}\label{val-SYNC_VAR.mTakePoll}\item {\index{mGetPoll@mGetPoll!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{val}} {\cf mGetPoll: \(\alpha\mtoksep{}\mbox{\cf{}mvar}\rightarrow \alpha\mtoksep{}\mbox{\cf{}option}\)}\label{val-SYNC_VAR.mGetPoll}\begin{speccomment}\item These are non-blocking versions of {\cf \small m\-Take} and {\cf \small m\-Get} (respectively). If the corresponding blocking form would block, then they return {\cf \small NONE}; otherwise they return {\cf \small SOME} of the variable's contents. \end{speccomment}\item {\index{mSwap@mSwap!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{val}} {\cf mSwap: \((\alpha\mtoksep{}\mbox{\cf{}mvar}\mtoksep{}\verb,*,\mtoksep{}\alpha)\rightarrow \alpha\)}\label{val-SYNC_VAR.mSwap}\begin{speccomment}\item {\cf \small m\-Swap (\mbox{\cf \small \textit{mv}}, \mbox{\cf \small \textit{new\-V}}) } puts the value \mbox{\cf \small \textit{new\-V}} into the M-variable \mbox{\cf \small \textit{mv}} and returns the previous contents. If the variable is empty, then the thread blocks until a value is available. It is equivalent to the code: \begin{code}let val x = mTake \mbox{\cf \small \textit{mv}} in mPut(\mbox{\cf \small \textit{mv}}, \mbox{\cf \small \textit{new\-V}}); x end \end{code} except that {\cf \small m\-Swap} is executed atomically. \end{speccomment}\item {\index{mSwapEvt@mSwapEvt!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{val}} {\cf mSwapEvt: \((\alpha\mtoksep{}\mbox{\cf{}mvar}\mtoksep{}\verb,*,\mtoksep{}\alpha)\rightarrow \alpha\mtoksep{}\mbox{\cf{}event}\)}\label{val-SYNC_VAR.mSwapEvt}\begin{speccomment}\item {\cf \small m\-Swap\-Evt \mbox{\cf \small \textit{mv}} } returns an event-value that represents the {\cf \small m\-Swap} operation on \mbox{\cf \small \textit{mv}} and \mbox{\cf \small \textit{new\-V}}. \end{speccomment}\item {\index{sameMVar@sameMVar!SYNC_VAR@\textcf{SYNC\_\linebreak[0]VAR}}}{\kw{val}} {\cf sameMVar: \((\alpha\mtoksep{}\mbox{\cf{}mvar}\mtoksep{}\verb,*,\mtoksep{}\alpha\mtoksep{}\mbox{\cf{}mvar})\rightarrow \mbox{\cf{}bool}\)}\label{val-SYNC_VAR.sameMVar}\begin{speccomment}\item {\cf \small same\-MVar (\mbox{\cf \small \textit{mv1}}, \mbox{\cf \small \textit{mv2}}) } returns {\cf \small true}, if \mbox{\cf \small \textit{mv1}} and \mbox{\cf \small \textit{mv2}} are the same M-variable. \end{speccomment}\end{descr}I-variables provide a useful mechanism for implementing the reply communication in request/reply protocols. They may also be used to implement incremental data structures and streams.A disciplined use of M-variables can provide an atomic read-modify-write operation.\begin{seealso}{\cf CML} (\pageref{str-CML})\end{seealso}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -