{-# LINE 1 "System/Posix/Semaphore.hsc" #-}{-# LANGUAGE Safe #-}{-# LANGUAGE CApiFFI #-}{-# LANGUAGE InterruptibleFFI #-}------------------------------------------------------------------------------- |-- Module : System.Posix.Semaphore-- Copyright : (c) Daniel Franke 2007-- License : BSD-style (see the file libraries/base/LICENSE)---- Maintainer : libraries@haskell.org-- Stability : experimental-- Portability : non-portable (requires POSIX)---- POSIX named semaphore support.-------------------------------------------------------------------------------moduleSystem.Posix.Semaphore(OpenSemFlags (..),Semaphore (),semOpen ,semUnlink ,semWait ,semWaitInterruptible ,semTryWait ,semThreadWait ,semPost ,semGetValue )whereimportForeign.CimportForeign.ForeignPtrhiding(newForeignPtr)importForeign.ConcurrentimportForeign.PtrimportSystem.Posix.TypesimportControl.ConcurrentimportData.Bits{-# LINE 39 "System/Posix/Semaphore.hsc" #-}importForeign.MarshalimportForeign.Storable{-# LINE 42 "System/Posix/Semaphore.hsc" #-}{-# LINE 44 "System/Posix/Semaphore.hsc" #-}importSystem.Posix.Internals(hostIsThreaded){-# LINE 49 "System/Posix/Semaphore.hsc" #-}dataOpenSemFlags =OpenSemFlags {OpenSemFlags -> Bool
semCreate ::Bool,-- ^ If true, create the semaphore if it-- does not yet exist.OpenSemFlags -> Bool
semExclusive ::Bool-- ^ If true, throw an exception if the-- semaphore already exists.}newtypeSemaphore =Semaphore (ForeignPtr())-- | Open a named semaphore with the given name, flags, mode, and initial-- value.semOpen ::String->OpenSemFlags ->FileMode->Int->IOSemaphore semOpen :: String -> OpenSemFlags -> FileMode -> Int -> IO Semaphore
semOpen String
name OpenSemFlags
flags FileMode
mode Int
value =letcflags :: Int
cflags =(ifOpenSemFlags -> Bool
semCreate OpenSemFlags
flags thenInt
64elseInt
0)Int -> Int -> Int
forall a. Bits a => a -> a -> a
.|.{-# LINE 65 "System/Posix/Semaphore.hsc" #-}(ifOpenSemFlags -> Bool
semExclusive OpenSemFlags
flags thenInt
128elseInt
0){-# LINE 66 "System/Posix/Semaphore.hsc" #-}semOpen' :: CString -> IO Semaphore
semOpen' CString
cname =doPtr ()
sem <-String -> String -> IO (Ptr ()) -> IO (Ptr ())
forall a. String -> String -> IO (Ptr a) -> IO (Ptr a)
throwErrnoPathIfNullString
"semOpen"String
name (IO (Ptr ()) -> IO (Ptr ())) -> IO (Ptr ()) -> IO (Ptr ())
forall a b. (a -> b) -> a -> b
$CString -> CInt -> FileMode -> CUInt -> IO (Ptr ())
sem_open CString
cname (Int -> CInt
forall a. Enum a => Int -> a
toEnumInt
cflags )FileMode
mode (Int -> CUInt
forall a. Enum a => Int -> a
toEnumInt
value )ForeignPtr ()
fptr <-Ptr () -> IO () -> IO (ForeignPtr ())
forall a. Ptr a -> IO () -> IO (ForeignPtr a)
newForeignPtrPtr ()
sem (Ptr () -> IO ()
finalize Ptr ()
sem )Semaphore -> IO Semaphore
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return(Semaphore -> IO Semaphore) -> Semaphore -> IO Semaphore
forall a b. (a -> b) -> a -> b
$ForeignPtr () -> Semaphore
Semaphore ForeignPtr ()
fptr finalize :: Ptr () -> IO ()
finalize Ptr ()
sem =String -> String -> IO CInt -> IO ()
forall a. (Eq a, Num a) => String -> String -> IO a -> IO ()
throwErrnoPathIfMinus1_String
"semOpen"String
name (IO CInt -> IO ()) -> IO CInt -> IO ()
forall a b. (a -> b) -> a -> b
$Ptr () -> IO CInt
sem_close Ptr ()
sem inString -> (CString -> IO Semaphore) -> IO Semaphore
forall a. String -> (CString -> IO a) -> IO a
withCAStringString
name CString -> IO Semaphore
semOpen' -- | Delete the semaphore with the given name.semUnlink ::String->IO()semUnlink :: String -> IO ()
semUnlink String
name =String -> (CString -> IO ()) -> IO ()
forall a. String -> (CString -> IO a) -> IO a
withCAStringString
name CString -> IO ()
semUnlink' wheresemUnlink' :: CString -> IO ()
semUnlink' CString
cname =String -> String -> IO CInt -> IO ()
forall a. (Eq a, Num a) => String -> String -> IO a -> IO ()
throwErrnoPathIfMinus1_String
"semUnlink"String
name (IO CInt -> IO ()) -> IO CInt -> IO ()
forall a b. (a -> b) -> a -> b
$CString -> IO CInt
sem_unlink CString
cname -- | Lock the semaphore, blocking until it becomes available. Since this-- is done through a system call, this will block the *entire runtime*,-- not just the current thread. If this is not the behaviour you want,-- use semThreadWait instead.semWait ::Semaphore ->IO()semWait :: Semaphore -> IO ()
semWait (Semaphore ForeignPtr ()
fptr )=ForeignPtr () -> (Ptr () -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtrForeignPtr ()
fptr Ptr () -> IO ()
semWait' wheresemWait' :: Ptr () -> IO ()
semWait' Ptr ()
sem =String -> IO CInt -> IO ()
forall a. (Eq a, Num a) => String -> IO a -> IO ()
throwErrnoIfMinus1Retry_String
"semWait"(IO CInt -> IO ()) -> IO CInt -> IO ()
forall a b. (a -> b) -> a -> b
$Ptr () -> IO CInt
sem_wait Ptr ()
sem -- | Lock the semaphore, blocking until it becomes available.---- Unlike 'semWait', this wait operation can be interrupted with-- an asynchronous exception (e.g. a call to 'throwTo' from another thread).semWaitInterruptible ::Semaphore ->IOBoolsemWaitInterruptible :: Semaphore -> IO Bool
semWaitInterruptible (Semaphore ForeignPtr ()
fptr )=ForeignPtr () -> (Ptr () -> IO Bool) -> IO Bool
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtrForeignPtr ()
fptr Ptr () -> IO Bool
semWait' wheresemWait' :: Ptr () -> IO Bool
semWait' Ptr ()
sem =doCInt
res <-Ptr () -> IO CInt
sem_wait_interruptible Ptr ()
sem ifCInt
res CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
==CInt
0thenBool -> IO Bool
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
returnBool
TrueelsedoErrno
errno <-IO Errno
getErrnoifErrno
errno Errno -> Errno -> Bool
forall a. Eq a => a -> a -> Bool
==Errno
eINTRthenBool -> IO Bool
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
returnBool
FalseelseString -> IO Bool
forall a. String -> IO a
throwErrnoString
"semWaitInterrruptible"-- | Attempt to lock the semaphore without blocking. Immediately return-- False if it is not available.semTryWait ::Semaphore ->IOBoolsemTryWait :: Semaphore -> IO Bool
semTryWait (Semaphore ForeignPtr ()
fptr )=ForeignPtr () -> (Ptr () -> IO Bool) -> IO Bool
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtrForeignPtr ()
fptr Ptr () -> IO Bool
semTrywait' wheresemTrywait' :: Ptr () -> IO Bool
semTrywait' Ptr ()
sem =doCInt
res <-Ptr () -> IO CInt
sem_trywait Ptr ()
sem (ifCInt
res CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
==CInt
0thenBool -> IO Bool
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
returnBool
TrueelsedoErrno
errno <-IO Errno
getErrno(ifErrno
errno Errno -> Errno -> Bool
forall a. Eq a => a -> a -> Bool
==Errno
eINTRthenPtr () -> IO Bool
semTrywait' Ptr ()
sem elseifErrno
errno Errno -> Errno -> Bool
forall a. Eq a => a -> a -> Bool
==Errno
eAGAINthenBool -> IO Bool
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
returnBool
FalseelseString -> IO Bool
forall a. String -> IO a
throwErrnoString
"semTrywait"))-- | Poll the semaphore until it is available, then lock it. Unlike-- semWait, this will block only the current thread rather than the-- entire process.semThreadWait ::Semaphore ->IO()semThreadWait :: Semaphore -> IO ()
semThreadWait Semaphore
sem -- N.B. semWait can be safely used in the case of the threaded runtime, where-- the safe foreign call will be performed in its own thread, thereby not-- blocking the process.|Bool
hostIsThreaded=Semaphore -> IO ()
semWait Semaphore
sem |Bool
otherwise=doBool
res <-Semaphore -> IO Bool
semTryWait Semaphore
sem ifBool
res then() -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return()elsedoIO ()
yieldIO () -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>>Semaphore -> IO ()
semThreadWait Semaphore
sem -- | Unlock the semaphore.semPost ::Semaphore ->IO()semPost :: Semaphore -> IO ()
semPost (Semaphore ForeignPtr ()
fptr )=ForeignPtr () -> (Ptr () -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtrForeignPtr ()
fptr Ptr () -> IO ()
semPost' wheresemPost' :: Ptr () -> IO ()
semPost' Ptr ()
sem =String -> IO CInt -> IO ()
forall a. (Eq a, Num a) => String -> IO a -> IO ()
throwErrnoIfMinus1Retry_String
"semPost"(IO CInt -> IO ()) -> IO CInt -> IO ()
forall a b. (a -> b) -> a -> b
$Ptr () -> IO CInt
sem_post Ptr ()
sem -- | Return the semaphore's current value.semGetValue ::Semaphore ->IOInt{-# LINE 140 "System/Posix/Semaphore.hsc" #-}semGetValue(Semaphorefptr)=withForeignPtrfptrsemGetValue'wheresemGetValue'sem=alloca(semGetValue_sem)semGetValue_ ::Ptr()->PtrCInt->IOIntsemGetValue_ :: Ptr () -> Ptr CInt -> IO Int
semGetValue_ Ptr ()
sem Ptr CInt
ptr =doString -> IO Int -> IO ()
forall a. (Eq a, Num a) => String -> IO a -> IO ()
throwErrnoIfMinus1Retry_String
"semGetValue"(IO Int -> IO ()) -> IO Int -> IO ()
forall a b. (a -> b) -> a -> b
$Ptr () -> Ptr CInt -> IO Int
sem_getvalue Ptr ()
sem Ptr CInt
ptr CInt
cint <-Ptr CInt -> IO CInt
forall a. Storable a => Ptr a -> IO a
peekPtr CInt
ptr Int -> IO Int
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return(Int -> IO Int) -> Int -> IO Int
forall a b. (a -> b) -> a -> b
$CInt -> Int
forall a. Enum a => a -> Int
fromEnumCInt
cint foreignimportcapisafe"semaphore.h sem_getvalue"sem_getvalue ::Ptr()->PtrCInt->IOInt{-# LINE 156 "System/Posix/Semaphore.hsc" #-}foreignimportcapisafe"semaphore.h sem_open"sem_open ::CString->CInt->CMode->CUInt->IO(Ptr())foreignimportcapisafe"semaphore.h sem_close"sem_close ::Ptr()->IOCIntforeignimportcapisafe"semaphore.h sem_unlink"sem_unlink ::CString->IOCIntforeignimportcapisafe"semaphore.h sem_wait"sem_wait ::Ptr()->IOCIntforeignimportcapiinterruptible"semaphore.h sem_wait"sem_wait_interruptible ::Ptr()->IOCIntforeignimportcapisafe"semaphore.h sem_trywait"sem_trywait ::Ptr()->IOCIntforeignimportcapisafe"semaphore.h sem_post"sem_post ::Ptr()->IOCInt

AltStyle によって変換されたページ (->オリジナル) /