summaryrefslogtreecommitdiff
path: root/include/mupdf/helpers/mu-threads.h
blob: 7cdd817babfda8a95d4ad97463a4d974fde2aac8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
#ifndef MUPDF_HELPERS_MU_THREADS_H
#define MUPDF_HELPERS_MU_THREADS_H

/*
	Simple threading helper library.
	Includes implementations for Windows, pthreads,
	and "no threads".

	The "no threads" implementation simply provides types
	and stub functions so that things will build, but abort
	if we try to call them. This simplifies the job for
	calling functions.

	To build this library on a platform with no threading,
	define DISABLE_MUTHREADS (or extend the ifdeffery below
	so that it does so).

	To build this library on a platform that uses a
	threading model other than windows threads or pthreads,
	extend the #ifdeffery below to set MUTHREAD_IMPL_TYPE
	to an unused value, and modify mu-threads.c
	appropriately.
*/

#if !defined(DISABLE_MUTHREADS)
#if defined(_WIN32) || defined(_WIN64)
#define MU_THREAD_IMPL_TYPE 1
#elif defined(HAVE_PTHREADS)
#define MU_THREAD_IMPL_TYPE 2
#else
#define DISABLE_MUTHREADS
#endif
#endif

/*
	Types
*/
typedef struct mu_thread_s mu_thread;
typedef struct mu_semaphore_s mu_semaphore;
typedef struct mu_mutex_s mu_mutex;

/*
	Semaphores

	Created with a value of 0. Triggering a semaphore
	increments the value. Waiting on a semaphore reduces
	the value, blocking if it would become negative.

	Never increment the value of a semaphore above 1, as
	this has undefined meaning in this implementation.
*/

/*
	mu_create_semaphore: Create a semaphore.

	sem: Pointer to a mu_semaphore to populate.

	Returns non-zero for error.
*/
int mu_create_semaphore(mu_semaphore *sem);

/*
	mu_destroy_semaphore: Destroy a semaphore.
	Semaphores may safely be destroyed multiple
	times. Any semaphore initialised to zeros is
	safe to destroy.

	Never destroy a semaphore that may be being waited
	upon, as this has undefined meaning in this
	implementation.

	sem: Pointer to a mu_semaphore to destroy.
*/
void mu_destroy_semaphore(mu_semaphore *sem);

/*
	mu_trigger_semaphore: Increment the value of the
	semaphore. Never blocks.

	sem: The semaphore to increment.

	Returns non-zero on error.
*/
int mu_trigger_semaphore(mu_semaphore *sem);

/*
	mu_wait_semaphore: Decrement the value of the
	semaphore, blocking if this would involve making
	the value negative.

	sem: The semaphore to decrement.

	Returns non-zero on error.
*/
int mu_wait_semaphore(mu_semaphore *sem);

/*
	Threads
*/

/*
	The type for the function that a thread runs.

	arg: User supplied data.
*/
typedef void (mu_thread_fn)(void *arg);

/*
	mu_create_thread: Create a thread to run the
	supplied function with the supplied argument.

	th: Pointer to mu_thread to populate with created
	threads information.

	fn: The function for the thread to run.

	arg: The argument to pass to fn.
*/
int mu_create_thread(mu_thread *th, mu_thread_fn *fn, void *arg);

/*
	mu_destroy_thread: Destroy a thread. This function
	blocks until a thread has terminated normally, and
	destroys its storage. A mu_thread may safely be destroyed
	multiple times, as may any mu_thread initialised with
	zeros.

	th: Pointer to mu_thread to destroy.
*/
void mu_destroy_thread(mu_thread *th);

/*
	Mutexes

	This implementation does not specify whether
	mutexes are recursive or not.
*/

/*
	mu_create_mutex: Create a mutex.

	mutex: pointer to a mu_mutex to populate.

	Returns non-zero on error.
*/
int mu_create_mutex(mu_mutex *mutex);

/*
	mu_destroy_mutex: Destroy a mutex. A mu_mutex may
	safely be destroyed several times, as may a mu_mutex
	initialised with zeros. Never destroy locked mu_mutex.

	mutex: Pointer to mu_mutex to destroy.
*/
void mu_destroy_mutex(mu_mutex *mutex);

/*
	mu_lock_mutex: Lock a mutex.

	mutex: Mutex to lock.
*/
void mu_lock_mutex(mu_mutex *mutex);

/*
	mu_unlock_mutex: Unlock a mutex.

	mutex: Mutex to unlock.
*/
void mu_unlock_mutex(mu_mutex *mutex);


/*
	Everything under this point is implementation specific.
	Only people looking to extend the capabilities of this
	helper module should need to look below here.
*/

#ifdef DISABLE_MUTHREADS

/* Null implementation */
struct mu_semaphore_s
{
	int dummy;
};

struct mu_thread_s
{
	int dummy;
};

struct mu_mutex_s
{
	int dummy;
};

#elif MU_THREAD_IMPL_TYPE == 1

#include <windows.h>

/* Windows threads */
struct mu_semaphore_s
{
	HANDLE handle;
};

struct mu_thread_s
{
	HANDLE handle;
	mu_thread_fn *fn;
	void *arg;
};

struct mu_mutex_s
{
	CRITICAL_SECTION mutex;
};

#elif MU_THREAD_IMPL_TYPE == 2

/*
	PThreads - without working unnamed semaphores.

	Neither ios nor OSX supports unnamed semaphores.
	Named semaphores are a pain to use, so we implement
	our own sempahores using condition variables and
	mutexes.
*/

#include <pthread.h>

struct mu_semaphore_s
{
	int count;
	pthread_mutex_t mutex;
	pthread_cond_t cond;
};

struct mu_thread_s
{
	pthread_t thread;
	mu_thread_fn *fn;
	void *arg;
};

struct mu_mutex_s
{
	pthread_mutex_t mutex;
};

/*
	Add new threading implementations here, with
	#elif MU_THREAD_IMPL_TYPE == 3... etc.
*/

#else
#error Unknown MU_THREAD_IMPL_TYPE setting
#endif

#endif /* MUPDF_HELPERS_MU_THREADS_H */