ObjFW  Diff

Differences From Artifact [b865223801]:

To Artifact [475603ba84]:

  • File src/OFThread.m — part of check-in [e1e7ffa903] at 2011-09-22 23:25:42 on branch trunk — Exceptions are now autoreleased.

    This is safe as an "exception loop" can't happen, since if allocating
    an exception fails, it throws an OFAllocFailedException which is
    preallocated and can always be thrown.

    So, the worst case would be that an autorelease of an exception fails,
    triggering an OFOutOfMemoryException for which there is no memory,
    resulting in an OFAllocFailedException to be thrown. (user: js, size: 9810) [annotate] [blame] [check-ins using]


63
64
65
66
67
68
69
70

71
72
73
74
75
76
77
63
64
65
66
67
68
69

70
71
72
73
74
75
76
77







-
+








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

	if (!of_tlskey_set(threadSelf, thread))
		@throw [OFInitializationFailedException
		    newWithClass: [thread class]];
		    exceptionWithClass: [thread class]];

	/*
	 * Nasty workaround for thread implementations which can't return a
	 * value on join.
	 */
#ifdef OF_HAVE_BLOCKS
	if (thread->block != NULL)
105
106
107
108
109
110
111
112


113
114
115
116
117
118
119
105
106
107
108
109
110
111

112
113
114
115
116
117
118
119
120







-
+
+








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

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

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

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







-
-
+
+

















-
+



-
+





-
+











-
+





-
+








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

	if (!of_tlskey_set(key->key, [object retain]))
		@throw [OFInvalidArgumentException newWithClass: self
						       selector: _cmd];
		@throw [OFInvalidArgumentException exceptionWithClass: self
							     selector: _cmd];

	[oldObject release];
}

+ (id)objectForTLSKey: (OFTLSKey*)key
{
	return [[of_tlskey_get(key->key) retain] autorelease];
}

+ (OFThread*)currentThread
{
	return [[of_tlskey_get(threadSelf) retain] autorelease];
}

+ (void)sleepForTimeInterval: (double)seconds
{
	if (seconds < 0)
		@throw [OFOutOfRangeException newWithClass: self];
		@throw [OFOutOfRangeException exceptionWithClass: self];

#ifndef _WIN32
	if (seconds > UINT_MAX)
		@throw [OFOutOfRangeException newWithClass: self];
		@throw [OFOutOfRangeException exceptionWithClass: self];

	sleep((unsigned int)seconds);
	usleep((useconds_t)rint((seconds - floor(seconds)) * 1000000));
#else
	if (seconds * 1000 > UINT_MAX)
		@throw [OFOutOfRangeException newWithClass: self];
		@throw [OFOutOfRangeException exceptionWithClass: self];

	Sleep((unsigned int)(seconds * 1000));
#endif
}

+ (void)sleepUntilDate: (OFDate*)date
{
	double seconds = [date timeIntervalSinceNow];

#ifndef _WIN32
	if (seconds > UINT_MAX)
		@throw [OFOutOfRangeException newWithClass: self];
		@throw [OFOutOfRangeException exceptionWithClass: self];

	sleep((unsigned int)seconds);
	usleep((useconds_t)rint((seconds - floor(seconds)) * 1000000));
#else
	if (seconds * 1000 > UINT_MAX)
		@throw [OFOutOfRangeException newWithClass: self];
		@throw [OFOutOfRangeException exceptionWithClass: self];

	Sleep((unsigned int)(seconds * 1000));
#endif
}

+ (void)yield
{
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
290
291
292


293
294
295
296
297
298
299
300
301
302


303
304
305
306
307
308
309
310
311
312
313


314
315
316
317
318
319
320
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
290
291


292
293
294
295
296
297
298
299
300
301


302
303
304
305
306
307
308
309
310
311
312


313
314
315
316
317
318
319
320
321







-
-
+
+











-
-
+
+










-
-
+
+








-
-
+
+









-
-
+
+








	return self;
}
#endif

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

	return nil;
}

- (void)handleTermination
{
}

- (void)start
{
	if (running == OF_THREAD_RUNNING)
		@throw [OFThreadStillRunningException newWithClass: isa
							    thread: self];
		@throw [OFThreadStillRunningException exceptionWithClass: isa
								  thread: self];

	if (running == OF_THREAD_WAITING_FOR_JOIN) {
		of_thread_detach(thread);
		[returnValue release];
	}

	[self retain];

	if (!of_thread_new(&thread, call_main, self)) {
		[self release];
		@throw [OFThreadStartFailedException newWithClass: isa
							   thread: self];
		@throw [OFThreadStartFailedException exceptionWithClass: isa
								 thread: self];
	}

	running = OF_THREAD_RUNNING;
}

