ObjFW  Check-in [d966ede8fe]

Overview
Comment:Add +[threadWithBlock:] to OFThread.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: d966ede8fe4fa0df02b5b1160497828f042bfcdeceda80b1331d8f5d7526f98e
User & Date: js on 2011-07-06 22:49:03
Other Links: manifest | tags
Context
2011-07-06
22:55
Only allow an OFConstantString as format. check-in: 7558e235fe user: js tags: trunk
22:49
Add +[threadWithBlock:] to OFThread. check-in: d966ede8fe user: js tags: trunk
22:39
Documentation fixes. check-in: 16ce0fea69 user: js tags: trunk
Changes

Modified src/OFThread.h from [7979d66d62] to [965a5e323a].

17
18
19
20
21
22
23




24
25
26
27
28
29
30
#import "OFObject.h"
#import "OFList.h"

#import "threading.h"

@class OFDate;





/**
 * \brief A class for Thread Local Storage keys.
 */
@interface OFTLSKey: OFObject
{
@public
	of_tlskey_t key;







>
>
>
>







17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#import "OFObject.h"
#import "OFList.h"

#import "threading.h"

@class OFDate;

#ifdef OF_HAVE_BLOCKS
typedef id (^of_thread_block_t)(id object);
#endif

/**
 * \brief A class for Thread Local Storage keys.
 */
@interface OFTLSKey: OFObject
{
@public
	of_tlskey_t key;
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
 * \brief A class which provides portable threads.
 *
 * To use it, you should create a new class derived from it and reimplement
 * main.
 */
@interface OFThread: OFObject
{

	id object;
	of_thread_t thread;
@public
	enum {
		OF_THREAD_NOT_RUNNING,
		OF_THREAD_RUNNING,
		OF_THREAD_WAITING_FOR_JOIN
	} running;



	id returnValue;
}





/**
 * \return A new, autoreleased thread
 */
+ thread;

/**
 * \param object An object which is passed for use in the main method or nil
 * \return A new, autoreleased thread
 */
+ threadWithObject: (id)object;

















/**
 * Sets the Thread Local Storage for the specified key.
 *
 * The specified object is first retained and then the object stored before is
 * released. You can specify nil as object if you want the old object to be
 * released and don't want any new object for the TLS key.







>


<





>
>
>


>
>
>
>











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







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
 * \brief A class which provides portable threads.
 *
 * To use it, you should create a new class derived from it and reimplement
 * main.
 */
@interface OFThread: OFObject
{
@public
	id object;
	of_thread_t thread;

	enum {
		OF_THREAD_NOT_RUNNING,
		OF_THREAD_RUNNING,
		OF_THREAD_WAITING_FOR_JOIN
	} running;
#ifdef OF_HAVE_BLOCKS
	of_thread_block_t block;
#endif
	id returnValue;
}

#if defined(OF_HAVE_PROPERTIES) && defined(OF_HAVE_BLOCKS)
@property (retain) of_thread_block_t block;
#endif

/**
 * \return A new, autoreleased thread
 */
+ thread;

/**
 * \param object An object which is passed for use in the main method or nil
 * \return A new, autoreleased thread
 */
+ threadWithObject: (id)object;

#ifdef OF_HAVE_BLOCKS
/**
 * \param block A block which is executed by the thread
 * \return A new, autoreleased thread
 */
+ threadWithBlock: (of_thread_block_t)block;

/**
 * \param block A block which is executed by the thread
 * \param object An object which is passed for use in the main method or nil
 * \return A new, autoreleased thread
 */
+ threadWithBlock: (of_thread_block_t)block
	   object: (id)object;
#endif

/**
 * Sets the Thread Local Storage for the specified key.
 *
 * The specified object is first retained and then the object stored before is
 * released. You can specify nil as object if you want the old object to be
 * released and don't want any new object for the TLS key.
161
162
163
164
165
166
167
















168
169
170
171
172
173
174
+ (void)terminateWithObject: (id)object;

/**
 * \param object An object which is passed for use in the main method or nil
 * \return An initialized OFThread.
 */
- initWithObject: (id)object;

















/**
 * The main routine of the thread. You need to reimplement this!
 *
 * It can access the object passed to the threadWithObject or initWithObject
 * method using the instance variable named object.
 *







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







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
+ (void)terminateWithObject: (id)object;

/**
 * \param object An object which is passed for use in the main method or nil
 * \return An initialized OFThread.
 */
- initWithObject: (id)object;

#ifdef OF_HAVE_BLOCKS
/**
 * \param block A block which is executed by the thread
 * \return An initialized OFThread.
 */
- initWithBlock: (of_thread_block_t)block;

/**
 * \param block A block which is executed by the thread
 * \param object An object which is passed for use in the main method or nil
 * \return An initialized OFThread.
 */
- initWithBlock: (of_thread_block_t)block
	 object: (id)object;
#endif

/**
 * The main routine of the thread. You need to reimplement this!
 *
 * It can access the object passed to the threadWithObject or initWithObject
 * method using the instance variable named object.
 *

Modified src/OFThread.m from [ca215c7c50] to [812930f276].

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
		@throw [OFInitializationFailedException
		    newWithClass: [thread class]];

	/*
	 * Nasty workaround for thread implementations which can't return a
	 * value on join.
	 */




