@@ -32,11 +32,25 @@ import Nix.Utils ( bool
3232data Deferred m v = Computed v | Deferred (m v )
3333 deriving (Functor , Foldable , Traversable )
3434
35+ -- | It is a reference (@ref-tf: Ref m@), and as such also holds @Bool@ lock.
36+ type ThunkRef m = (Var m Bool )
37+
38+ -- | Reference (@ref-tf: Ref m v@) to a value that thunk holds.
39+ type ThunkValueRef m v = Var m (Deferred m v )
40+
41+ -- | @ref-tf@ lock instruction for @Ref m@ (@ThunkRef@).
42+ lock :: Bool -> (Bool , Bool )
43+ lock = (True , )
44+
45+ -- | @ref-tf@ unlock instruction for @Ref m@ (@ThunkRef@).
46+ unlock :: Bool -> (Bool , Bool )
47+ unlock = (False , )
48+
3549-- * Data type for thunks: @NThunkF@
3650
3751-- | The type of very basic thunks
3852data NThunkF m v
39- = Thunk (ThunkId m ) (Var m Bool ) (Var m ( Deferred m v ) )
53+ = Thunk (ThunkId m ) (ThunkRef m ) (ThunkValueRef m v )
4054
4155instance (Eq v , Eq (ThunkId m )) => Eq (NThunkF m v ) where
4256 Thunk x _ _ == Thunk y _ _ = x == y
@@ -52,16 +66,19 @@ type MonadBasicThunk m = (MonadThunkId m, MonadVar m)
5266instance (MonadBasicThunk m , MonadCatch m )
5367 => MonadThunk (NThunkF m v ) m v where
5468
69+ -- | Return thunk ID
5570 thunkId :: NThunkF m v -> ThunkId m
5671 thunkId (Thunk n _ _) = n
5772
73+ -- | Create new thunk
5874 thunk :: m v -> m (NThunkF m v )
5975 thunk action =
6076 do
6177 freshThunkId <- freshId
6278 Thunk freshThunkId <$> newVar False <*> newVar (Deferred action)
6379
64- -- | Non-blocking query
80+ -- | Non-blocking query, return value if @Computed@,
81+ -- return first argument otherwise.
6582 queryM :: m v -> NThunkF m v -> m v
6683 queryM n (Thunk _ _ ref) =
6784 do
@@ -88,33 +105,34 @@ instance (MonadBasicThunk m, MonadCatch m)
88105
89106-- *** United body of `force*`
90107
108+ -- | If @m v@ is @Computed@ - returns is
91109forceMain
92110 :: ( MonadBasicThunk m
93111 , MonadCatch m
94112 )
95113 => NThunkF m v
96114 -> m v
97- forceMain (Thunk n active ref ) =
115+ forceMain (Thunk n thunkRef thunkValRef ) =
98116 do
99117 deferred
100118 pure
101119 (\ action ->
102120 do
103- lockThunk <- atomicModifyVar active ( True , )
121+ lockedIt <- atomicModifyVar thunkRef lock
104122 bool
105123 (throwM $ ThunkLoop $ show n)
106124 (do
107125 v <- catch action $ \ (e :: SomeException ) ->
108126 do
109- _ <- atomicModifyVar active ( False , )
127+ _unlockedIt <- atomicModifyVar thunkRef unlock
110128 throwM e
111- writeVar ref (Computed v)
112- _unlockThunk <- atomicModifyVar active ( False , )
129+ writeVar thunkValRef (Computed v)
130+ _unlockedIt <- atomicModifyVar thunkRef unlock
113131 pure v
114132 )
115- (not lockThunk )
133+ (not lockedIt )
116134 )
117- =<< readVar ref
135+ =<< readVar thunkValRef
118136{-# inline forceMain #-} -- it is big function, but internal, and look at its use.
119137
120138
@@ -129,22 +147,23 @@ instance (MonadBasicThunk m, MonadCatch m)
129147 -> m r
130148 -> NThunkF m v
131149 -> m r
132- queryMF k n (Thunk _ active ref ) =
150+ queryMF k n (Thunk _ thunkRef thunkValRef ) =
133151 do
134- thunkIsAvaliable <- not <$> atomicModifyVar active (True , )
152+ lockedIt <- atomicModifyVar thunkRef (True , )
135153 bool
136154 n
137155 go
138- thunkIsAvaliable
156+ ( not lockedIt)
139157 where
140158 go =
141159 do
142- eres <- readVar ref
160+ eres <- readVar thunkValRef
143161 res <-
144- case eres of
145- Computed v -> k v
146- Deferred _mv -> n
147- _ <- atomicModifyVar active (False , )
162+ deferred
163+ k
164+ (const n)
165+ eres
166+ _unlockedIt <- atomicModifyVar thunkRef (False , )
148167 pure res
149168
150169 forceF
@@ -165,10 +184,12 @@ instance (MonadBasicThunk m, MonadCatch m)
165184 -> m (NThunkF m v )
166185 furtherF k t@ (Thunk _ _ ref) =
167186 do
168- _ <- atomicModifyVar ref $
169- \ x -> case x of
170- Computed _ -> (x, x)
171- Deferred d -> (Deferred (k d), x)
187+ _modifiedIt <- atomicModifyVar ref $
188+ \ x ->
189+ deferred
190+ (const (x, x))
191+ (\ d -> (Deferred (k d), x))
192+ x
172193 pure t
173194
174195
0 commit comments