sweep
authorMart Lubbers <mart@martlubbers.net>
Sat, 24 Jun 2017 14:02:40 +0000 (16:02 +0200)
committerMart Lubbers <mart@martlubbers.net>
Sat, 24 Jun 2017 14:02:40 +0000 (16:02 +0200)
results.arch.tex
results.mtask.tex
thesis.tex

index 20f0402..e4e5d38 100644 (file)
@@ -71,26 +71,38 @@ the device software.
 \end{itemize}
 
 \subsection{Client}
-\subsubsection*{Engine}
+\subsubsection{Engine}
 The client is in a constant loop listening for input and waiting to execute
-\gls{Task}. The pseudocode for this is shown in Algorithm~\ref{alg:client}.
+\gls{Task}. The pseudocode for this is shown in Algorithm~\ref{alg:client}. The
+\CI{input\_available} function waits for input, but has a timeout set which can
+be interrupted. The timeout of the function determines the amount of loops per
+time interval and is a parameter that can be set during compilation for a
+device.
 
-\todo{make algorithm}
 \begin{algorithm}[H]
-       \KwData{\textbf{stack} stack, \textbf{time} $t, t_p$}
+       \KwData{
+               \textbf{list} $tasks$,
+               \textbf{time} $t$
+       }
 
-       $t\leftarrow\text{now}()$\;
        \Begin{
                \While{true}{
-                       $t_p\leftarrow t$\;
-                       $t\leftarrow\text{now}()$\;
-                       \If{notEmpty$($queue$)$}{
-                               $task\leftarrow \text{queue.pop}()$\;
-                               $task$.wait $\leftarrow task$.wait $-(t-t_p)$\;
-                               \eIf{$task.wait>t_0$}{
-                                       queue.append$(task)$\;
-                               }{
-                                       run\_task$(task)$\;
+                       \If{input\_available$()$}{
+                               receive\_data()\;
+                       }
+
+                       $t\leftarrow \text{now}()$\;
+                       \ForEach{$t\leftarrow tasks$}{
+                               \uIf{is\_interrupt$(t) \&\& $had\_interrupt$(t)$}{
+                                       run\_task$(t)$\;
+                               }
+                               \ElseIf{$t-t.\text{lastrun} > t.\text{interval}$}{
+                                       run\_task$(t)$\;
+                                       \uIf{$t.\text{interval}==0$}{
+                                               delete\_task$(t)$\;
+                                       }\Else{
+                                               $t.\text{lastrun}\leftarrow t$\;
+                                       }
                                }
                        }
                }
@@ -98,20 +110,21 @@ The client is in a constant loop listening for input and waiting to execute
        \caption{Engine pseudocode}\label{alg:client}
 \end{algorithm}
 
-\subsubsection*{Storage}
+\subsubsection{Storage}
 \glspl{Task} and \glspl{SDS} are stored on the client in one big memory space
-that is fully allocated at the start of the program. The space could also have
-been dynamically allocated but that would require using the heap which is
-unwanted in small memory environments. \Glspl{Task} grow from the bottom up
-and \glspl{SDS} grow from the top down. When a \gls{Task} or \gls{SDS} is
-removed, all \glspl{Task} are relocated in the memory space to not leave
-holes. Both \glspl{Task} and \glspl{SDS} are stored as structs and helper
-functions are available to loop through them without having to fiddle in the
-memory space. The instance for \glspl{Task} and \glspl{SDS} are shown in
-Listing~\ref{lst:structs} accompanied by the helper functions for \glspl{Task}.
-\Glspl{Task} consist the length, interval, last run time, id and the bytecode.
-\Glspl{SDS} consist just of an id, value and type. The pointer to the bytecode
-of the \gls{Task} always points to the location in the memory space.
+that is reserved at the start of the program. The space could also have been
+dynamically allocated but that would require using the heap which is unwanted
+in small memory environments. \Glspl{Task} grow from the bottom up and
+\glspl{SDS} grow from the top down. When a \gls{Task} or \gls{SDS} is removed,
+all \glspl{Task} are relocated in the memory space to not leave holes. Both
+\glspl{Task} and \glspl{SDS} are stored as structures that are linked in the
+memory space, helper functions are available to loop through them without
+having to fiddle in the memory space itself. The instance for \glspl{Task} and
+\glspl{SDS} are shown in Listing~\ref{lst:structs} accompanied by the helper
+functions for \glspl{Task}. \Glspl{Task} consist the length, interval, last run
+time, id and the bytecode. \Glspl{SDS} consist just of an id, value and type.
+The pointer to the bytecode of the \gls{Task} always points to the location in
+the memory space.
 
 \begin{lstlisting}[language=C,label={lst:structs},%
        caption={The data type storing the \glspl{Task}}]
@@ -136,16 +149,17 @@ struct sds *sds_head(void);
 struct sds *sds_next(struct sds *s);
 \end{lstlisting}
 
-\subsubsection*{Interpretation}
-Execution of a \gls{Task} always start with prepared the stack and the program
-counter and stack pointer are set to zero and the bottom respectively. When
-finished, the interpreter executes one step at the time while the program
-counter is smaller than the program length. The code for this is listed in
+\subsubsection{Interpretation}
+The execution of a \gls{Task} is started by running the \CI{run\_task} function
+and always start with prepared the stack and the program counter and stack
+pointer are set to zero and the bottom respectively. When finished, the
+interpreter executes one step at the time while the program counter is smaller
+than the program length. The code for this is listed in
 Listing~\ref{lst:interpr}. One execution step is basically a big switch
 statement going over all possible bytecode instructions. Some instructions are
 detailed upon in the listing. The \CI{BCPush} instruction is a little more
 complicated in the real code because some decoding will take place as not all
-\CI{BCValue}'s are of the same length and are encoded.
+\CI{BCValue}s are of the same length and are encoded.
 
 \begin{lstlisting}[language=C,label={lst:interpr},%
        caption={Rough code outline for interpretation}]
@@ -183,21 +197,21 @@ void run_task(struct task *t){
 \end{lstlisting}
 
 \subsection{Specification}
-The server stores a description for every device available in a record type
-which are stored in a \gls{SDS}. From the macro settings in
-the interface file, a profile is created for the device that describes the
-specification. When a connection between the server and a client is established
-the server will send a request for specification. The client will serialize his
-specification and send it to the server so that the server knows what the
-client is capable of. The exact specification is shown in
-Listing~\ref{lst:devicespec} and stores the peripheral availability, the memory
-available for storing \glspl{Task} and \glspl{SDS} and the size of the stack.
+The server stores a description for every device available in a record type.
+From the macro settings in the interface file, a profile is created that
+describes the specification of the device. When the connection between the
+server and a client is established, the server will send a request for
+specification. The client will serialize his specification and send it to the
+server so that the server knows what the client is capable of.  The exact
+specification is shown in Listing~\ref{lst:devicespec} and stores the
+peripheral availability, the memory available for storing \glspl{Task} and
+\glspl{SDS} and the size of the stack.
 
 \begin{lstlisting}[label={lst:devicespec},
        caption={Device specification for \glspl{mTask}}]
 :: MTaskDeviceSpec =
        { haveLed     :: Bool
-       , haveLcd     :: Bool
+       , haveLCD     :: Bool
        , have...
        , bytesMemory :: Int
        , stackSize   :: Int
@@ -215,20 +229,19 @@ provides functionality to list \glspl{SDS}, add \glspl{Task}, remove
 \glspl{Task}, administrate devices and view the state of the system.
 
 \subsection{Device Storage}
-All devices that have been connected to the server are stored in a \gls{SDS}.
-The \gls{SDS} contains a list of \CI{MTaskDevice}s. The \CI{MTaskDevice}
-definition is shown in Listing~\ref{lst:mtaskdevice} accompanied with the used
-classes and types.
+Everything that a device encompasses is stored in the \CI{MTaskDevice} record
+type. This includes management for the \glspl{SDS} and \glspl{Task} stored on
+the device. The \CI{MTaskDevice} definition is shown in
+Listing~\ref{lst:mtaskdevice} accompanied with the necessary classes and sub
+types.
 
 \begin{lstlisting}[caption={Device type},label={lst:mtaskdevice}]
-deviceStoreNP :: Shared [MTaskDevice]
-deviceShare :: MTaskDevice -> Shared MTaskDevice
-
 :: Channels :== ([MTaskMSGRecv], [MTaskMSGSend], Bool)
 :: BCState = ... // Compiler state, explained in later sections
-:: MTaskResource 
+:: MTaskResource
        = TCPDevice TCPSettings
        | SerialDevice TTYSettings
+       | ...
 :: MTaskDevice =
                { deviceTask :: Maybe TaskId
                , deviceError :: Maybe String
@@ -268,52 +281,18 @@ the specification of the device that is received when connecting. All of this
 is given in Listing~\ref{lst:mtaskdevice}. The definitions of the message
 format are explained in the following section.
 
-\subsection{Integration}
-When the system starts up, the devices from the previous execution still
-residing in the \gls{SDS} must be cleaned up. It might be the case that they
-contain \glspl{Task}, \glspl{SDS} or errors that are no longer applicable in
-this run. A user or programmer can later choose to reconnect to some devices.
-
-\begin{lstlisting}[caption={Starting up the devices},%
-       label={lst:startupdevs}]
-startupDevices :: Task [MTaskDevice]
-startupDevices = upd (map reset) deviceStoreNP
-       where reset d = {d & deviceTask=Nothing, deviceTasks=[], deviceError=Nothing}
-\end{lstlisting}
-
-The system's management is done through the interface of a single \gls{Task}
-called \CI{mTaskManager}. To manage the system, a couple of different
-functionalities are needed and are launched. An image of the management
-interface is shown in Figure~\ref{lst:manage}. The left sidebar of the
-interface shows the list of example \glspl{Task} that are present in the
-system. When clicking a \gls{Task}, a dialog opens in which you can select the
-device to send the \gls{Task} to. The dialog might contain user specified
-variables. All example \glspl{mTask} are of the type 
-\CI{Task (Main (ByteCode () Stmt))} and can thus ask for user input first if
-needed for parameterized \glspl{mTask}. The bottom panel shows the device
-information. In this panel, the devices can be created and modified.  Moreover,
-this panel allows the user to reconnect with a device after a restart of the
-server application.
-
-\todo{redo this image}
-\begin{figure}[H]
-       \centering
-       \includegraphics[width=\linewidth]{manage}
-       \caption{The device management interface}\label{lst:manage}
-\end{figure}
-
 \subsection{Shares}
 The architecture of the system keeps track of the \glspl{SDS} stored on
-the client in the big devices \gls{SDS}. Client-\glspl{SDS} can be stored on
-one device at the same time. This means that if a \gls{SDS} updates, everyone
-watching it will be notified. This would result in to a lot of notifications
-that are not meant for the listener. Moreover, when a client updates the
-\gls{SDS} this is processed by the connection handler and results in an update
-of the real \gls{SDS}. Finally, the \gls{SDS} of a client must be synchronized
-with the actual device. Thus, when an \gls{iTasks}-\gls{Task} writes the
-client-\gls{SDS}, it must be propagated to the real device. There are several
-ways of tackling this problem each with their own pros and cons and their own
-level of abstraction.
+the client in a big \gls{SDS} containing a list of devices. Client-\glspl{SDS}
+can be stored on one device at the same time. This means that if a \gls{SDS}
+updates, everyone watching it will be notified. This would result in to a lot
+of notifications that are not meant for the listener. Moreover, when a client
+updates the \gls{SDS} this is processed by the connection handler and results
+in an update of the real \gls{SDS}. Finally, the \gls{SDS} of a client must be
+synchronized with the actual device. Thus, when an \gls{iTasks}-\gls{Task}
+writes the client-\gls{SDS}, it must be propagated to the real device. There
+are several ways of tackling this problem each with their own pros and cons and
+their own level of abstraction.
 
 First an actual \gls{iTasks}-\gls{SDS} for every \gls{SDS} used in a client can
 be instantiated with one \gls{iTasks}-\gls{Task} listening to the \gls{SDS} and
@@ -333,58 +312,127 @@ Ultimately, the current approach --- a single \gls{SDS} for the entire system
 \CI{mapReadWrite} can be used but it suffers the same problem as mentioned
 before. Moreover, a \gls{Task} still has to watch the \gls{SDS} and communicate
 the client-\gls{SDS} updates to the actual device. Both of these problems can
-be solved using a tailor made share heavily depending on parametric lenses. The
-type signature of the share then is as listed in Listing~\ref{lst:actualdev}.
-
-\begin{lstlisting}[label={lst:actualdev},%
-       caption={Device \gls{SDS}}]
-deviceStore :: Shared [MTaskDevice]
-\end{lstlisting}
+be solved by using a tailor made share that heavily depends on parametric
+lenses.
 
 \subsection{Parametric Lenses}
 The type of the parametric lens is \CI{Maybe (MTaskDevice, Int)}. The \gls{SDS}
 can be responsible for the entire list of devices, from now on global.
 Moreover, the \gls{SDS} can focus on a single device, from now on local. A
 local \gls{SDS} can also specifically focus on a single \gls{SDS} on a single
-device, from now on called local-share.
+device, from now on called local-share. The implementation of the real
+\gls{SDS} is given in Listing~\ref{lst:actualdev}. The \gls{SDS} is a lens on
+an actual \gls{SDS} that writes to a file or memory. Reading the \gls{SDS} is
+nothing more than reading the real \gls{SDS}. Writing the \gls{SDS} is a little
+bit more involved. If the write operation originated from a \gls{SDS} focussed
+on a single client-\gls{SDS}, the write action must also be relayed to the
+actual device. If the write originated from a \gls{SDS} focussed the devices or
+on one device only, nothing needs to be done. The notification predicate
+determines whether a watcher gets a notification update.
 
-\paragraph{Global \glspl{SDS}: }
+\begin{lstlisting}[label={lst:actualdev},%
+       caption={Device \gls{SDS}}]
+deviceStore :: RWShared (Maybe (MTaskDevice, Int)) [MTaskDevice] [MTaskDevice]
+deviceStore = SDSSource {SDSSource | name="deviceStore", read = realRead, write= realWrite}
+where
+       realRead :: (Maybe (MTaskDevice,Int)) *IWorld -> (MaybeError TaskException [MTaskDevice], *IWorld)
+       realRead p iw = read realDeviceStore iw
+
+       realWrite :: (Maybe (MTaskDevice,Int)) [MTaskDevice] *IWorld -> (MaybeError TaskException (SDSNotifyPred (Maybe (MTaskDevice,Int))), *IWorld)
+       realWrite mi w iw
+       # (merr, iw) = write w realDeviceStore iw
+       | isError merr || isNothing mi = (merr $> notifyPred mi, iw)
+       # (Just (dev, ident)) = mi
+       | ident == -1 = (merr $> notifyPred mi, iw)
+       = case find ((==)dev) w of
+               Nothing = (Error $ exception "Device lost", iw)
+               Just {deviceShares} = case find (\d->d.identifier == ident) deviceShares of
+                       Nothing = (Error $ exception "Share lost", iw)
+                       Just s = case sendMessagesIW [MTUpd ident s.MTaskShare.value] dev iw of
+                               (Error e, iw) = (Error e, iw)
+                               (Ok _, iw) = (Ok $ notifyPred mi, iw)
+
+       notifyPred :: (Maybe (MTaskDevice, Int)) (Maybe (MTaskDevice, Int)) -> Bool
+       notifyPred Nothing Nothing = True    // Global watcher looking at a global event
+       notifyPred Nothing (Just _) = False  // Global watcher looking at a local event
+       notifyPred (Just _) Nothing = False  // Local watcher looking at a global event
+       // Local device watcher looking at a local event
+       notifyPred (Just (d1, -1)) (Just (d2, _)) = d1 == d2
+       // Local share watcher looking at a local share event
+       notifyPred (Just (d1, i1)) (Just (d2, i2)) = d1 == d2 && i1 == i2
+
+       realDeviceStore :: Shared [MTaskDevice]
+       realDeviceStore = sharedStore "mTaskDevices" []
+\end{lstlisting}
+
+\subsubsection{Global \glspl{SDS}}
 Accessing the global \gls{SDS} is just a matter of focussing the
-\CI{deviceStore} with the \CI{Nothing} parameter. The signature for
-\CI{deviceStore} was given in Chapter~\ref{chp:arch}. The actual implementation
-is as in Listing~\ref{lst:global}
+\CI{deviceStore} with the \CI{Nothing} parameter as follows:
 
-\begin{lstlisting}[label={lst:shareimpl},%
-       caption={Base share implementation}]
-deviceStoreNP :: RWShared (Maybe (MTaskDevice, Int)) [MTaskDevice] [MTaskDevice]
+\begin{lstlisting}[caption={Global \gls{SDS}}]
+deviceStoreNP :: Shared [MTaskDevice]
 deviceStoreNP = sdsFocus Nothing deviceStore
 \end{lstlisting}
 
+\subsubsection{Local \glspl{SDS}}
+Accessing a single device can be done using the \CI{mapReadWrite} function.
+Since device comparison is shallow, the device that is given is allowed to be
+an old version. The identification of devices is solely done on the name of the
+channels and is unique throughout the system. The implementation is as follows:
 
+\begin{lstlisting}[caption={Local \gls{SDS}}]
+deviceShare :: MTaskDevice -> Shared MTaskDevice
+deviceShare d = mapReadWriteError
+       ( \ds->case find ((==)d) of
+               Nothing = exception "Device lost"
+               Just d = Ok d)
+       , \w ds->case splitWith ((==)d) ds of
+               ([], _) = Error $ exception "Device lost"
+               ([_:_], ds) = Ok $ Just [w:ds])
+       $ sdsFocus (Just (d, -1)) deviceStore
+\end{lstlisting}
 
-
-\paragraph{Local \glspl{SDS}: }
-\paragraph{Local-share specific \glspl{SDS}: }
-
-The implementation for the share is shown in Listing~\ref{lst:shareimpl}. The
-\CI{realDeviceStore} \gls{SDS} is not exported through the header files. This
-\gls{SDS} contains the actual \gls{SDS} that writes to disk or memory.
-\CI{Int} is the identifier of the \gls{SDS}. The \gls{iTasks} way of applying
-lenses is through the \CI{sdsFocus} function and through the \CI{sdsLens}
-functions. \CI{sdsFocus} allows the programmer to fix the parameter.
-\CI{sdsLens} is basically a \CI{mapReadWrite} that has access to the parameter.
-This allows the programmer to create filters and lenses. Both of the methods
-are not good enough for the device \gls{SDS} because they do not achieve the
-writing to the actual device. Writing to a device requires being able to write
-to \glspl{SDS}. To solve this problem, a real base \gls{SDS} is created. All
-the details are visible in Listing~\ref{lst:shareimpl}.
+\subsubsection{Local-share specific \glspl{SDS}}
+A single \gls{SDS} on a single device can be accessed using the \CI{shareShare}
+function. This function focusses the real big \gls{SDS} on a single share and
+uses the \CI{mapReadWrite} functions to serve the correct part of the
+information.
+
+\begin{lstlisting}[caption={Local \gls{SDS}}]
+shareShare :: MTaskDevice MTaskShare -> Shared BCValue
+shareShare dev share = sdsFocus ()
+       $ mapReadWriteError (read, write)
+       $ sdsFocus (Just (dev, share.identifier))
+       $ deviceStore
+where
+       read :: [MTaskDevice] -> MaybeError TaskException BCValue
+       read devs = case find ((==)dev) devs of
+               Nothing = exception "Device lost"
+               Just d = case find ((==)share) d.deviceShares of
+                       Nothing = exception "Share lost"
+                       Just s = Ok s.MTaskShare.value
+       
+       write :: BCValue [MTaskDevice] -> MaybeError TaskException (Maybe [MTaskDevice])
+       write val devs = case partition ((==)dev) devs of
+               ([], _) = Error $ exception "Device doesn't exist anymore"
+               ([_,_:_], _) = Error $ exception "Multiple matching devices"
+               ([d=:{deviceShares}], devs) = case partition ((==)share) deviceShares of
+                       ([], _) = Error $ exception "Share doesn't exist anymore"
+                       ([_,_:_], _) = Error $ exception "Multiple matching shares"
+                       ([s], shares) = Ok $ Just [{MTaskDevice | d & 
+                               deviceShares=[{MTaskShare | s & value=val}:shares]}:devs]
+\end{lstlisting}
 
 \section{Communication}
 The communication from the server to the client and vice versa is just a
-character stream containing encoded \gls{mTask} messages. The specific encoding
-is visible in Appendix~\ref{app:communication-protocol}. The type holding the
-messages in Listing~\ref{lst:avmsg}. Detailed explanation about the message
-types will be given in the following subsections.
+character stream containing encoded \gls{mTask} messages. The \CI{synFun}
+belonging to the device is responsible for sending the content in the left
+channel and putting received messages in the right channel. Moreover, it should
+set the boolean value to \CI{True} when the connection is terminated. The
+specific encoding of the messages is visible in
+Appendix~\ref{app:communication-protocol}. The type holding the messages in
+Listing~\ref{lst:avmsg}. Detailed explanation about the message types and
+according actions will be given in the following subsections.
 
 \begin{lstlisting}[label={lst:avmsg},caption={Available messages}]
 :: MTaskId :== Int
@@ -407,29 +455,26 @@ types will be given in the following subsections.
 \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}, 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 the device functionality heavily
-depends on the specific \CI{deviceShare} function that applies a function a device in
-the \gls{SDS} when they are equal. Device equality is defined as equality on
-their channels. This allows you to give an old device record to the function
-and still update the latest instance. Listing~\ref{lst:connectDevice} shows the
-connection function.
+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 the device functionality
+heavily depends on the specific \CI{deviceShare} function that generates a
+\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}]
-withDevices :: MTaskDevice (MTaskDevice -> MTaskDevice) -> Task [MTaskDevice]
-
 connectDevice :: (MTaskDevice (Shared Channels) -> Task ()) MTaskDevice -> Task Channels
 connectDevice procFun device = let ch = channels device
-       in appendTopLevelTask 'DM'.newMap True
-               (procFun device ch -||- catchAll (getSynFun d.deviceData ch) errHdl)
-               >>= \tid->withDevices device (\d->{d&deviceTask=Just tid,deviceError=Nothing})
+       in traceValue "connectDevice" >>| appendTopLevelTask 'DM'.newMap True
+               (       procFun device ch -||- catchAll (getSynFun device.deviceData ch) errHdl)
+               >>= \tid->upd (\d->{d&deviceTask=Just tid,deviceError=Nothing}) (deviceShare device)
                >>| upd (\(r,s,ss)->(r,s++[MTSpec],ss)) ch
-       where
-               errHdl e = withDevices device (\d->{d & deviceTask=Nothing, deviceError=Just e}) @! ()
+where
+       errHdl e = upd (\d->{d & deviceTask=Nothing, deviceError=Just e}) (deviceShare device) @! ()
 \end{lstlisting}
 
 Figure~\ref{fig:handshake} shows the connection diagram. The client responds to
@@ -476,8 +521,8 @@ of the device. This will result in sending the actual \gls{SDS} specification
 and \gls{Task} specifications to the device. A \gls{Task} record is created
 with the identifier $-1$ to denote a \gls{Task} not yet acknowledged. Finally
 the device itself is updated with the new state and with the new \gls{Task}.
-When the device returns an acknowledgement the \gls{Task} is updated
-accordingly.
+After waiting for the acknowledgement the device is updated again and the
+\gls{Task} returns.
 
 \begin{lstlisting}[label={lst:sendtask},%
        caption={Sending a \gls{Task} to a device}]
@@ -487,18 +532,21 @@ 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 [MTaskDevice]
+sendTaskToDevice :: String (Main (ByteCode a Stmt)) (MTaskDevice, MTaskInterval) -> Task MTaskTask
 sendTaskToDevice wta mTask (device, timeout)
-# (msgs, newState) = toMessages timeout mTask device.deviceState
-# shares = [makeShare wta sdsi sdsval\\{sdsi,sdsval}<-newState.sdss, (MTSds sdsi` _)<-msgs | sdsi == sdsi`] 
+# (msgs, newState=:{sdss}) = toMessages timeout mTask device.deviceState
+# shares = [makeShare wta "" sdsi sdsval\\{sdsi,sdsval}<-sdss, (MTSds sdsi` _)<-msgs | sdsi == sdsi`]
 = updateShares device ((++) shares)
        >>| sendMessages msgs device
        >>| makeTask wta -1
-       >>= withDevices device o addTaskUpState newState
-       where
-               addTaskUpState :: BCState MTaskTask MTaskDevice -> MTaskDevice
-               addTaskUpState st task device = {MTaskDevice | device &
-                       deviceState=st, deviceTasks=[task:device.deviceTasks]}
+       >>= \t->upd (addTaskUpState newState t) (deviceShare device)
+       >>| wait "Waiting for task to be acked" (taskAcked t) (deviceShare device)
+       >>| treturn t
+where
+       addTaskUpState :: BCState MTaskTask MTaskDevice -> MTaskDevice
+       addTaskUpState st task device = {MTaskDevice | device & deviceState=st, deviceTasks=[task:device.deviceTasks]}
+       taskAcked t d = maybe True (\t->t.ident <> -1) $ find (eq t) d.deviceTasks
+       eq t1 t2 = t1.dateAdded == t2.dateAdded && t1.MTaskTask.name == t2.MTaskTask.name
 \end{lstlisting}
 
 \subsection{Miscellaneous Messages}
@@ -509,8 +557,55 @@ losing all the \glspl{SDS} and \glspl{Task} that were stored and reset itself.
 Shortly after the shutdown message a new server can connect to the device
 because the device is back in listening mode.
 
-\section{Lifting mTask to iTasks}
-\todo{task lifting}
+\subsection{Integration}
+When the system starts up, the devices from the previous execution still
+residing in the \gls{SDS} must be cleaned up. It might be the case that they
+contain \glspl{Task}, \glspl{SDS} or errors that are no longer applicable in
+this run. A user or programmer can later choose to reconnect to some devices.
+
+\begin{lstlisting}[caption={Starting up the devices},%
+       label={lst:startupdevs}]
+startupDevices :: Task [MTaskDevice]
+startupDevices = upd (map reset) deviceStoreNP
+       where reset d = {d & deviceTask=Nothing, deviceTasks=[], deviceError=Nothing}
+\end{lstlisting}
+
+The system's management is done through the interface of a single \gls{Task}
+called \CI{mTaskManager}. To manage the system, a couple of different
+functionalities are needed and are launched. An image of the management
+interface is shown in Figure~\ref{lst:manage}. The left sidebar of the
+interface shows the list of example \glspl{Task} that are present in the
+system. When clicking a \gls{Task}, a dialog opens in which you can select the
+device to send the \gls{Task} to. The dialog might contain user specified
+variables. All example \glspl{mTask} are of the type \CI{Task (Main (ByteCode
+() Stmt))} and can thus ask for user input first if needed for parameterized
+\glspl{mTask}. The bottom panel shows the device information. In this panel,
+the devices can be created and modified.  Moreover, this panel allows the user
+to reconnect with a device after a restart of the server application.
+
+\todo{redo this image}
+\begin{figure}[H]
+       \centering
+       \includegraphics[width=\linewidth]{manage}
+       \caption{The device management interface}\label{lst:manage}
+\end{figure}
+
+\section[Lifting mTasks to iTasks-Tasks]%
+       {Lifting \glspl{mTask} 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}-\glspl{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}
 
 \section{Examples}
 \todo{example program (demo)}
index a939d4f..92e0782 100644 (file)
@@ -228,6 +228,8 @@ instance noOp ByteCode where
        noOp = tell` [BCNop]
 \end{lstlisting}
 
+\todo{Add return instruction}
+
 \subsection{Shared Data Sources \& Assignment}
 Shared data sources must be acquired from the state and constructing one
 involves multiple steps. First, a fresh identifier is grabbed from the state.
@@ -327,4 +329,3 @@ position in the program memory.
 20   : BCDigitalWrite (Digital D0)
 \end{lstlisting}
 \todo{More elaborate example}
-\todo{Add return instruction}
index 611367f..be19044 100644 (file)
 \chapter{Embedded Domain Specific Languages}\label{chp:dsl}
 \input{methods.dsl}
 
-\chapter{The mTask EDSL}\label{chp:mtask}
+\chapter[The mTask EDSL]{The \gls{mTask} \gls{EDSL}}\label{chp:mtask}
 \input{methods.mtask}
 
-\chapter{Extending the mTask EDSL}\label{chp:mtaskcont}
+\chapter[Extending the mTask EDSL]{Extending the \gls{mTask} {EDSL}}\label{chp:mtaskcont}
 \input{results.mtask}
 
 \chapter{System Architecture}\label{chp:arch}