| Safe Haskell | Safe-Inferred | 
|---|---|
| Language | GHC2021 | 
Control.RefCount
Synopsis
- data Ref obj where
 - releaseRef :: (RefCounted m obj, PrimMonad m, MonadMask m) => Ref obj -> m ()
 - withRef :: forall m obj a. (PrimMonad m, MonadThrow m) => Ref obj -> (obj -> m a) -> m a
 - dupRef :: forall m obj. (RefCounted m obj, PrimMonad m, MonadThrow m) => Ref obj -> m (Ref obj)
 - data RefException
- = RefUseAfterRelease RefId CallStack CallStack CallStack
 - | RefDoubleRelease RefId CallStack CallStack CallStack
 - | RefNeverReleased RefId CallStack
 
 - newtype WeakRef a = WeakRef a
 - mkWeakRef :: Ref obj -> WeakRef obj
 - mkWeakRefFromRaw :: obj -> WeakRef obj
 - deRefWeak :: (RefCounted m obj, PrimMonad m) => RefCtx -> WeakRef obj -> m (Maybe (Ref obj))
 - class RefCounted m obj | obj -> m where
- getRefCounter :: obj -> RefCounter m
 
 - newRef :: (RefCounted m obj, PrimMonad m) => RefCtx -> m () -> (RefCounter m -> obj) -> m (Ref obj)
 - data RefCounter m = RefCounter !(PrimVar (PrimState m) Int) !(m ())
 - newRefCounter :: PrimMonad m => m () -> m (RefCounter m)
 - incrementRefCounter :: PrimMonad m => RefCounter m -> m ()
 - decrementRefCounter :: (PrimMonad m, MonadMask m) => RefCounter m -> m ()
 - tryIncrementRefCounter :: PrimMonad m => RefCounter m -> m Bool
 - checkForgottenRefs :: forall m. (PrimMonad m, MonadThrow m) => RefCtx -> m ()
 - ignoreForgottenRefs :: (PrimMonad m, MonadCatch m) => RefCtx -> m ()
 - enableForgottenRefChecks :: PrimMonad m => RefCtx -> m ()
 - disableForgottenRefChecks :: PrimMonad m => RefCtx -> m ()
 - data RefCtx
 - withRefCtx :: (PrimMonad m, MonadThrow m) => (RefCtx -> m a) -> m a
 - newRefCtx :: PrimMonad m => m RefCtx
 - closeRefCtx :: forall m. (PrimMonad m, MonadThrow m) => RefCtx -> m ()
 
Using references
A reference to an object of type a. Use references to support prompt
 finalisation of object resources.
Rules of use:
- Each 
Refmust eventually be released exactly once withreleaseRef. - Use 
withRef, orDeRefto (temporarily) obtain the underlying object. - After calling 
releaseRef, the operationswithRefand patternDeRefmust not be used. - After calling 
releaseRef, an object obtained previously fromDeRefmust not be used. For this reason, it is advisable to usewithRefwhere possible, and be careful with use ofDeRef. - A 
Refmay be duplicated usingdupRefto produce an independent reference (which must itself be released withreleaseRef). 
All of these operations are thread safe. They are not async-exception safe
 however: the operations that allocate or deallocate must be called with
 async exceptions masked. This includes newRef, dupRef and releaseRef.
Provided that all these rules are followed, this guarantees that the object's finaliser will be run exactly once, promptly, when the final reference is released.
In debug mode (when using CPP define NO_IGNORE_ASSERTS), adherence to
 these rules are checked dynamically. These dynamic checks are however not
 thread safe, so it is not guaranteed that all violations are always detected.
Bundled Patterns
| pattern DeRef :: obj -> Ref obj | Get the object in a   | 
releaseRef :: (RefCounted m obj, PrimMonad m, MonadMask m) => Ref obj -> m () Source #
Release a reference to an object that will no longer be used (via this reference).
dupRef :: forall m obj. (RefCounted m obj, PrimMonad m, MonadThrow m) => Ref obj -> m (Ref obj) Source #
Duplicate an existing reference, to produce a new reference.
data RefException Source #
Constructors
| RefUseAfterRelease | |
| RefDoubleRelease | |
| RefNeverReleased RefId CallStack | Allocation site  | 
Instances
| Exception RefException Source # | |
Defined in Control.RefCount Methods toException :: RefException -> SomeException # fromException :: SomeException -> Maybe RefException # displayException :: RefException -> String #  | |
| Show RefException Source # | |
Defined in Control.RefCount Methods showsPrec :: Int -> RefException -> ShowS # show :: RefException -> String # showList :: [RefException] -> ShowS #  | |
Weak references
A "weak" reference to an object: that is, a reference that does not
 guarantee to keep the object alive. If however the object is still alive
 (due to other normal references still existing) then it can be converted
 back into a normal reference with deRefWeak.
