grapesy-1.0.0: kvstore/KVStore/Util/Store.hs
-- | Simple in-memory key-value var
--
-- Intended for qualified import.
--
-- > import KVStore.Util.Store (Store)
-- > import KVStore.Util.Store qualified as Store
module KVStore.Util.Store (
Store -- opaque
-- * API
, new
, get
, putIfAbsent
, replace
, remove
) where
import Control.Concurrent
import Data.Hashable (Hashable)
import Data.HashMap.Strict (HashMap)
import Data.HashMap.Strict qualified as HashMap
{-------------------------------------------------------------------------------
Definition
-------------------------------------------------------------------------------}
newtype Store a b = Wrap {
unwrap :: MVar (HashMap a b)
}
{-------------------------------------------------------------------------------
API
-------------------------------------------------------------------------------}
new :: IO (Store a b)
new = Wrap <$> newMVar HashMap.empty
-- | Get value associated with the key, if it exists
get :: Hashable a => Store a b -> a -> IO (Maybe b)
get store key = withStore store $ HashMap.lookup key
-- | Remove an key from the map
remove :: Hashable a => Store a b -> a -> IO ()
remove store key = modifyStore_ store $ HashMap.delete key
-- | Put a new key/value pair into the var
--
-- Returns 'True' on success, or 'False' if they key was already present.
putIfAbsent :: Hashable a => Store a b -> a -> b -> IO Bool
putIfAbsent store key value =
modifyStore store $ \hm ->
case HashMap.lookup key hm of
Nothing -> (HashMap.insert key value hm, True)
Just _ -> (hm, False)
-- | Replace the value associated with the key, if the key already exists
--
-- Returns 'True' if the value was successfully replaced, or 'False' if the key
-- was not present.
replace :: Hashable a => Store a b -> a -> b -> IO Bool
replace store key newValue =
modifyStore store $ \hm ->
case HashMap.lookup key hm of
Nothing -> (hm, False)
Just _ -> (HashMap.insert key newValue hm, True)
{-------------------------------------------------------------------------------
Internal: wrap pure operations
-------------------------------------------------------------------------------}
withStore :: Store a b -> (HashMap a b -> r) -> IO r
withStore store f = withMVar (unwrap store) $ return . f
modifyStore :: Store a b -> (HashMap a b -> (HashMap a b, r)) -> IO r
modifyStore store f = modifyMVar (unwrap store) $ return . f
modifyStore_ :: Store a b -> (HashMap a b -> HashMap a b) -> IO ()
modifyStore_ store f = modifyMVar_ (unwrap store) $ return . f