module Network.GnuTLS.RefCount (RefCount, newRefCount, allocRef, freeRef, addRefFinalizer) where import Data.IORef -- | A simple reference count with a list of finalizers. newtype RefCount = RC (IORef (Int, [IO ()])) -- | Create a new reference count with one reference and -- the suplied action as the initial finalizer. newRefCount :: IO () -> IO RefCount newRefCount act = return . RC =<< newIORef (1, [act]) -- | Allocate an additional reference to the RefCount. allocRef :: RefCount -> IO () allocRef (RC ref) = atomicModifyIORef ref $ \(iv,cs) -> ((iv+1,cs),()) -- | Free a reference to the RefCount. If the number -- of references goes down to zero all the associated -- finalizers are fired. The RefCount is left in -- unusable state when all the references have been -- deleted. freeRef :: RefCount -> IO () freeRef (RC ref) = atomicModifyIORef ref handler >>= sequence_ where handler (1,cs) = (error "Double free of RefCount",cs) handler (k,cs) = ((k-1,cs), []) -- | Associate an additional finalizer with the RefCount. addRefFinalizer :: RefCount -> IO () -> IO () addRefFinalizer (RC ref) c = atomicModifyIORef ref $ \(iv,cs) -> ((iv,c:cs),())