@@ -16,12 +16,14 @@ module Nix.Thunk.Basic
1616 , MonadBasicThunk
1717 ) where
1818
19- import Control.Exception hiding ( catch )
20- import Control.Monad.Catch
21-
19+ import Control.Exception ( SomeException )
20+ import Control.Monad ( (<=<) )
21+ import Control.Monad.Catch ( MonadCatch (.. )
22+ , MonadThrow (throwM )
23+ )
2224import Nix.Thunk
2325import Nix.Var
24- import Nix.Utils ( bool )
26+ import Nix.Utils ( bool )
2527
2628data Deferred m v = Deferred (m v ) | Computed v
2729 deriving (Functor , Foldable , Traversable )
@@ -45,139 +47,128 @@ instance (MonadBasicThunk m, MonadCatch m)
4547 thunkId (Thunk n _ _) = n
4648
4749 thunk :: m v -> m (NThunkF m v )
48- thunk = buildThunk
50+ thunk action =
51+ do
52+ freshThunkId <- freshId
53+ Thunk freshThunkId <$> newVar False <*> newVar (Deferred action)
4954
5055 queryM :: m v -> NThunkF m v -> m v
51- queryM = queryThunk
56+ queryM n (Thunk _ active ref) =
57+ do
58+ thunkIsAvaliable <- not <$> atomicModifyVar active (True , )
59+ bool
60+ n
61+ go
62+ thunkIsAvaliable
63+ where
64+ go = do
65+ eres <- readVar ref
66+ res <-
67+ case eres of
68+ Computed v -> pure v
69+ Deferred _mv -> n
70+ _ <- atomicModifyVar active (False , )
71+ pure res
5272
5373 force :: NThunkF m v -> m v
54- force = forceThunk
74+ force (Thunk n active ref) =
75+ do
76+ eres <- readVar ref
77+ case eres of
78+ Computed v -> pure v
79+ Deferred action ->
80+ do
81+ nowActive <- atomicModifyVar active (True , )
82+ bool
83+ (do
84+ v <- catch action $ \ (e :: SomeException ) ->
85+ do
86+ _ <- atomicModifyVar active (False , )
87+ throwM e
88+ writeVar ref (Computed v)
89+ _ <- atomicModifyVar active (False , )
90+ pure v
91+ )
92+ (throwM $ ThunkLoop $ show n)
93+ nowActive
5594
5695 forceEff :: NThunkF m v -> m v
57- forceEff = forceEffects
96+ forceEff (Thunk _ active ref) =
97+ do
98+ nowActive <- atomicModifyVar active (True , )
99+ bool
100+ (do
101+ eres <- readVar ref
102+ case eres of
103+ Computed v -> pure v
104+ Deferred action ->
105+ do
106+ v <- action
107+ writeVar ref (Computed v)
108+ _ <- atomicModifyVar active (False , )
109+ pure v
110+ )
111+ (pure $ error " Loop detected" )
112+ nowActive
58113
59114 further :: NThunkF m v -> m (NThunkF m v )
60- further = furtherThunk
61-
62-
63- -- ** Specialization barrier
64-
65- -- Since Kleisly functors, ad-hoc polymorphism of type classes has computational cost.
66- -- Especially when one also exports those functions.
67- -- So here - helping the compiler to specialize functions.
68-
69- buildThunk :: MonadBasicThunk m => m v -> m (NThunkF m v )
70- buildThunk action = do
71- freshThunkId <- freshId
72- Thunk freshThunkId <$> newVar False <*> newVar (Deferred action)
73-
74- -- 2021-02-25: NOTE: Please, look into thread handling of this.
75- -- Locking system was not implemented at the time.
76- -- How query operates? Is it normal that query on request if the thunk is locked - returns the thunk
77- -- and when the value calculation is deferred - returns the thunk, it smells fishy.
78- -- And because the query's impemetation are not used, only API - they pretty much could survive being that fishy.
79- queryThunk
80- :: (MonadVar m , MonadCatch m , Show (ThunkId m ))
81- => m v
82- -> NThunkF m v
83- -> m v
84- queryThunk = queryMF pure
85-
86- forceThunk :: (MonadVar m , MonadCatch m , Show (ThunkId m ))
87- => NThunkF m v
88- -> m v
89- forceThunk = forceF pure
90-
91- forceEffects :: (MonadVar m , MonadCatch m , Show (ThunkId m ))
92- => NThunkF m v
93- -> m v
94- forceEffects = forceEffF pure
95-
96- furtherThunk :: (MonadVar m , MonadCatch m , Show (ThunkId m ))
97- => NThunkF m v
98- -> m (NThunkF m v )
99- furtherThunk = furtherF id
115+ further t@ (Thunk _ _ ref) = do
116+ _ <- atomicModifyVar ref $
117+ \ x -> case x of
118+ Computed _ -> (x, x)
119+ Deferred d -> (Deferred d, x)
120+ pure t
100121
101122
102123-- * Kleisli functor HOFs
103124
104- instance (MonadVar m , MonadCatch m , Show ( ThunkId m ) )
125+ instance (MonadBasicThunk m , MonadCatch m )
105126 => MonadThunkF (NThunkF m v ) m v where
106127
107128 queryMF
108- :: ()
109- => (v -> m r )
129+ :: (v -> m r )
110130 -> m r
111131 -> NThunkF m v
112132 -> m r
113- queryMF k n (Thunk _ active ref) = do
114- thunkIsAvaliable <- not <$> atomicModifyVar active (True , )
115- bool
116- n
117- go
118- thunkIsAvaliable
119- where
120- go = do
121- eres <- readVar ref
122- res <-
123- case eres of
124- Computed v -> k v
125- Deferred _mv -> n
126- _ <- atomicModifyVar active (False , )
127- pure res
133+ queryMF k n (Thunk _ active ref) =
134+ do
135+ thunkIsAvaliable <- not <$> atomicModifyVar active (True , )
136+ bool
137+ n
138+ go
139+ thunkIsAvaliable
140+ where
141+ go =
142+ do
143+ eres <- readVar ref
144+ res <-
145+ case eres of
146+ Computed v -> k v
147+ Deferred _mv -> n
148+ _ <- atomicModifyVar active (False , )
149+ pure res
128150
129151 forceF
130- :: (MonadCatch m , Show (ThunkId m ))
131- => (v -> m a )
152+ :: (v -> m a )
132153 -> NThunkF m v
133154 -> m a
134- forceF k (Thunk n active ref) = do
135- eres <- readVar ref
136- case eres of
137- Computed v -> k v
138- Deferred action -> do
139- nowActive <- atomicModifyVar active (True , )
140- bool
141- (do
142- v <- catch action $ \ (e :: SomeException ) -> do
143- _ <- atomicModifyVar active (False , )
144- throwM e
145- _ <- atomicModifyVar active (False , )
146- writeVar ref (Computed v)
147- k v
148- )
149- (throwM $ ThunkLoop $ show n)
150- nowActive
155+ forceF k = k <=< force
151156
152157 forceEffF
153- :: ()
154- => (v -> m r )
158+ :: (v -> m r )
155159 -> NThunkF m v
156160 -> m r
157- forceEffF k (Thunk _ active ref) = do
158- nowActive <- atomicModifyVar active (True , )
159- bool
160- (do
161- eres <- readVar ref
162- case eres of
163- Computed v -> k v
164- Deferred action -> do
165- v <- action
166- writeVar ref (Computed v)
167- _ <- atomicModifyVar active (False , )
168- k v
169- )
170- (pure $ error " Loop detected" )
171- nowActive
161+ forceEffF k = k <=< forceEff
172162
173163 furtherF
174- :: ()
175- => (m v -> m v )
164+ :: (m v -> m v )
176165 -> NThunkF m v
177166 -> m (NThunkF m v )
178- furtherF k t@ (Thunk _ _ ref) = do
179- _ <- atomicModifyVar ref $ \ x -> case x of
180- Computed _ -> (x, x)
181- Deferred d -> (Deferred (k d), x)
182- pure t
167+ furtherF k t@ (Thunk _ _ ref) =
168+ do
169+ _ <- atomicModifyVar ref $
170+ \ x -> case x of
171+ Computed _ -> (x, x)
172+ Deferred d -> (Deferred (k d), x)
173+ pure t
183174
0 commit comments