0 | module System.Posix.Pthreads
  1 |
  2 | import System.Posix.Pthreads.Prim as P
  3 | import public Control.Monad.Resource
  4 | import public Data.C.Ptr
  5 | import public System.Posix.Errno
  6 | import public System.Posix.Pthreads.Struct
  7 | import public System.Posix.Pthreads.Types
  8 | import System.Posix.Signal
  9 | import System.Posix.Time
 10 |
 11 | %default total
 12 |
 13 | export %inline
 14 | ELift1 World f => Resource f MutexT where
 15 |   cleanup m = lift1 {s = World} $ ffi (P.destroyMutex m)
 16 |
 17 | export %inline
 18 | ELift1 World f => Resource f CondT where
 19 |   cleanup m = lift1 {s = World} $ ffi (P.destroyCond m)
 20 |
 21 | ||| Returns the thread ID of the current thread.
 22 | export %inline
 23 | pthreadSelf : HasIO io => io PthreadT
 24 | pthreadSelf = primIO P.pthreadSelf
 25 |
 26 | ||| Blocks the current thread and waits for the given thread to terminate.
 27 | export %inline
 28 | pthreadJoin : Has Errno es => EIO1 f => PthreadT -> f es ()
 29 | pthreadJoin p = elift1 (P.pthreadJoin p)
 30 |
 31 | ||| Allocates and initializes a new mutex of the given type.
 32 | |||
 33 | ||| This must be freed with `destroyMutex`.
 34 | export
 35 | mkmutex : Has Errno es => EIO1 f => MutexType -> f es MutexT
 36 | mkmutex t = elift1 (P.mkmutex t)
 37 |
 38 | ||| Destroys a mutex and frees the memory allocated for it.
 39 | export %inline
 40 | destroyMutex : HasIO io => MutexT -> io ()
 41 | destroyMutex m = primIO (P.destroyMutex m)
 42 |
 43 | ||| Tries to lock the given mutex, blocking the calling thread
 44 | ||| in case it is already locked.
 45 | export %inline
 46 | lockMutex : Has Errno es => EIO1 f => MutexT -> f es ()
 47 | lockMutex p = elift1 (P.lockMutex p)
 48 |
 49 | ||| Like `lockMutex` but returns a boolean with `False` indicating
 50 | ||| that the lock timed out
 51 | export
 52 | timedlockMutex : Has Errno es => EIO1 f => MutexT -> Clock Duration -> f es Bool
 53 | timedlockMutex p cl = elift1 (P.timedlockMutex p cl)
 54 |
 55 | ||| Like `lockMutex` but returns `False` in case the mutex is
 56 | ||| already locked.
 57 | export
 58 | trylockMutex : Has Errno es => EIO1 f => MutexT -> f es Bool
 59 | trylockMutex p = elift1 (P.trylockMutex p)
 60 |
 61 | ||| Unlocks the given mutex.
 62 | |||
 63 | ||| This is an error if the calling thread is not the one holding
 64 | ||| the mutex's lock.
 65 | export %inline
 66 | unlockMutex : Has Errno es => EIO1 f => MutexT -> f es ()
 67 | unlockMutex p = elift1 (P.unlockMutex p)
 68 |
 69 | --------------------------------------------------------------------------------
 70 | -- CondT
 71 | --------------------------------------------------------------------------------
 72 |
 73 | ||| Allocates and initializes a new condition variable.
 74 | |||
 75 | ||| This must be freed with `destroyCond`.
 76 | export %inline
 77 | mkcond : Has Errno es => EIO1 f => f es CondT
 78 | mkcond = elift1 P.mkcond
 79 |
 80 | ||| Destroys a condition variable and frees the memory allocated for it.
 81 | export %inline
 82 | destroyCond : HasIO io => CondT -> io ()
 83 | destroyCond = primIO . destroyCond
 84 |
 85 | ||| Signals the given `pthread_cond_t`.
 86 | |||
 87 | ||| If several threads are waiting on the condition, it is unspecified
 88 | ||| which of them will be signalled. We are only guaranteed that at least
 89 | ||| of them will be woken up.
 90 | export %inline
 91 | condSignal : Has Errno es => EIO1 f => CondT -> f es ()
 92 | condSignal c = elift1 (condSignal c)
 93 |
 94 | ||| Broadcasts the given `pthread_cond_t`.
 95 | |||
 96 | ||| This will wake up all threads waiting on the given condition.
 97 | export %inline
 98 | condBroadcast : Has Errno es => EIO1 f => CondT -> f es ()
 99 | condBroadcast c = elift1 (condBroadcast c)
100 |
101 | ||| Blocks the given thread and waits for the given condition to
102 | ||| be signalled.
103 | |||
104 | ||| Note: The mutex must have been locked by the calling thread. The
105 | ||| lock is automatically released upon calling `condWait`, and when
106 | ||| the thread is woken up, the mutex will automatically be locked again.
107 | export %inline
108 | condWait : Has Errno es => EIO1 f => CondT -> MutexT -> f es ()
109 | condWait c m = elift1 (condWait c m)
110 |
111 | ||| Like `condWait` but will return `False` in case the operation timed out.
112 | export %inline
113 | condTimedwait : Has Errno es => EIO1 f => CondT -> MutexT -> Clock UTC -> f es Bool
114 | condTimedwait c m d = elift1 (condTimedwait c m d)
115 |
116 | --------------------------------------------------------------------------------
117 | -- Thread Cancelation
118 | --------------------------------------------------------------------------------
119 |
120 | ||| Sends a cancelation request to the given thread.
121 | export %inline
122 | pthreadCancel : Has Errno es => EIO1 f => PthreadT -> f es ()
123 | pthreadCancel t = elift1 (P.pthreadCancel t)
124 |
125 | ||| Tests for thread cancelation in the absence of other cancelation
126 | ||| points.
127 | export %inline
128 | pthreadTestCancel : HasIO io => io ()
129 | pthreadTestCancel = primIO P.pthreadTestCancel
130 |
131 | ||| Sets the current thread's cancel type returning the previous cancel type.
132 | export %inline
133 | setCancelType : HasIO io => CancelType -> io CancelType
134 | setCancelType = primIO . P.setCancelType
135 |
136 | ||| Sets the current thread's cancel state returning the previous cancel state.
137 | export %inline
138 | setCancelState : HasIO io => CancelState -> io CancelState
139 | setCancelState = primIO . P.setCancelState
140 |
141 | --------------------------------------------------------------------------------
142 | -- Signals and Threads
143 | --------------------------------------------------------------------------------
144 |
145 | ||| Adjust the thread's signal mask according to the given `How`
146 | ||| and signal set.
147 | export %inline
148 | pthreadSigmask : Has Errno es => EIO1 f => How -> List Signal -> f es ()
149 | pthreadSigmask h ss = elift1 (P.pthreadSigmask h ss)
150 |
151 | ||| Returns the current signal mask of the thread.
152 | |||
153 | ||| Note: This allocates a new `sigset_t` pointer and returns the
154 | |||       previously set signal mask. Client code is responsible to
155 | |||       free the memory for this once it is no longer used.
156 | export %inline
157 | pthreadSiggetmask : HasIO io => io SigsetT
158 | pthreadSiggetmask = primIO P.pthreadSiggetmask
159 |
160 |
161 | ||| Sends the given signal to the given thread.
162 | export %inline
163 | pthreadKill : Has Errno es => EIO1 f => PthreadT -> Signal -> f es ()
164 | pthreadKill t s = elift1 (P.pthreadKill t s)
165 |