{- | Reference counting Data with a finalizer that will be called when the counter reached zero. Thread-safe. -} module Data.RefCount ( RefCount, newRefCount, incRefCount, decRefCount, ) where import Control.Monad import Data.IORef data RefCount = RefCount !(IO ()) !(IORef Int) newRefCount cleanup = RefCount cleanup `liftM` newIORef 1 incRefCount (RefCount _ ref) = atomicModifyIORef ref $ \x -> (succ x, ()) decRefCount (RefCount cleanup ref) = do refCnt <- atomicModifyIORef ref $ \x -> let x' = pred x in (x', x') when (refCnt == 0) cleanup