ObjFW  Check-in [c4f724070a]

Overview
Comment:OFThread: Configurable priority and stack size
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: c4f724070a065e9c06f862b6ce883bb159689a17158b8a4260a6df8f2c721aeb
User & Date: js on 2014-07-19 16:27:02
Other Links: manifest | tags
Context
2014-07-23
19:34
threading: Get rid of warnings with old compilers check-in: 9e60532254 user: js tags: trunk
2014-07-19
16:27
OFThread: Configurable priority and stack size check-in: c4f724070a user: js tags: trunk
16:16
Fix MinGW32 build check-in: 083e05b444 user: js tags: trunk
Changes

Modified src/OFThread.h from [dbfdd8a5a4] to [c8632579ec].

54
55
56
57
58
59
60

61
62
63
64
65
66
67
{
# ifdef OF_THREAD_M
@public
# else
@private
# endif
	of_thread_t _thread;

	enum {
		OF_THREAD_NOT_RUNNING,
		OF_THREAD_RUNNING,
		OF_THREAD_WAITING_FOR_JOIN
	} _running;
	void *_pool;
# ifdef OF_HAVE_BLOCKS







>







54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
{
# ifdef OF_THREAD_M
@public
# else
@private
# endif
	of_thread_t _thread;
	of_thread_attr_t _attr;
	enum {
		OF_THREAD_NOT_RUNNING,
		OF_THREAD_RUNNING,
		OF_THREAD_WAITING_FOR_JOIN
	} _running;
	void *_pool;
# ifdef OF_HAVE_BLOCKS
75
76
77
78
79
80
81


82
83
84
85
86
87
88
}

# ifdef OF_HAVE_PROPERTIES
#  ifdef OF_HAVE_BLOCKS
@property (copy) of_thread_block_t threadBlock;
#  endif
@property (copy) OFString *name;


# endif

/*!
 * @brief Creates a new thread.
 *
 * @return A new, autoreleased thread
 */







>
>







76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
}

# ifdef OF_HAVE_PROPERTIES
#  ifdef OF_HAVE_BLOCKS
@property (copy) of_thread_block_t threadBlock;
#  endif
@property (copy) OFString *name;
@property float priority;
@property size_t stackSize;
# endif

/*!
 * @brief Creates a new thread.
 *
 * @return A new, autoreleased thread
 */
211
212
213
214
215
216
217

































218
219

/*!
 * @brief Sets the name for the thread.
 *
 * @param name The name for the thread
 */
- (void)setName: (OFString*)name;

































#endif
@end







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


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

/*!
 * @brief Sets the name for the thread.
 *
 * @param name The name for the thread
 */
- (void)setName: (OFString*)name;

/*!
 * @brief Returns the priority of the thread.
 *
 * @return The priority of the thread
 */
- (float)priority;

/*!
 * @brief Sets the priority of the thread.
 *
 * @note This has to be set before the thread is started!
 *
 * @param priority The priority for the thread, with 0.0 being the lowest and
 *		   1.0 the highest
 */
- (void)setPriority: (float)priority;

/*!
 * @brief Returns the stack size of the thread.
 *
 * @return The stack size of the thread
 */
- (size_t)stackSize;

/*!
 * @brief Sets the stack size of the thread.
 *
 * @note This has to be set before the thread is started!
 *
 * @param stackSize The stack size for the thread
 */
- (void)setStackSize: (size_t)stackSize;
#endif
@end

Modified src/OFThread.m from [8e23861680] to [b9ff0cb8da].

89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
		@throw [OFInitializationFailedException
		    exceptionWithClass: [thread class]];

	thread->_pool = objc_autoreleasePoolPush();

	/*
	 * Nasty workaround for thread implementations which can't return a
	 * value on join.
	 */
# ifdef OF_HAVE_BLOCKS
	if (thread->_threadBlock != NULL)
		thread->_returnValue = [thread->_threadBlock() retain];
	else
# endif
		thread->_returnValue = [[thread main] retain];







|







89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
		@throw [OFInitializationFailedException
		    exceptionWithClass: [thread class]];

	thread->_pool = objc_autoreleasePoolPush();

	/*
	 * Nasty workaround for thread implementations which can't return a
	 * pointer on join.
	 */
