ObjFW  Check-in [4d1d644283]

Overview
Comment:Add Thread Local Storage support to OFThread.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 4d1d6442830163d336624e7afd92cfc50f24b795c277d66e21ab30230ab61ca1
User & Date: js on 2009-05-04 12:57:43
Other Links: manifest | tags
Context
2009-05-04
13:01
Use OFThread's TLS in OFAutoreleasePool. check-in: 2d09137a6b user: js tags: trunk
12:57
Add Thread Local Storage support to OFThread. check-in: 4d1d644283 user: js tags: trunk
2009-05-03
21:33
Get rid of + new.
Additionally, make - accept return an autoreleased OFTCPSocket.
check-in: 5ca127891c user: js tags: trunk
Changes

Modified src/OFThread.h from [1ac78297bf] to [5e60e220d4].

13
14
15
16
17
18
19


























20
21
22
23
24
25
26
#include <pthread.h>
#else
#include <windows.h>
#endif

#import "OFObject.h"



























/**
 * The OFThread class provides portable threads.
 *
 * To use it, you should create a new class derived from it and reimplement
 * main.
 */
@interface OFThread: OFObject







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







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
#include <pthread.h>
#else
#include <windows.h>
#endif

#import "OFObject.h"

/**
 * A Thread Local Storage key.
 */
@interface OFTLSKey: OFObject
{
@public
#ifndef _WIN32
	pthread_key_t key;
#else
	DWORD key;
#endif
}

/**
 * \param destructor A destructor that is called when the thread is terminated
 * \return A new autoreleased Thread Local Storage key
 */
+ tlsKeyWithDestructor: (void(*)(void*))destructor;

/**
 * \param destructor A destructor that is called when the thread is terminated
 * \return An initialized Thread Local Storage key
 */
- initWithDestructor: (void(*)(void*))destructor;
@end

/**
 * The OFThread class provides portable threads.
 *
 * To use it, you should create a new class derived from it and reimplement
 * main.
 */
@interface OFThread: OFObject
38
39
40
41
42
43
44




















45
46
47
48
49
50
51

/**
 * \param obj An object that is passed to the main method
 * \return A new, autoreleased thread
 */
+ threadWithObject: (id)obj;





















/**
 * \param obj An object that is passed to the main method
 * \return An initialized OFThread.
 */
- initWithObject: (id)obj;

/**







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







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

/**
 * \param obj An object that is passed to the main method
 * \return A new, autoreleased thread
 */
+ threadWithObject: (id)obj;

/**
 * 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.
 *
 * \param key The Thread Local Storage key
 * \param obj The object the Thread Local Storage key will be set to
 */
+ setObject: (id)obj
  forTLSKey: (OFTLSKey*)key;

/**
 * Returns the object for the specified Thread Local Storage key.
 *
 * \param key The Thread Local Storage key
 */
+ (id)objectForTLSKey: (OFTLSKey*)key;

/**
 * \param obj An object that is passed to the main method
 * \return An initialized OFThread.
 */
- initWithObject: (id)obj;

/**

Modified src/OFThread.m from [170f123979] to [afc7a8ea8e].

40
41
42
43
44
45
46

















































47
48
49
50
51
52
53
	 *
	 * The reason is that you derive from OFThread and reimplement main.
	 * If OFThread instead of self would be used here, the reimplemented
	 * main would never be called.
	 */
	return [[[self alloc] initWithObject: obj] autorelease];
}


















































- initWithObject: (id)obj
{
	Class c;

	self = [super init];
	object = obj;







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







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
	 *
	 * The reason is that you derive from OFThread and reimplement main.
	 * If OFThread instead of self would be used here, the reimplemented
	 * main would never be called.
	 */
	return [[[self alloc] initWithObject: obj] autorelease];
}

+ setObject: (id)obj
  forTLSKey: (OFTLSKey*)key
{
	id old;

	@try {
		old = [self objectForTLSKey: key];
	} @catch (OFNotInSetException *e) {
		[e free];
		old = nil;
	}

#ifndef _WIN32
	if (pthread_setspecific(key->key, obj))
#else
	if (!TlsSetValue(key->key, obj))
#endif
		/* FIXME: Maybe another exception would be better */
		@throw [OFNotInSetException newWithClass: self];

	if (obj != nil)
		[obj retain];
	if (old != nil)
		[old release];

	return self;
}

+ (id)objectForTLSKey: (OFTLSKey*)key
{
	void *ret;

#ifndef _WIN32
	ret = pthread_getspecific(key->key);
#else
	ret = TlsGetValue(key->key);
#endif

	/*
	 * NULL and nil might be different on some platforms. NULL is returned
	 * if the key is missing, nil can be returned if it was explicitly set
	 * to nil to release the old object.
	 */
	if (ret == NULL || (id)ret == nil)
		@throw [OFNotInSetException newWithClass: self];

	return (id)ret;
}

- initWithObject: (id)obj
{
	Class c;

	self = [super init];
	object = obj;
109
110
111
112
113
114
115



























		CloseHandle(thread);
	}
#endif

	return [super free];
}
@end


































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
		CloseHandle(thread);
	}
#endif

	return [super free];
}
@end

@implementation OFTLSKey
+ tlsKeyWithDestructor: (void(*)(void*))destructor
{
	return [[[OFTLSKey alloc] initWithDestructor: destructor] autorelease];
}

- initWithDestructor: (void(*)(void*))destructor
{
	Class c;

	self = [super init];

	/* FIXME: Call destructor on Win32 */
#ifndef _WIN32
	if (pthread_key_create(&key, destructor)) {
#else
	if ((key = TlsAlloc()) == TLS_OUT_OF_INDEXES) {
#endif
		c = isa;
		[super free];
		@throw [OFInitializationFailedException newWithClass: c];
	}

	return self;
}
@end