- (id)join
{
	if (running == OF_THREAD_NOT_RUNNING || !of_thread_join(thread))
		@throw [OFThreadJoinFailedException newWithClass: isa
							  thread: self];
		@throw [OFThreadJoinFailedException exceptionWithClass: isa
								thread: self];

	running = OF_THREAD_NOT_RUNNING;

	return returnValue;
}

- (void)dealloc
{
	if (running == OF_THREAD_RUNNING)
		@throw [OFThreadStillRunningException newWithClass: isa
							    thread: self];
		@throw [OFThreadStillRunningException exceptionWithClass: isa
								  thread: self];

	/*
	 * 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);
361
362
363
364
365
366
367
368

369
370
371
372
373
374
375
362
363
364
365
366
367
368

369
370
371
372
373
374
375
376







-
+







- init
{
	self = [super init];

	@try {
		if (!of_tlskey_new(&key))
			@throw [OFInitializationFailedException
			    newWithClass: isa];
			    exceptionWithClass: isa];

		initialized = YES;

		@synchronized (TLSKeys) {
			listObject = [TLSKeys appendObject: self];
		}
	} @catch (id e) {
417
418
419
420
421
422
423
424

425
426
427
428
429
430
431
432
433
434
435
436


437
438
439
440
441
442
443
444
445
446
447
448


449
450
451
452
453
454
455
456



457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475

476
477
478
479
480
481
482
483
484
485
486
487



488
489
490
491
492
493
494



495
496
497
498
499
500
501



502
503
504
505
506
507
508
509
510


511
512
513
514
418
419
420
421
422
423
424

425
426
427
428
429
430
431
432
433
434
435


436
437
438
439
440
441
442
443
444
445
446
447


448
449
450
451
452
453
454
455


456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476

477
478
479
480
481
482
483
484
485
486
487


488
489
490
491
492
493
494
495


496
497
498
499
500
501
502
503


504
505
506
507
508
509
510
511
512
513


514
515
516
517
518
519







-
+










-
-
+
+










-
-
+
+






-
-
+
+
+


















-
+










-
-
+
+
+





-
-
+
+
+





-
-
+
+
+







-
-
+
+




- init
{
	self = [super init];

	if (!of_mutex_new(&mutex)) {
		Class c = isa;
		[self release];
		@throw [OFInitializationFailedException newWithClass: c];
		@throw [OFInitializationFailedException exceptionWithClass: c];
	}

	initialized = YES;

	return self;
}

- (void)lock
{
	if (!of_mutex_lock(&mutex))
		@throw [OFMutexLockFailedException newWithClass: isa
							  mutex: self];
		@throw [OFMutexLockFailedException exceptionWithClass: isa
								mutex: self];
}

- (BOOL)tryLock
{
	return of_mutex_trylock(&mutex);
}

- (void)unlock
{
	if (!of_mutex_unlock(&mutex))
		@throw [OFMutexUnlockFailedException newWithClass: isa
							    mutex: self];
		@throw [OFMutexUnlockFailedException exceptionWithClass: isa
								  mutex: self];
}

- (void)dealloc
{
	if (initialized)
		if (!of_mutex_free(&mutex))
			@throw [OFMutexStillLockedException newWithClass: isa
								   mutex: self];
			@throw [OFMutexStillLockedException
			    exceptionWithClass: isa
					 mutex: self];

	[super dealloc];
}
@end

@implementation OFCondition
+ condition
{
	return [[[self alloc] init] autorelease];
}

- init
{
	self = [super init];

	if (!of_condition_new(&condition)) {
		Class c = isa;
		[self release];
		@throw [OFInitializationFailedException newWithClass: c];
		@throw [OFInitializationFailedException exceptionWithClass: c];
	}

	conditionInitialized = YES;

	return self;
}

- (void)wait
{
	if (!of_condition_wait(&condition, &mutex))
		@throw [OFConditionWaitFailedException newWithClass: isa
							  condition: self];
		@throw [OFConditionWaitFailedException
		    exceptionWithClass: isa
			     condition: self];
}

- (void)signal
{
	if (!of_condition_signal(&condition))
		@throw [OFConditionSignalFailedException newWithClass: isa
							    condition: self];
		@throw [OFConditionSignalFailedException
		    exceptionWithClass: isa
			     condition: self];
}

- (void)broadcast
{
	if (!of_condition_broadcast(&condition))
		@throw [OFConditionBroadcastFailedException newWithClass: isa
							       condition: self];
		@throw [OFConditionBroadcastFailedException
		    exceptionWithClass: isa
			     condition: self];
}

- (void)dealloc
{
	if (conditionInitialized)
		if (!of_condition_free(&condition))
			@throw [OFConditionStillWaitingException
			    newWithClass: isa
			       condition: self];
			    exceptionWithClass: isa
				     condition: self];

	[super dealloc];
}
@end