hans-2.1.0.0: src/Hans/Ports.hs
module Hans.Ports (
-- * Port Management
PortManager
, emptyPortManager
, isReserved
, reserve
, unreserve
, nextPort
) where
import Control.Monad (MonadPlus(mzero),guard)
import Data.List (delete)
import qualified Data.Set as Set
-- Port Management -------------------------------------------------------------
data PortManager i = PortManager
{ portNext :: [i]
, portActive :: Set.Set i
}
emptyPortManager :: [i] -> PortManager i
emptyPortManager range = PortManager
{ portNext = range
, portActive = Set.empty
}
isReserved :: (Eq i, Ord i) => i -> PortManager i -> Bool
isReserved i pm = i `Set.member` portActive pm
reserve :: (MonadPlus m, Eq i, Ord i) => i -> PortManager i -> m (PortManager i)
reserve i pm = do
guard (not (isReserved i pm))
return $! pm
{ portNext = delete i (portNext pm)
, portActive = Set.insert i (portActive pm)
}
unreserve :: (MonadPlus m, Eq i, Ord i)
=> i -> PortManager i -> m (PortManager i)
unreserve i pm = do
guard (isReserved i pm)
return $! pm
{ portNext = i : portNext pm
, portActive = Set.delete i (portActive pm)
}
nextPort :: (MonadPlus m, Eq i, Ord i)
=> PortManager i -> m (i, PortManager i)
nextPort pm = case portNext pm of
[] -> mzero
i:_ -> do
pm' <- reserve i pm
return $! (i,pm')