1 #ifndef MUPDF_HELPERS_MU_THREADS_H 2 #define MUPDF_HELPERS_MU_THREADS_H 3 4 /* 5 Simple threading helper library. 6 Includes implementations for Windows, pthreads, 7 and "no threads". 8 9 The "no threads" implementation simply provides types 10 and stub functions so that things will build, but abort 11 if we try to call them. This simplifies the job for 12 calling functions. 13 14 To build this library on a platform with no threading, 15 define DISABLE_MUTHREADS (or extend the ifdeffery below 16 so that it does so). 17 18 To build this library on a platform that uses a 19 threading model other than windows threads or pthreads, 20 extend the #ifdeffery below to set MUTHREAD_IMPL_TYPE 21 to an unused value, and modify mu-threads.c 22 appropriately. 23 */ 24 25 #if !defined(DISABLE_MUTHREADS) 26 #ifdef _WIN32 27 #define MU_THREAD_IMPL_TYPE 1 28 #elif defined(HAVE_PTHREAD) 29 #define MU_THREAD_IMPL_TYPE 2 30 #else 31 #define DISABLE_MUTHREADS 32 #endif 33 #endif 34 35 /* 36 Types 37 */ 38 typedef struct mu_thread mu_thread; 39 typedef struct mu_semaphore mu_semaphore; 40 typedef struct mu_mutex mu_mutex; 41 42 /* 43 Semaphores 44 45 Created with a value of 0. Triggering a semaphore 46 increments the value. Waiting on a semaphore reduces 47 the value, blocking if it would become negative. 48 49 Never increment the value of a semaphore above 1, as 50 this has undefined meaning in this implementation. 51 */ 52 53 /* 54 Create a semaphore. 55 56 sem: Pointer to a mu_semaphore to populate. 57 58 Returns non-zero for error. 59 */ 60 int mu_create_semaphore(mu_semaphore *sem); 61 62 /* 63 Destroy a semaphore. 64 Semaphores may safely be destroyed multiple 65 times. Any semaphore initialised to zeros is 66 safe to destroy. 67 68 Never destroy a semaphore that may be being waited 69 upon, as this has undefined meaning in this 70 implementation. 71 72 sem: Pointer to a mu_semaphore to destroy. 73 */ 74 void mu_destroy_semaphore(mu_semaphore *sem); 75 76 /* 77 Increment the value of the 78 semaphore. Never blocks. 79 80 sem: The semaphore to increment. 81 82 Returns non-zero on error. 83 */ 84 int mu_trigger_semaphore(mu_semaphore *sem); 85 86 /* 87 Decrement the value of the 88 semaphore, blocking if this would involve making 89 the value negative. 90 91 sem: The semaphore to decrement. 92 93 Returns non-zero on error. 94 */ 95 int mu_wait_semaphore(mu_semaphore *sem); 96 97 /* 98 Threads 99 */ 100 101 /* 102 The type for the function that a thread runs. 103 104 arg: User supplied data. 105 */ 106 typedef void (mu_thread_fn)(void *arg); 107 108 /* 109 Create a thread to run the 110 supplied function with the supplied argument. 111 112 th: Pointer to mu_thread to populate with created 113 threads information. 114 115 fn: The function for the thread to run. 116 117 arg: The argument to pass to fn. 118 */ 119 int mu_create_thread(mu_thread *th, mu_thread_fn *fn, void *arg); 120 121 /* 122 Destroy a thread. This function 123 blocks until a thread has terminated normally, and 124 destroys its storage. A mu_thread may safely be destroyed 125 multiple times, as may any mu_thread initialised with 126 zeros. 127 128 th: Pointer to mu_thread to destroy. 129 */ 130 void mu_destroy_thread(mu_thread *th); 131 132 /* 133 Mutexes 134 135 This implementation does not specify whether 136 mutexes are recursive or not. 137 */ 138 139 /* 140 Create a mutex. 141 142 mutex: pointer to a mu_mutex to populate. 143 144 Returns non-zero on error. 145 */ 146 int mu_create_mutex(mu_mutex *mutex); 147 148 /* 149 Destroy a mutex. A mu_mutex may 150 safely be destroyed several times, as may a mu_mutex 151 initialised with zeros. Never destroy locked mu_mutex. 152 153 mutex: Pointer to mu_mutex to destroy. 154 */ 155 void mu_destroy_mutex(mu_mutex *mutex); 156 157 /* 158 Lock a mutex. 159 160 mutex: Mutex to lock. 161 */ 162 void mu_lock_mutex(mu_mutex *mutex); 163 164 /* 165 Unlock a mutex. 166 167 mutex: Mutex to unlock. 168 */ 169 void mu_unlock_mutex(mu_mutex *mutex); 170 171 /* 172 Everything under this point is implementation specific. 173 Only people looking to extend the capabilities of this 174 helper module should need to look below here. 175 */ 176 177 #ifdef DISABLE_MUTHREADS 178 179 /* Null implementation */ 180 struct mu_semaphore 181 { 182 int dummy; 183 }; 184 185 struct mu_thread 186 { 187 int dummy; 188 }; 189 190 struct mu_mutex 191 { 192 int dummy; 193 }; 194 195 #elif MU_THREAD_IMPL_TYPE == 1 196 197 #include <windows.h> 198 199 /* Windows threads */ 200 struct mu_semaphore 201 { 202 HANDLE handle; 203 }; 204 205 struct mu_thread 206 { 207 HANDLE handle; 208 mu_thread_fn *fn; 209 void *arg; 210 }; 211 212 struct mu_mutex 213 { 214 CRITICAL_SECTION mutex; 215 }; 216 217 #elif MU_THREAD_IMPL_TYPE == 2 218 219 /* 220 PThreads - without working unnamed semaphores. 221 222 Neither ios nor OSX supports unnamed semaphores. 223 Named semaphores are a pain to use, so we implement 224 our own semaphores using condition variables and 225 mutexes. 226 */ 227 228 #include <pthread.h> 229 230 struct mu_semaphore 231 { 232 int count; 233 pthread_mutex_t mutex; 234 pthread_cond_t cond; 235 }; 236 237 struct mu_thread 238 { 239 pthread_t thread; 240 mu_thread_fn *fn; 241 void *arg; 242 }; 243 244 struct mu_mutex 245 { 246 pthread_mutex_t mutex; 247 }; 248 249 /* 250 Add new threading implementations here, with 251 #elif MU_THREAD_IMPL_TYPE == 3... etc. 252 */ 253 254 #else 255 #error Unknown MU_THREAD_IMPL_TYPE setting 256 #endif 257 258 #endif /* MUPDF_HELPERS_MU_THREADS_H */ 259