ObjFW  Check-in [0639a351db]

Overview
Comment:Remove "object" from OFThread.

Blocks don't allow passing it anymore and without blocks, subclassing is
necessary anyway so that an ivar with the correct type can be added
(instead of id) if required.

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 0639a351db29a26ab317c0a1a2c654b4df8b7d91c73e06ca894cffc37b8c249d
User & Date: js on 2012-11-10 00:14:59
Other Links: manifest | tags
Context
2012-11-10
10:27
Make it possible to give threads a name. check-in: debba8efb6 user: js tags: trunk
00:14
Remove "object" from OFThread. check-in: 0639a351db user: js tags: trunk
2012-11-08
15:55
Revert "Async I/O: Pass a context." check-in: 497d3f962c user: js tags: trunk
Changes

Modified src/OFThread.h from [eeffe88350] to [9008bb5cf4].

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
#endif

@class OFDate;
@class OFSortedList;
@class OFRunLoop;

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

/*!
 * @brief A class which provides portable threads.
 *
 * To use it, you should create a new class derived from it and reimplement
 * main.
 *
 * @warning Even though the OFCopying protocol is implemented, it does
 *	    <i>not</i> return an independent copy of the thread, but instead
 *	    retains it. This is so that the thread can be used as a key for a
 *	    dictionary, so context can be associated with a thread.
 */
@interface OFThread: OFObject <OFCopying>
{
#ifdef OF_THREAD_M
@public
#endif
	id object;
#ifndef OF_THREAD_M
@private
#endif
	of_thread_t thread;
	enum {
		OF_THREAD_NOT_RUNNING,
		OF_THREAD_RUNNING,
		OF_THREAD_WAITING_FOR_JOIN







|

















|
<
<







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
#endif

@class OFDate;
@class OFSortedList;
@class OFRunLoop;

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

/*!
 * @brief A class which provides portable threads.
 *
 * To use it, you should create a new class derived from it and reimplement
 * main.
 *
 * @warning Even though the OFCopying protocol is implemented, it does
 *	    <i>not</i> return an independent copy of the thread, but instead
 *	    retains it. This is so that the thread can be used as a key for a
 *	    dictionary, so context can be associated with a thread.
 */
@interface OFThread: OFObject <OFCopying>
{
#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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/*!
 * @brief Creates a new thread.
 *
 * @return A new, autoreleased thread
 */
+ (instancetype)thread;

/*!
 * @brief Creates a new thread with the specified object.
 *
 * @param object An object which is passed for use in the main method or nil
 * @return A new, autoreleased thread
 */
+ (instancetype)threadWithObject: (id)object;

#ifdef OF_HAVE_BLOCKS
/*!
 * @brief Creates a new thread with the specified block.
 *
 * @param block A block which is executed by the thread
 * @return A new, autoreleased thread
 */







<
<
<
<
<
<
<
<







70
71
72
73
74
75
76








77
78
79
80
81
82
83
/*!
 * @brief Creates a new thread.
 *
 * @return A new, autoreleased thread
 */
+ (instancetype)thread;









#ifdef OF_HAVE_BLOCKS
/*!
 * @brief Creates a new thread with the specified block.
 *
 * @param block A block which is executed by the thread
 * @return A new, autoreleased thread
 */
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
 *
 * @param object The object which the terminated thread will return
 */
+ (void)terminateWithObject: (id)object;

+ (void)OF_createMainThread;

/*!
 * @brief Initializes an already allocated thread with the specified 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
/*!
 * @brief Initializes an already allocated thread with the specified block.
 *
 * @param block A block which is executed by the thread
 * @return An initialized OFThread.
 */







<
<
<
<
<
<
<
<







152
153
154
155
156
157
158








159
160
161
162
163
164
165
 *
 * @param object The object which the terminated thread will return
 */
+ (void)terminateWithObject: (id)object;

+ (void)OF_createMainThread;









#ifdef OF_HAVE_BLOCKS
/*!
 * @brief Initializes an already allocated thread with the specified block.
 *
 * @param block A block which is executed by the thread
 * @return An initialized OFThread.
 */

Modified src/OFThread.m from [94dbbf6fa0] to [378318c425].

66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

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