Weak references do not themselves need to be released.
Constructors
| WeakRef a | 
mkWeakRef :: Ref obj -> WeakRef obj Source #
Given an existing normal reference, create a new weak reference.
mkWeakRefFromRaw :: obj -> WeakRef obj Source #
Given an existing raw reference, create a new weak reference.
deRefWeak :: (RefCounted m obj, PrimMonad m) => RefCtx -> WeakRef obj -> m (Maybe (Ref obj)) Source #
If the object is still alive, obtain a new normal reference. The normal
 rules for Ref apply, including the need to eventually call releaseRef.
Implementing objects with finalisers
class RefCounted m obj | obj -> m where Source #
Class of objects which support Ref.
For objects in this class the guarantee is that (when the Ref rules are
 followed) the object's finaliser is called exactly once.
Methods
getRefCounter :: obj -> RefCounter m Source #
newRef :: (RefCounted m obj, PrimMonad m) => RefCtx -> m () -> (RefCounter m -> obj) -> m (Ref obj) Source #
Make a new reference.
The given finaliser is run when the last reference is released. The finaliser is run with async exceptions masked.
Low level reference counts
data RefCounter m Source #
A reference counter with an optional finaliser action. Once the reference
 count reaches 0, the finaliser will be run.
Constructors
| RefCounter !(PrimVar (PrimState m) Int) !(m ()) | 
Instances
| Show (RefCounter m) Source # | |
Defined in Control.RefCount Methods showsPrec :: Int -> RefCounter m -> ShowS # show :: RefCounter m -> String # showList :: [RefCounter m] -> ShowS #  | |
| NFData (RefCounter m) Source # | NOTE: Only strict in the variable and not the referenced value.  | 
Defined in Control.RefCount Methods rnf :: RefCounter m -> () #  | |
newRefCounter :: PrimMonad m => m () -> m (RefCounter m) Source #
Make a reference counter with initial value 1.
The given finaliser is run when the reference counter reaches 0. The
 finaliser is run with async exceptions masked.
incrementRefCounter :: PrimMonad m => RefCounter m -> m () Source #
Increase the reference counter by one.
The count must be known (from context) to be non-zero already. Typically this will be because the caller has a reference already and is handing out another reference to some other code.
decrementRefCounter :: (PrimMonad m, MonadMask m) => RefCounter m -> m () Source #
Decrease the reference counter by one.
The count must be known (from context) to be non-zero. Typically this will be because the caller has a reference already (that they took out themselves or were given).
tryIncrementRefCounter :: PrimMonad m => RefCounter m -> m Bool Source #
Try to turn a "weak" reference on something into a proper reference.
 This is by analogy with deRefWeak :: Weak v -> IO (Maybe v), but for
 reference counts.
This amounts to trying to increase the reference count, but if it is already
 zero then this will fail. And unlike with addReference where such failure
 would be a programmer error, this corresponds to the case when the thing the
 reference count is tracking has been closed already.
The result is True when a strong reference has been obtained and False
 when upgrading fails.
Test API
checkForgottenRefs :: forall m. (PrimMonad m, MonadThrow m) => RefCtx -> m () Source #
Run a GC to try and see if any refs have been forgotten without being released. If so, this will throw a synchronous exception.
Note however that this is not the only place where RefNeverReleased
 exceptions can be thrown. All Ref operations poll for forgotten refs.
ignoreForgottenRefs :: (PrimMonad m, MonadCatch m) => RefCtx -> m () Source #
Ignore and reset the state of forgotten reference tracking. This ensures that any stale forgotten references are not reported later.
This is especillay important in QC tests with shrinking which otherwise leads to confusion.
enableForgottenRefChecks :: PrimMonad m => RefCtx -> m () Source #
In debug mode, enable forgotten reference checks.
disableForgottenRefChecks :: PrimMonad m => RefCtx -> m () Source #
In debug mode, disable forgotten reference checks.
Reference context
withRefCtx :: (PrimMonad m, MonadThrow m) => (RefCtx -> m a) -> m a Source #
newRefCtx :: PrimMonad m => m RefCtx Source #
Create a new RefCtx.
It is preferable to use withRefCtx.
closeRefCtx :: forall m. (PrimMonad m, MonadThrow m) => RefCtx -> m () Source #
Close a RefCtx.
It is preferable to use withRefCtx.