add factorial example'
authorMart Lubbers <mart@martlubbers.net>
Sun, 2 Jul 2017 20:17:58 +0000 (22:17 +0200)
committerMart Lubbers <mart@martlubbers.net>
Sun, 2 Jul 2017 20:17:58 +0000 (22:17 +0200)
arch.communication.tex
arch.example.tex
arch.lift.tex [deleted file]
arch.tex

index 9082fd5..2472ab7 100644 (file)
@@ -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]}
index 4b4f48e..db9a2a7 100644 (file)
@@ -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 (file)
index 1e96bab..0000000
+++ /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}
index e1ae608..1ae8e44 100644 (file)
--- 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}