	[thread handleTermination];

	thread->running = OF_THREAD_WAITING_FOR_JOIN;







|







66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

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

	[thread handleTermination];

	thread->running = OF_THREAD_WAITING_FOR_JOIN;
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
}

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

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

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








<
<
<
<
<







110
111
112
113
114
115
116





117
118
119
120
121
122
123
}

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






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

237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
	mainThread->thread = of_thread_current();

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

- initWithObject: (id)object_
{
	self = [super init];

	object = [object_ retain];

	return self;
}

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

	@try {
		block = [block_ copy];







<
<
<
<
<
<
<
<
<







232
233
234
235
236
237
238









239
240
241
242
243
244
245
	mainThread->thread = of_thread_current();

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










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

	@try {
		block = [block_ copy];
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
	[[OFRunLoop currentRunLoop] run];

	return nil;
}

- (void)handleTermination
{
	OFRunLoop *tmp = runLoop;
	runLoop = nil;
	[tmp release];
}

- (void)start
{
	if (running == OF_THREAD_RUNNING)
		@throw [OFThreadStillRunningException
		    exceptionWithClass: [self class]







|

|







257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
	[[OFRunLoop currentRunLoop] run];

	return nil;
}

- (void)handleTermination
{
	OFRunLoop *oldRunLoop = runLoop;
	runLoop = nil;
	[oldRunLoop release];
}

- (void)start
{
	if (running == OF_THREAD_RUNNING)
		@throw [OFThreadStillRunningException
		    exceptionWithClass: [self class]
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
	/*
	 * We should not be running anymore, but call detach in order to free
	 * the resources.
	 */
	if (running == OF_THREAD_WAITING_FOR_JOIN)
		of_thread_detach(thread);

	[object release];
	[returnValue release];
	[runLoop release];

	[super dealloc];
}

- copy
{
	return [self retain];
}
@end







<











324
325
326
327
328
329
330

331
332
333
334
335
336
337
338
339
340
341
	/*
	 * We should not be running anymore, but call detach in order to free
	 * the resources.
	 */
	if (running == OF_THREAD_WAITING_FOR_JOIN)
		of_thread_detach(thread);


	[returnValue release];
	[runLoop release];

	[super dealloc];
}

- copy
{
	return [self retain];
}
@end

Modified tests/OFThreadTests.m from [b3376c3e2c] to [b6a82ebbc3].

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

@interface TestThread: OFThread
@end

@implementation TestThread
- (id)main
{
	if ([object isEqual: @"foo"])
		return @"success";

	return nil;
}
@end

@implementation TestsAppDelegate (OFThreadTests)
- (void)threadTests
{
	OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
	TestThread *t;
	OFTLSKey *key;

	TEST(@"+[threadWithObject:]",
	    (t = [TestThread threadWithObject: @"foo"]))

	TEST(@"-[start]", R([t start]))

	TEST(@"-[join]", [[t join] isEqual: @"success"])

	TEST(@"OFTLSKey's +[TLSKey]", (key = [OFTLSKey TLSKey]))








<
|
<
<










|
<







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

@interface TestThread: OFThread
@end

@implementation TestThread
- (id)main
{

	return @"success";


}
@end

@implementation TestsAppDelegate (OFThreadTests)
- (void)threadTests
{
	OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
	TestThread *t;
	OFTLSKey *key;

	TEST(@"+[thread]", (t = [TestThread thread]))


	TEST(@"-[start]", R([t start]))

	TEST(@"-[join]", [[t join] isEqual: @"success"])

	TEST(@"OFTLSKey's +[TLSKey]", (key = [OFTLSKey TLSKey]))