on master help sign in
fix dev documentation
9915f73Harendra Kumar
src/Strands/Context.hs+42−27
@@ -45,60 +45,75 @@ data ChildEvent a =
45
45
46-- | Describes the context of a computation.
46-- | Describes the context of a computation.
47data Context = Context
47data Context = Context
48+ {
49+ ---------------------------------------------------------------------------
50+ -- Execution state
51+ ---------------------------------------------------------------------------
52+
48− { mailBox :: Maybe Any -- untyped,
53+ mailBox :: Maybe Any -- untyped,
49− -- ^ mailBox to send event data to the child thread
54+ -- ^ mailBox to send event data to the child thread
50
55
51− -- the 'm' and 'f' in an 'm >>= f' operation of the monad
52− -- In nested binds we store the current m only, but the whole stack of fs
53 , currentm :: Any -- untyped, the real type is: m a
56 , currentm :: Any -- untyped, the real type is: m a
57+ -- ^ The 'm' in an 'm >>= f' operation of the monad. This tells us where we
58+ -- are in the monadic computation at this point.
59+
54 , fstack :: [Any] -- untyped, the real type is: [a -> m b]
60 , fstack :: [Any] -- untyped, the real type is: [a -> m b]
55− -- XXX keep a composed computation instead
61+ -- ^ The head of the list stores the 'f' corresponding to 'currentm' in an
56− -- ^ List of continuations
62+ -- 'm >>= f' operation of the monad. This is stack because when a
63+ -- computation has nested binds we need to store the next 'f' for each
64+ -- layer of nesting.
57
65
58 -- log only when there is a restore or if we are teleporting
66 -- log only when there is a restore or if we are teleporting
59 -- We can use a HasLog constraint to statically enable/disable logging
67 -- We can use a HasLog constraint to statically enable/disable logging
60 -- , journal :: Maybe Log
68 -- , journal :: Maybe Log
61 , location :: Location
69 , location :: Location
62
70
71+ ---------------------------------------------------------------------------
72+ -- User state
73+ ---------------------------------------------------------------------------
74+
63 , mfData :: M.Map TypeRep Any -- untyped, type coerced
75 , mfData :: M.Map TypeRep Any -- untyped, type coerced
64 -- ^ State data accessed with get or put operations
76 -- ^ State data accessed with get or put operations
65
77
78+ ---------------------------------------------------------------------------
79+ -- Thread creation, communication and cleanup
80+ ---------------------------------------------------------------------------
81+ -- When a new thread is created the parent records it in the
82+ -- 'pendingThreads' field and 'threadCredit' is decremented. When a child
83+ -- thread is done it sends a done event to the parent on an unbounded
84+ -- channel and goes away. Before starting a new thread the parent always
85+ -- processes the unbounded channel to clear up the pending zombies. This
86+ -- strategy ensures that the zombie queue will never grow more than the
87+ -- number of running threads. Before exiting, the parent thread waits on
88+ -- the channel until all its children are cleaned up.
89+ ---------------------------------------------------------------------------
90+
66 -- XXX use Either parentChannel accumResults
91 -- XXX use Either parentChannel accumResults
67 , accumResults :: Maybe (IORef [Any])
92 , accumResults :: Maybe (IORef [Any])
68 -- ^ Accumulated results, only the top level thread context accumulates.
93 -- ^ Accumulated results, only the top level thread context accumulates.
69 -- Child threads just pass on results via the parent channels.
94 -- Child threads just pass on results via the parent channels.
70− -- XXX we can pass this at the time of fork rather than keeping it here.
71
95
72 , parentChannel :: Maybe (TChan (ChildEvent Any))
96 , parentChannel :: Maybe (TChan (ChildEvent Any))
73− -- ^ Our parent thread's channel to communicate to when we die
97+ -- ^ Parent thread's channel to communicate to when a child thread dies or
74−
98+ -- yields a result value
75− -- Thread creation and cleanup handling. When a new thread is created the
76− -- parent records it in the 'children' field and 'threadCredit' is
77− -- decremented. When a child thread is done it sends a done event to the
78− -- parent on an unbounded channel and goes away. Before starting a new
79− -- thread the parent always processes the unbounded channel to clear up the
80− -- pending zombies. This strategy ensures that the zombie queue will never
81− -- grow more than the number of running threads. Before exiting, the
82− -- parent thread waits on the channel until all its children are cleaned
83− -- up.
84
99
85 , childChannel :: TChan (ChildEvent Any)
100 , childChannel :: TChan (ChildEvent Any)
86− -- ^ A channel for the immediate children to communicate to us when they die.
101+ -- ^ A channel for the immediate children to communicate to us when they
87− -- Each thread has its own dedicated channel for its children
102+ -- die. Each thread has its own dedicated channel for its children
88
103
89 -- We always track the child threads, otherwise the programmer needs to
104 -- We always track the child threads, otherwise the programmer needs to
90− -- worry about if some threads may remain hanging due because they are
105+ -- worry about if some threads may remain hanging because they are stuck in
91− -- stuck in an infinite loop or a forever blocked IO. Also, it is not clear
106+ -- an infinite loop or a forever blocked IO. Also, it is not clear whether
92− -- whether there is a significant gain by disabling tracking. Instead of
107+ -- there is a significant gain by disabling tracking. Instead of using
93− -- using the threadIds we can also keep a count instead, that will allow us
108+ -- threadIds we can also keep a count instead, that will allow us to wait
94− -- to wait for all children to drain but we cannot kill them.
109+ -- for all children to drain but we cannot kill them.
95 --
110 --
96 -- We need these as IORefs since we need any changes to these to be
111 -- We need these as IORefs since we need any changes to these to be
97 -- reflected back in the calling code that waits for the children.
112 -- reflected back in the calling code that waits for the children.
98
113
99 , pendingThreads :: IORef [ThreadId]
114 , pendingThreads :: IORef [ThreadId]
100− -- ^ Active immediate child threads of this thread, modified only by this
115+ -- ^ Active immediate child threads spawned by this thread, modified only
101− -- thread, therefore atomic modification is not needed.
116+ -- by this thread, therefore atomic modification is not needed.
102
117
103 -- By default this limit is shared by the current tree of threads. But at
118 -- By default this limit is shared by the current tree of threads. But at
104 -- any point the 'threads' primitive can be used to start a new limit for
119 -- any point the 'threads' primitive can be used to start a new limit for