From 432d1916fb34e42708252c601d77af05842eb1d9 Mon Sep 17 00:00:00 2001 From: Mart Lubbers Date: Sun, 2 Jul 2017 22:17:58 +0200 Subject: [PATCH] add factorial example' --- arch.communication.tex | 50 +++++++++++++++++++++------------- arch.example.tex | 62 +++++++++++++++++++++++++++++++++++++++++- arch.lift.tex | 14 ---------- arch.tex | 4 --- 4 files changed, 92 insertions(+), 38 deletions(-) delete mode 100644 arch.lift.tex diff --git a/arch.communication.tex b/arch.communication.tex index 9082fd5..2472ab7 100644 --- a/arch.communication.tex +++ b/arch.communication.tex @@ -53,26 +53,38 @@ brevity. \subsection{Add a device} A device can be added by filling in the \CI{MTaskDevice} record as much as -possible and running the \CI{connectDevice} function. This function grabs the -channels, starts the synchronization \gls{Task} (\CI{synFun}), makes sure the -errors are handled when needed and runs a processing function in parallel to -react on the incoming messages. Moreover, it sends a specification request to -the device in question to determine the details of the device and updates the -record to contain the top-level \gls{Task}-id. All device functionality -heavily depends on the specific \CI{deviceShare} function that generates an -\gls{SDS} for a specific device. This allows giving an old device record to the -function and still update the latest instance. Listing~\ref{lst:connectDevice} -shows the connection function. +possible and running the \CI{connectDevice} function. This function grabs and +clears the channels, starts the synchronization \gls{Task} (\CI{synFun}), makes +sure the errors are handled when needed and runs a processing function in +parallel to react on the incoming messages. Moreover, it sends a specification +request to the device in question to determine the details of the device and +updates the record to contain the top-level \gls{Task}-id. All device +functionality heavily depends on the specific \CI{deviceShare} function that +generates an \gls{SDS} for a specific device. This allows giving an old device +record to the function and still update the latest instance. +Listing~\ref{lst:connectDevice} shows the connection function. \begin{lstlisting}[label={lst:connectDevice},% caption={Connect a device}] -connectDevice :: (MTaskDevice (Shared Channels) -> Task ()) MTaskDevice -> Task Channels -connectDevice procFun device = set ([], [], False) ch - >>| appendTopLevelTask 'DM'.newMap True - ( procFun device ch -||- catchAll (getSynFun device.deviceData ch) errHdl) - >>= \tid->upd (\d->{d&deviceTask=Just tid,deviceError=Nothing}) (deviceShare device) - >>| set (r,[MTSpec],ss) ch - >>| treturn device +process :: MTaskDevice (Shared Channels) -> Task () +process device ch = forever $ wait "process" (not o isEmpty o fst3) ch + >>= \(r,s,ss)->upd (appFst3 (const [])) ch >>| proc r +where + proc :: [MTaskMSGRecv] -> Task () + proc [] = treturn () + proc [m:ms] = (case m of + MTPub i val = updateShareFromPublish device i val @! () + ... + MTDevSpec s = deviceAddSpec device s @! () + ) >>| proc ms + +connectDevice :: MTaskDevice -> Task Channels +connectDevice device = set ([], [], False) ch + >>| appendTopLevelTask 'DM'.newMap True + ( process device ch -||- catchAll (getSynFun device.deviceData ch) errHdl) + >>= \tid->upd (\d->{d&deviceTask=Just tid,deviceError=Nothing}) (deviceShare device) + >>| set (r,[MTSpec],ss) ch + >>| treturn device where errHdl e = upd (\d->{d & deviceTask=Nothing, deviceError=Just e}) (deviceShare device) @! () ch = channels device @@ -132,7 +144,7 @@ makeTask name ident = get currentDateTime @ \dt->{MTaskTask | name=name, ident=i makeShare :: String Int BCValue -> MTaskShare makeShare withTask identifier value = {MTaskShare | withTask=[withTask], identifier=identifier, value=value} -sendTaskToDevice :: String (Main (ByteCode a Stmt)) (MTaskDevice, MTaskInterval) -> Task MTaskTask +sendTaskToDevice :: String (Main (ByteCode a Stmt)) (MTaskDevice, MTaskInterval) -> Task (MTaskTask, [MTaskShare]) sendTaskToDevice wta mTask (device, timeout) # (msgs, newState=:{sdss}) = toMessages timeout mTask device.deviceState # shares = [makeShare wta "" sdsi sdsval\\{sdsi,sdsval}<-sdss, (MTSds sdsi` _)<-msgs | sdsi == sdsi`] @@ -141,7 +153,7 @@ sendTaskToDevice wta mTask (device, timeout) >>| makeTask wta -1 >>= \t->upd (addTaskUpState newState t) (deviceShare device) >>| wait "Waiting for task to be acked" (taskAcked t) (deviceShare device) - >>| treturn t + >>| treturn (t, shares) where addTaskUpState :: BCState MTaskTask MTaskDevice -> MTaskDevice addTaskUpState st task device = {MTaskDevice | device & deviceState=st, deviceTasks=[task:device.deviceTasks]} diff --git a/arch.example.tex b/arch.example.tex index 4b4f48e..db9a2a7 100644 --- a/arch.example.tex +++ b/arch.example.tex @@ -1 +1,61 @@ -Here comes a description of the demo program. +\subsection{Framework} +Systems built with support for \gls{mTask} are often following the same design +pattern. First the devices are created --- with or without the interaction of +the user --- and they are then connected. When all devices are registered, the +\gls{mTask}-\glspl{Task} can be sent and \gls{iTasks}-\glspl{Task} can be +started to monitor the output. When everything is finished, the devices are +removed and the system is powered off. + +\begin{lstlisting}[language=Clean,label={lst:framework}, + caption={\gls{mTask} framework for building applications}] +w :: Task () +w = makeDevice "dev1" (...) >>= connectDevice + >>= \dev1->makeDevice "dev2" (...) >>= connectDevice + >>= \dev2->... + ... + >>* [OnAction (Action "Shutdown") $ always + $ deleteDevice dev1 + >>| deleteDevice dev2 + >>| ... + >>| shutDown 0 + ] +\end{lstlisting} + +\subsection{Thermostat} +The thermostat is a classic example program for showing interactions between +peripherals. The following program shows a system containing two devices. One +device is connected via \gls{TCP} and contains a temperature sensor. The second + +\subsection[Lifting mTasks to iTasks-Tasks]% + {Lifting \gls{mTask}-\glspl{Task} to \gls{iTasks}-\glspl{Task}} +If the user does not want to know where and when a \gls{mTask} is actually +executed and is just interested in the results it can lift the \gls{mTask} to +an \gls{iTasks}-\gls{Task}. The function is called with a name, \gls{mTask}, +device and interval specification and it will return a \gls{Task} that finishes +if and only if the \gls{mTask} has returned. + +\begin{lstlisting}[caption={Starting up the devices}] +liftmTask :: String (Main (ByteCode () Stmt)) (MTaskDevice, MTaskInterval) -> Task [MTaskShare] +liftmTask wta mTask c=:(dev, _)= sendTaskToDevice wta mTask c + >>= \(t, shs)->wait "Waiting for mTask to return" (taskRemoved t) (deviceShare dev) + >>| viewInformation "Done!" [] () + >>| treturn shs +where + taskRemoved t d = isNothing $ find (\t1->t1.ident==t.ident) d.deviceTasks +\end{lstlisting} + +The factorial example can then be lifted to a real \gls{iTasks}-\gls{mTask} +with the following code: +\begin{lstlisting}[caption={Lifting the factorial \gls{Task} to \gls{iTasks}}] +factorial :: MTaskDevice -> Task BCValue +factorial dev = enterInformation "Factorial of ?" [] + >>= \fac->liftmTask "fact" (fact fac) (dev, OnInterval 100) + @ fromJust o find (\x->x.humanName == "result") + @ \s->s.MTaskShare.value +where + fact i = sds \y=i + In namedsds \x=(1 Named "result") + In {main = IF (y <=. lit 1) + ( pub x :. retrn ) + ( x =. x *. y :. y =. y -. lit 1 )} +\end{lstlisting} diff --git a/arch.lift.tex b/arch.lift.tex deleted file mode 100644 index 1e96bab..0000000 --- a/arch.lift.tex +++ /dev/null @@ -1,14 +0,0 @@ -If the user does not want to know where and when a \gls{mTask} is actually -executed and is just interested in the results it can lift the \gls{mTask} to -an \gls{iTasks}-\gls{Task}. The function is called with a name, \gls{mTask}, -device and interval specification and it will return a \gls{Task} that finishes -if and only if the \gls{mTask} has returned. - -\begin{lstlisting}[caption={Starting up the devices}] -liftmTask :: String (Main (ByteCode () Stmt)) (MTaskDevice, MTaskInterval) -> Task () -liftmTask wta mTask c=:(dev, _)= sendTaskToDevice wta mTask c - >>= \t->wait "Waiting for mTask to return" (taskRemoved t) (deviceShare dev) - >>| viewInformation "Done!" [] () -where - taskRemoved t d = isNothing $ find (\t1->t1.ident==t.ident) d.deviceTasks -\end{lstlisting} diff --git a/arch.tex b/arch.tex index e1ae608..1ae8e44 100644 --- a/arch.tex +++ b/arch.tex @@ -21,9 +21,5 @@ normal \gls{iTasks}-\glspl{Task}. \section{Communication}\label{sec:communication} \input{arch.communication} -\section[Lifting mTasks to iTasks-Tasks]% - {Lifting \gls{mTask}-\glspl{Task} to \gls{iTasks}-\glspl{Task}} -\input{arch.lift} - \section{Example} \input{arch.example} -- 2.20.1