	thread->returnValue = [[thread main] retain];




	[thread handleTermination];

	thread->running = OF_THREAD_WAITING_FOR_JOIN;

	[OFTLSKey callAllDestructors];
	[OFAutoreleasePool releaseAll];

	[thread release];

#if defined(OF_GNU_RUNTIME) || defined(OF_OLD_GNU_RUNTIME)
	objc_thread_remove();
#endif

	return 0;
}

@implementation OFThread




+ (void)initialize
{
	if (self != [OFThread class])
		return;

	if (!of_tlskey_new(&threadSelf))
		@throw [OFInitializationFailedException newWithClass: self];
}

+ thread
{
	return [[[self alloc] init] autorelease];
}

+ threadWithObject: (id)object
{
	return [[[self alloc] initWithObject: object] autorelease];
}















+ (void)setObject: (id)object
	forTLSKey: (OFTLSKey*)key
{
	id oldObject = of_tlskey_get(key->key);

	if (!of_tlskey_set(key->key, [object retain]))







>
>
>
>
|
>
>
>


















>
>
>
>


















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







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
		@throw [OFInitializationFailedException
		    newWithClass: [thread class]];

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

	[thread handleTermination];

	thread->running = OF_THREAD_WAITING_FOR_JOIN;

	[OFTLSKey callAllDestructors];
	[OFAutoreleasePool releaseAll];

	[thread release];

#if defined(OF_GNU_RUNTIME) || defined(OF_OLD_GNU_RUNTIME)
	objc_thread_remove();
#endif

	return 0;
}

@implementation OFThread
#if defined(OF_HAVE_PROPERTIES) && defined(OF_HAVE_BLOCKS)
@synthesize block;
#endif

+ (void)initialize
{
	if (self != [OFThread class])
		return;

	if (!of_tlskey_new(&threadSelf))
		@throw [OFInitializationFailedException newWithClass: self];
}

+ thread
{
	return [[[self alloc] init] autorelease];
}

+ threadWithObject: (id)object
{
	return [[[self alloc] initWithObject: object] autorelease];
}

#ifdef OF_HAVE_BLOCKS
+ threadWithBlock: (of_thread_block_t)block
{
	return [[[self alloc] initWithBlock: block] autorelease];
}

+ threadWithBlock: (of_thread_block_t)block
	   object: (id)object
{
	return [[[self alloc] initWithBlock: block
				     object: object] autorelease];
}
#endif

+ (void)setObject: (id)object
	forTLSKey: (OFTLSKey*)key
{
	id oldObject = of_tlskey_get(key->key);

	if (!of_tlskey_set(key->key, [object retain]))
239
240
241
242
243
244
245
























246
247
248
249
250
251
252
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

























- (id)main
{
	@throw [OFNotImplementedException newWithClass: isa
					      selector: _cmd];

	return nil;







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







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
290
291
292
293
294
295
296
297
298
299
300
301
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

#ifdef OF_HAVE_BLOCKS
- initWithBlock: (of_thread_block_t)block_
{
	return [self initWithBlock: block_
			    object: nil];
}

- initWithBlock: (of_thread_block_t)block_
	 object: (id)object_
{
	self = [super init];

	@try {
		block = [block_ retain];
		object = [object_ retain];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}
#endif

- (id)main
{
	@throw [OFNotImplementedException newWithClass: isa
					      selector: _cmd];

	return nil;