{-# LANGUAGE MultiParamTypeClasses, TypeFamilies, FlexibleInstances, FlexibleContexts, UndecidableInstances #-} module PrioritySync.Internal.Room (Room, newRoom, RoomCore.userData, inUse, Claim, claimedRoom, claimedThread, ClaimMode(..), claim, approveClaims, approve, RoomCore.isEmpty) where import PrioritySync.Internal.RoomGroup import PrioritySync.Internal.ClaimContext import PrioritySync.Internal.RoomCore as RoomCore import PrioritySync.Internal.RoomConstraint import Control.Concurrent.STM import Data.Map as Map -- | Temporarily 'Acquire', and then release, or 'Release', and then acquire, some 'Room's for the duration of a critical section. -- A simple example where a room might be used to prevent interleaving of 'stdout': -- -- > room <- newRoom (MaxThreads 1) -- > forkIO $ claim Acquire (Default,room) $ putStrLn "Hello World!" -- > forkIO $ claim Acquire (Default,room) $ putStrLn "Foo! Bar!" claim :: (RoomGroup c,ClaimContext c) => ClaimMode -> c -> IO a -> IO a claim claim_mode c actionIO = do room_context_data <- newTVarIO (error "claim: BaseRoomContextData not yet available (please report a bug against the priority-sync package)") claim_ (Map.fromList $ Prelude.map (flip (,) claim_mode) $ roomsOf c) (\cs -> writeTVar room_context_data =<< approveClaimsEntering c cs) (\cs -> writeTVar room_context_data =<< approveClaimsExiting c cs) (waitingAction c =<< readTVar room_context_data) actionIO