# ifdef OF_HAVE_BLOCKS
	if (thread->_threadBlock != NULL)
		thread->_returnValue = [thread->_threadBlock() retain];
	else
# endif
		thread->_returnValue = [[thread main] retain];
255
256
257
258
259
260
261
















262
263
264
265
266
267
268
269
270
271
272
273
	mainThread = [[OFThread alloc] init];
	mainThread->_thread = of_thread_current();

	if (!of_tlskey_set(threadSelfKey, mainThread))
		@throw [OFInitializationFailedException
		    exceptionWithClass: self];
}

















# ifdef OF_HAVE_BLOCKS
- initWithThreadBlock: (of_thread_block_t)threadBlock
{
	self = [super init];

	@try {
		_threadBlock = [threadBlock copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




|







255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
	mainThread = [[OFThread alloc] init];
	mainThread->_thread = of_thread_current();

	if (!of_tlskey_set(threadSelfKey, mainThread))
		@throw [OFInitializationFailedException
		    exceptionWithClass: self];
}

- init
{
	self = [super init];

	@try {
		if (!of_thread_attr_init(&_attr))
			@throw [OFInitializationFailedException
			    exceptionWithClass: [self class]];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

# ifdef OF_HAVE_BLOCKS
- initWithThreadBlock: (of_thread_block_t)threadBlock
{
	self = [self init];

	@try {
		_threadBlock = [threadBlock copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
		[_returnValue release];
	}

	[self retain];

	_running = OF_THREAD_RUNNING;

	if (!of_thread_new(&_thread, callMain, self)) {
		[self release];
		@throw [OFThreadStartFailedException exceptionWithThread: self];
	}

	if (_name != nil)
		of_thread_set_name(_thread, [_name UTF8String]);
	else







|







320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
		[_returnValue release];
	}

	[self retain];

	_running = OF_THREAD_RUNNING;

	if (!of_thread_new(&_thread, callMain, self, &_attr)) {
		[self release];
		@throw [OFThreadStartFailedException exceptionWithThread: self];
	}

	if (_name != nil)
		of_thread_set_name(_thread, [_name UTF8String]);
	else
366
367
368
369
370
371
372




























373
374
375
376
377
378
379
		if (_name != nil)
			of_thread_set_name(_thread, [_name UTF8String]);
		else
			of_thread_set_name(_thread,
			    class_getName([self class]));
	}
}





























- (void)dealloc
{
	if (_running == OF_THREAD_RUNNING)
		@throw [OFThreadStillRunningException
		    exceptionWithThread: self];








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
		if (_name != nil)
			of_thread_set_name(_thread, [_name UTF8String]);
		else
			of_thread_set_name(_thread,
			    class_getName([self class]));
	}
}

- (float)priority
{
	return _attr.priority;
}

- (void)setPriority: (float)priority
{
	if (_running == OF_THREAD_RUNNING)
		@throw [OFThreadStillRunningException
		    exceptionWithThread: self];

	_attr.priority = priority;
}

- (size_t)stackSize
{
	return _attr.stackSize;
}

- (void)setStackSize: (size_t)stackSize
{
	if (_running == OF_THREAD_RUNNING)
		@throw [OFThreadStillRunningException
		    exceptionWithThread: self];

	_attr.stackSize = stackSize;
}

- (void)dealloc
{
	if (_running == OF_THREAD_RUNNING)
		@throw [OFThreadStillRunningException
		    exceptionWithThread: self];

Modified src/threading.h from [ca3714aa7c] to [0444440a9d].

23
24
25
26
27
28
29

30
31
32
33
34
35
36

#include <math.h>

#import "OFObject.h"

#if defined(OF_HAVE_PTHREADS)
# include <pthread.h>

typedef pthread_t of_thread_t;
typedef pthread_key_t of_tlskey_t;
typedef pthread_mutex_t of_mutex_t;
typedef pthread_cond_t of_condition_t;
typedef pthread_once_t of_once_t;
# define OF_ONCE_INIT PTHREAD_ONCE_INIT
#elif defined(_WIN32)







>







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

#include <math.h>

#import "OFObject.h"

#if defined(OF_HAVE_PTHREADS)
# include <pthread.h>
# include <sched.h>
typedef pthread_t of_thread_t;
typedef pthread_key_t of_tlskey_t;
typedef pthread_mutex_t of_mutex_t;
typedef pthread_cond_t of_condition_t;
typedef pthread_once_t of_once_t;
# define OF_ONCE_INIT PTHREAD_ONCE_INIT
#elif defined(_WIN32)
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
typedef volatile int of_spinlock_t;
# define OF_SPINCOUNT 10
#elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
typedef pthread_spinlock_t of_spinlock_t;
#else
typedef of_mutex_t of_spinlock_t;
#endif





#ifdef OF_HAVE_RECURSIVE_PTHREAD_MUTEXES
# define of_rmutex_t of_mutex_t
#else
typedef struct {
	of_mutex_t mutex;
	of_tlskey_t count;
} of_rmutex_t;
#endif






#if defined(OF_HAVE_PTHREADS)
# define of_thread_is_current(t) pthread_equal(t, pthread_self())
# define of_thread_current pthread_self
#elif defined(_WIN32)
# define of_thread_is_current(t) (t == GetCurrentThread())
# define of_thread_current GetCurrentThread
#else
# error of_thread_is_current not implemented!
# error of_thread_current not implemented!
#endif


extern bool of_thread_new(of_thread_t *thread, id (*function)(id), id data);

extern void of_thread_set_name(of_thread_t thread, const char *name);
extern bool of_thread_join(of_thread_t thread);
extern bool of_thread_detach(of_thread_t thread);
extern void OF_NO_RETURN of_thread_exit(void);
extern void of_once(of_once_t *control, void (*func)(void));
extern bool of_mutex_new(of_mutex_t *mutex);
extern bool of_mutex_lock(of_mutex_t *mutex);







>
>
>
>









>
>
>
>
>












>
|
>







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
typedef volatile int of_spinlock_t;
# define OF_SPINCOUNT 10
#elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
typedef pthread_spinlock_t of_spinlock_t;
#else
typedef of_mutex_t of_spinlock_t;
#endif

#ifdef OF_HAVE_SCHED_YIELD
# include <sched.h>
#endif

#ifdef OF_HAVE_RECURSIVE_PTHREAD_MUTEXES
# define of_rmutex_t of_mutex_t
#else
typedef struct {
	of_mutex_t mutex;
	of_tlskey_t count;
} of_rmutex_t;
#endif

typedef struct of_thread_attr_t {
	float priority;
	size_t stackSize;
} of_thread_attr_t;

#if defined(OF_HAVE_PTHREADS)
# define of_thread_is_current(t) pthread_equal(t, pthread_self())
# define of_thread_current pthread_self
#elif defined(_WIN32)
# define of_thread_is_current(t) (t == GetCurrentThread())
# define of_thread_current GetCurrentThread
#else
# error of_thread_is_current not implemented!
# error of_thread_current not implemented!
#endif

extern bool of_thread_attr_init(of_thread_attr_t *attr);
extern bool of_thread_new(of_thread_t *thread, id (*function)(id), id data,
    const of_thread_attr_t *attr);
extern void of_thread_set_name(of_thread_t thread, const char *name);
extern bool of_thread_join(of_thread_t thread);
extern bool of_thread_detach(of_thread_t thread);
extern void OF_NO_RETURN of_thread_exit(void);
extern void of_once(of_once_t *control, void (*func)(void));
extern bool of_mutex_new(of_mutex_t *mutex);
extern bool of_mutex_lock(of_mutex_t *mutex);

Modified src/threading.m from [0911130ba6] to [21c1e4f75c].

9
10
11
12
13
14
15


16
17
18
19
20
21
22
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */



#import "threading.h"

#if defined(OF_HAVE_PTHREADS)
# include "threading_pthread.m"
#elif defined(_WIN32)
# include "threading_winapi.m"







>
>







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "threading.h"

#if defined(OF_HAVE_PTHREADS)
# include "threading_pthread.m"
#elif defined(_WIN32)
# include "threading_winapi.m"

Modified src/threading_pthread.m from [9bd4f81445] to [9c2b4d74c8].

10
11
12
13
14
15
16




17


18

























19
20

21


































22
23



24
25
26
27
28
29
30
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */





#import "threading.h"




























bool
of_thread_new(of_thread_t *thread, id (*function)(id), id data)

{


































	return (pthread_create(thread, NULL, (void*(*)(void*))function,
	    (__bridge void*)data) == 0);



}

bool
of_thread_join(of_thread_t thread)
{
	void *ret;








>
>
>
>
|
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>







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
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

bool
of_thread_attr_init(of_thread_attr_t *attr)
{
	pthread_attr_t pattr;

	if (pthread_attr_init(&pattr) != 0)
		return false;

	@try {
		int policy, minPrio, maxPrio;
		struct sched_param param;

		if (pthread_attr_getschedpolicy(&pattr, &policy) != 0)
			return false;

		minPrio = sched_get_priority_min(policy);
		maxPrio = sched_get_priority_max(policy);

		if (pthread_attr_getschedparam(&pattr, &param) != 0)
			return false;

		attr->priority = (float)(param.sched_priority - minPrio) /
		    (maxPrio - minPrio);

		if (pthread_attr_getstacksize(&pattr, &attr->stackSize) != 0)
			return false;

		return true;
	} @finally {
		pthread_attr_destroy(&pattr);
	}
}

bool
of_thread_new(of_thread_t *thread, id (*function)(id), id data,
    const of_thread_attr_t *attr)
{
	pthread_attr_t pattr;

	if (pthread_attr_init(&pattr) != 0)
		return false;

	@try {
		if (attr != NULL) {
			int policy, minPrio, maxPrio;
			struct sched_param param;

			if (attr->priority < 0 || attr->priority > 1)
				return false;

			if (pthread_attr_getschedpolicy(&pattr, &policy) != 0)
				return false;

			minPrio = sched_get_priority_min(policy);
			maxPrio = sched_get_priority_max(policy);

			param.sched_priority = (float)minPrio +
			    attr->priority * (maxPrio - minPrio);

			if (pthread_attr_setinheritsched(&pattr,
			    PTHREAD_EXPLICIT_SCHED) != 0)
				return false;

			if (pthread_attr_setschedparam(&pattr, &param) != 0)
				return false;

			if (pthread_attr_setstacksize(&pattr,
			    attr->stackSize) != 0)
				return false;
		}

		return (pthread_create(thread, &pattr,
		    (void*(*)(void*))function, (__bridge void*)data) == 0);
	} @finally {
		pthread_attr_destroy(&pattr);
	}
}

bool
of_thread_join(of_thread_t thread)
{
	void *ret;

Modified src/threading_winapi.m from [a634dc92fc] to [73d2b0526d].

10
11
12
13
14
15
16







17

18

19
20

21












22
23
24

25





26
27
28
29
30
31
32
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */








#import "threading.h"



bool
of_thread_new(of_thread_t *thread, id (*function)(id), id data)

{












	*thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)function,
	    (__bridge void*)data, 0, NULL);


	return (thread != NULL);





}

bool
of_thread_join(of_thread_t thread)
{
	if (WaitForSingleObject(thread, INFINITE))
		return false;







>
>
>
>
>
>
>
|
>
|
>

|
>

>
>
>
>
>
>
>
>
>
>
>
>
|
|

>
|
>
>
>
>
>







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
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

bool
of_thread_attr_init(of_thread_attr_t *attr)
{
	attr->priority =
	    (float)(THREAD_PRIORITY_NORMAL - THREAD_PRIORITY_LOWEST) /
	    (THREAD_PRIORITY_HIGHEST - THREAD_PRIORITY_LOWEST);
	attr->stackSize = 0;

	return true;
}

bool
of_thread_new(of_thread_t *thread, id (*function)(id), id data,
    const of_thread_attr_t *attr)
{
	size_t stackSize = 0;
	int priority = 0;

	if (attr != NULL) {
		if (attr->priority < 0 || attr->priority > 1)
			return false;

		priority = THREAD_PRIORITY_LOWEST + attr->priority *
		    (THREAD_PRIORITY_HIGHEST - THREAD_PRIORITY_LOWEST);
		stackSize = attr->stackSize;
	}

	*thread = CreateThread(NULL, stackSize,
	    (LPTHREAD_START_ROUTINE)function, (__bridge void*)data, 0, NULL);

	if (thread == NULL)
		return false;

	if (priority > 0)
		return SetThreadPriority(*thread, priority);
	else
		return true;
}

bool
of_thread_join(of_thread_t thread)
{
	if (WaitForSingleObject(thread, INFINITE))
		return false;