Overview
Comment: | Move platform-specific threading stuff to threading.h. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
15a67e8ee5133ee931cde4d4244a865d |
User & Date: | js on 2009-09-21 11:15:27 |
Other Links: | manifest | tags |
Context
2009-09-21
| ||
11:26 | Only check if snprintf returns required space if there's no asprintf. check-in: a6513f3228 user: js tags: trunk | |
11:15 | Move platform-specific threading stuff to threading.h. check-in: 15a67e8ee5 user: js tags: trunk | |
2009-09-17
| ||
13:40 | Update config.guess, config.sub and install-sh. check-in: c74def94fc user: js tags: trunk | |
Changes
Modified src/Makefile from [862b2d6a24] to [6fdc4aab1f].
︙ | ︙ | |||
29 30 31 32 33 34 35 | OFXMLElement.m \ OFXMLParser.m INCLUDESTMP := ${SRCS:.c=.h} INCLUDES := ${INCLUDESTMP:.m=.h} \ OFMacros.h \ asprintf.h \ | | > | 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | OFXMLElement.m \ OFXMLParser.m INCLUDESTMP := ${SRCS:.c=.h} INCLUDES := ${INCLUDESTMP:.m=.h} \ OFMacros.h \ asprintf.h \ objfw.h \ threading.h SRCS += ${OBJC_SYNC_M} \ ${ASPRINTF_C} include ../buildsys.mk CPPFLAGS += -I.. CFLAGS += ${LIB_CFLAGS} OBJCFLAGS += ${LIB_CFLAGS} LD = ${OBJC} |
Modified src/OFAutoreleasePool.m from [992a58ee6a] to [2c07550cc7].
︙ | ︙ | |||
9 10 11 12 13 14 15 | * the packaging of this file. */ #include "config.h" #include <stdlib.h> | < < < < < < > > < | < < < | < < < < < | < < < | | < < < < < < < < | < | < < < | < | | > > < < < < | | < < < < | < | < < < | < < < < | < | < < | | < < < | | | < | 9 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 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 | * the packaging of this file. */ #include "config.h" #include <stdlib.h> #import "OFAutoreleasePool.h" #import "OFList.h" #import "OFThread.h" #import "OFExceptions.h" #import "threading.h" /* * Pay special attention to NULL and nil in this file, they might be different! * Use NULL for TLS values and nil for instance variables. */ static of_tlskey_t first_key, last_key; #ifndef _WIN32 /* Not used on Win32 yet */ static void release_all(id obj) { [of_tlskey_get(first_key) release]; } #endif @implementation OFAutoreleasePool + (void)initialize { if (self != [OFAutoreleasePool class]) return; if (!of_tlskey_new(&first_key, release_all) || !of_tlskey_new(&last_key, NULL)) @throw [OFInitializationFailedException newWithClass: self]; } + (void)addObjectToTopmostPool: (OFObject*)obj { id last = of_tlskey_get(last_key); if (last == nil) { @try { [[self alloc] init]; } @catch (OFException *e) { [obj release]; @throw e; } last = of_tlskey_get(last_key); } if (last == nil) { [obj release]; @throw [OFInitializationFailedException newWithClass: self]; } @try { [last addObject: obj]; } @catch (OFException *e) { [obj release]; @throw e; } } - init { id first; self = [super init]; first = of_tlskey_get(first_key); prev = of_tlskey_get(last_key); if (!of_tlskey_set(last_key, self)) { Class c = isa; [super dealloc]; @throw [OFInitializationFailedException newWithClass: c]; } if (first == nil) { if (!of_tlskey_set(first_key, self)) { Class c = isa; of_tlskey_set(last_key, prev); [super dealloc]; @throw [OFInitializationFailedException newWithClass: c]; } } if (prev != nil) prev->next = self; return self; } - (void)dealloc { [next dealloc]; if (prev != nil) prev->next = nil; /* FIXME: Add exception? */ of_tlskey_set(last_key, prev); if (of_tlskey_get(first_key) == self) of_tlskey_set(first_key, nil); [objects release]; [super dealloc]; } - addObject: (OFObject*)obj |
︙ | ︙ |
Modified src/OFExceptions.m from [a8fc13d28b] to [77ebe09448].
︙ | ︙ | |||
981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 | @"Joining a thread of class %s failed! Most likely, another thread " @"already waits for the thread to join.", [class className]]; return string; } @end @implementation OFThreadCanceledException - (OFString*)string { if (string != nil) return string; string = [[OFString alloc] initWithFormat: @"The requested action cannot be performed because the thread of " @"class %s was canceled!", [class className]]; return string; } @end | > | 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 | @"Joining a thread of class %s failed! Most likely, another thread " @"already waits for the thread to join.", [class className]]; return string; } @end /* FIXME: Not needed anymore? */ @implementation OFThreadCanceledException - (OFString*)string { if (string != nil) return string; string = [[OFString alloc] initWithFormat: @"The requested action cannot be performed because the thread of " @"class %s was canceled!", [class className]]; return string; } @end |
Modified src/OFThread.h from [36e8a35200] to [894be3846a].
1 2 3 4 5 6 7 8 9 10 11 | /* * Copyright (c) 2008 - 2009 * Jonathan Schleifer <js@webkeks.org> * * All rights reserved. * * This file is part of libobjfw. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE included in * the packaging of this file. */ | | < < < < | < | < < < | | < | < < < | 1 2 3 4 5 6 7 8 9 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 | /* * Copyright (c) 2008 - 2009 * Jonathan Schleifer <js@webkeks.org> * * All rights reserved. * * This file is part of libobjfw. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE included in * the packaging of this file. */ #import "OFObject.h" #import "threading.h" /** * A Thread Local Storage key. */ @interface OFTLSKey: OFObject { @public of_tlskey_t key; } /** * \param destructor A destructor that is called when the thread is terminated * \return A new autoreleased Thread Local Storage key */ + tlsKeyWithDestructor: (void(*)(id))destructor; /** * \param destructor A destructor that is called when the thread is terminated * \return An initialized Thread Local Storage key */ - initWithDestructor: (void(*)(id))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 { id object; of_thread_t thread; @public id retval; } /** * \param obj An object that is passed to the main method as a copy or nil * \return A new autoreleased thread */ + threadWithObject: (id)obj; |
︙ | ︙ | |||
113 114 115 116 117 118 119 | @end /** * A class for creating mutual exclusions. */ @interface OFMutex: OFObject { | < | < < < | 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | @end /** * A class for creating mutual exclusions. */ @interface OFMutex: OFObject { of_mutex_t mutex; } /** * \return A new autoreleased mutex. */ + mutex; |
︙ | ︙ |
Modified src/OFThread.m from [1a195479da] to [72efe40c4e].
︙ | ︙ | |||
10 11 12 13 14 15 16 | */ #include "config.h" #import "OFThread.h" #import "OFExceptions.h" | < < < < | | < | | > | > > | < | < < < | < < < | < < < < < < < < < < < < < < < < < < | < < < < | < < < | < < < < < < < < < < < < < < | < < < < < < | | < < < | < < < | > > < | < < < < | < < < < | < < < < | < < < | 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 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 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 | */ #include "config.h" #import "OFThread.h" #import "OFExceptions.h" #import "threading.h" static id call_main(id obj) { /* * Nasty workaround for thread implementations which can't return a * value on join. */ ((OFThread*)obj)->retval = [obj main]; return 0; } @implementation OFThread + threadWithObject: (id)obj { return [[[self alloc] initWithObject: obj] autorelease]; } + setObject: (id)obj forTLSKey: (OFTLSKey*)key { id old = of_tlskey_get(key->key); if (!of_tlskey_set(key->key, [obj retain])) /* FIXME: Maybe another exception would be better */ @throw [OFInvalidArgumentException newWithClass: self selector: _cmd]; [old release]; return self; } + (id)objectForTLSKey: (OFTLSKey*)key { return [[of_tlskey_get(key->key) retain] autorelease]; } - init { @throw [OFNotImplementedException newWithClass: isa selector: _cmd]; } - initWithObject: (id)obj { self = [super init]; object = [obj copy]; if (!of_thread_new(&thread, call_main, self)) { Class c = isa; [super dealloc]; @throw [OFInitializationFailedException newWithClass: c]; } return self; } - main { return nil; } - join { of_thread_join(thread); return retval; } - (void)dealloc { /* * No need to handle errors - if canceling the thread fails, we can't * do anything anyway. Most likely, it finished already or was already * canceled. */ of_thread_cancel(thread); [object release]; [super dealloc]; } @end @implementation OFTLSKey + tlsKeyWithDestructor: (void(*)(id))destructor { return [[[self alloc] initWithDestructor: destructor] autorelease]; } - initWithDestructor: (void(*)(id))destructor { self = [super init]; /* FIXME: Call destructor on Win32 */ if (!of_tlskey_new(&key, destructor)) { Class c = isa; [super dealloc]; @throw [OFInitializationFailedException newWithClass: c]; } return self; } /* FIXME: Add dealloc! */ @end @implementation OFMutex + mutex { return [[[self alloc] init] autorelease]; } - init { self = [super init]; if (!of_mutex_new(&mutex)) { Class c = isa; [self dealloc]; @throw [OFInitializationFailedException newWithClass: c]; } return self; } - lock { /* FIXME: Add error-handling */ of_mutex_lock(&mutex); return self; } - unlock { /* FIXME: Add error-handling */ of_mutex_unlock(&mutex); return self; } - (void)dealloc { /* FIXME: Add error-handling */ of_mutex_free(&mutex); [super dealloc]; } @end |
Modified src/objc_sync.m from [8a15b08565] to [441808ccaa].
︙ | ︙ | |||
11 12 13 14 15 16 17 | #include "config.h" #include <stdio.h> #include <stdlib.h> #include <assert.h> | < < < < < < < < | < | | < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | > | | | | | | 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 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 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 | #include "config.h" #include <stdio.h> #include <stdlib.h> #include <assert.h> #import <objc/objc.h> #import "threading.h" struct locks_s { id obj; size_t count; size_t recursion; of_thread_t thread; of_mutex_t mutex; }; static of_mutex_t mutex; static struct locks_s *locks = NULL; static size_t num_locks = 0; #define SYNC_ERR(f) \ { \ fprintf(stderr, "WARNING: %s failed in line %d!\n" \ "WARNING: This might result in a race " \ "condition!\n", f, __LINE__); \ return 1; \ } BOOL objc_sync_init() { return (of_mutex_new(&mutex) ? YES : NO); } int objc_sync_enter(id obj) { int i; if (obj == nil) return 0; if (!of_mutex_lock(&mutex)) SYNC_ERR("of_mutex_lock(&mutex)"); for (i = num_locks - 1; i >= 0; i--) { if (locks[i].obj == obj) { if (of_thread_is_current(locks[i].thread)) locks[i].recursion++; else { /* Make sure objc_sync_exit doesn't free it */ locks[i].count++; /* Unlock so objc_sync_exit can return */ if (!of_mutex_unlock(&mutex)) SYNC_ERR("of_mutex_unlock(&mutex)"); if (!of_mutex_lock(&locks[i].mutex)) { of_mutex_unlock(&mutex); SYNC_ERR( "of_mutex_lock(&locks[i].mutex"); } if (!of_mutex_lock(&mutex)) SYNC_ERR("of_mutex_lock(&mutex)"); assert(locks[i].recursion == 0); /* Update lock's active thread */ locks[i].thread = of_thread_current(); } if (!of_mutex_unlock(&mutex)) SYNC_ERR("of_mutex_unlock(&mutex)"); return 0; } } if (locks == NULL) { if ((locks = malloc(sizeof(struct locks_s))) == NULL) { of_mutex_unlock(&mutex); SYNC_ERR("malloc(...)"); } } else { struct locks_s *new_locks; if ((new_locks = realloc(locks, (num_locks + 1) * sizeof(struct locks_s))) == NULL) { of_mutex_unlock(&mutex); SYNC_ERR("realloc(...)"); } locks = new_locks; } locks[num_locks].obj = obj; locks[num_locks].count = 1; locks[num_locks].recursion = 0; locks[num_locks].thread = of_thread_current(); if (!of_mutex_new(&locks[num_locks].mutex)) { of_mutex_unlock(&mutex); SYNC_ERR("of_mutex_new(&locks[num_locks].mutex"); } if (!of_mutex_lock(&locks[num_locks].mutex)) { of_mutex_unlock(&mutex); SYNC_ERR("of_mutex_lock(&locks[num_locks].mutex"); } num_locks++; if (!of_mutex_unlock(&mutex)) SYNC_ERR("of_mutex_unlock(&mutex)"); return 0; } int objc_sync_exit(id obj) { int i; if (obj == nil) return 0; if (!of_mutex_lock(&mutex)) SYNC_ERR("of_mutex_lock(&mutex)"); for (i = num_locks - 1; i >= 0; i--) { if (locks[i].obj == obj) { if (locks[i].recursion > 0 && of_thread_is_current(locks[i].thread)) { locks[i].recursion--; if (!of_mutex_unlock(&mutex)) SYNC_ERR("of_mutex_unlock(&mutex)"); return 0; } if (!of_mutex_unlock(&locks[i].mutex)) { of_mutex_unlock(&mutex); SYNC_ERR("of_mutex_unlock(&locks[i].mutex)"); } locks[i].count--; if (locks[i].count == 0) { struct locks_s *new_locks = NULL; if (!of_mutex_free(&locks[i].mutex)) { of_mutex_unlock(&mutex); SYNC_ERR( "of_mutex_free(&locks[i].mutex"); } num_locks--; locks[i] = locks[num_locks]; if (num_locks == 0) { free(locks); new_locks = NULL; } else if ((new_locks = realloc(locks, num_locks * sizeof(struct locks_s))) == NULL) { of_mutex_unlock(&mutex); SYNC_ERR("realloc(...)"); } locks = new_locks; } if (!of_mutex_unlock(&mutex)) SYNC_ERR("of_mutex_unlock(&mutex)"); return 0; } } of_mutex_unlock(&mutex); SYNC_ERR("objc_sync_exit()"); } |
Added src/threading.h version [fc8a803188].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 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 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 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 | /* * Copyright (c) 2008 - 2009 * Jonathan Schleifer <js@webkeks.org> * * All rights reserved. * * This file is part of libobjfw. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE included in * the packaging of this file. */ #import "OFMacros.h" #ifndef _WIN32 #include <pthread.h> typedef pthread_t of_thread_t; typedef pthread_mutex_t of_mutex_t; typedef pthread_key_t of_tlskey_t; #else #include <windows.h> typedef HANDLE of_thread_t; typedef CRITICAL_SECTION of_mutex_t; typedef DWORD of_tlskey_t; #endif #ifndef _WIN32 #define of_thread_is_current(t) pthread_equal(t, pthread_self()) #define of_thread_current() pthread_self() #else #define of_thread_is_current(t) (t == GetCurrentThreadId()) #define of_thread_current() GetCurrentThreadId() #endif static OF_INLINE BOOL of_thread_new(of_thread_t *thread, id (*main)(id), id data) { #ifndef _WIN32 return (pthread_create(thread, NULL, (void*(*)(void*))main, (void*)data) ? NO : YES); #else *thread = CreateThread(NULL, 0, (void*(*)(void*))main, (void*)data, 0, NULL); return (thread == NULL ? NO : YES); #endif } static OF_INLINE BOOL of_thread_join(of_thread_t thread) { #ifndef _WIN32 void *ret; if (pthread_join(thread, &ret)) return NO; /* FIXME: Do we need a way to differentiate? */ return (ret != PTHREAD_CANCELED ? YES : NO); #else if (WaitForSingleObject(thread, INFINITE)) return NO; CloseHandle(thread); return YES; #endif } static OF_INLINE BOOL of_thread_cancel(of_thread_t thread) { #ifndef _WIN32 return (pthread_cancel(thread) ? NO : YES); #else if (thread != INVALID_HANDLE_VALUE) { TerminateThread(thread, 1); CloseHandle(thread); } return YES; #endif } static OF_INLINE BOOL of_mutex_new(of_mutex_t *mutex) { #ifndef _WIN32 return (pthread_mutex_init(mutex, NULL) ? NO : YES); #else InitializeCriticalSection(mutex); return YES; #endif } static OF_INLINE BOOL of_mutex_free(of_mutex_t *mutex) { #ifndef _WIN32 return (pthread_mutex_destroy(mutex) ? NO : YES); #else DeleteCriticalSection(mutex); return YES; #endif } static OF_INLINE BOOL of_mutex_lock(of_mutex_t *mutex) { #ifndef _WIN32 return (pthread_mutex_lock(mutex) ? NO : YES); #else EnterCriticalSection(mutex); return YES; #endif } static OF_INLINE BOOL of_mutex_unlock(of_mutex_t *mutex) { #ifndef _WIN32 return (pthread_mutex_unlock(mutex) ? NO : YES); #else LeaveCriticalSection(mutex); return YES; #endif } static OF_INLINE BOOL of_tlskey_new(of_tlskey_t *key, void (*destructor)(id)) { #ifndef _WIN32 return (pthread_key_create(key, (void(*)(void*))destructor) ? NO : YES); #else /* FIXME: Call destructor */ return ((*key = TlsAlloc()) == TLS_OUT_OF_INDEXES ? NO : YES); #endif } static OF_INLINE id of_tlskey_get(of_tlskey_t key) { #ifndef _WIN32 void *ret = pthread_getspecific(key); #else void *ret = TlsGetValue(key); #endif /* NULL and nil might be different! */ if (ret == NULL) return nil; return (id)ret; } static OF_INLINE BOOL of_tlskey_set(of_tlskey_t key, id obj) { void *p = (obj != nil ? (void*)obj : NULL); #ifndef _WIN32 return (pthread_setspecific(key, p) ? NO : YES); #else return (TlsSetValue(key, p) ? YES : NO); #endif } |