Overview
Comment: | Greatly improve OFThread. This fixes a lot of issues that happened in the real world. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
ea96fd1e24b97c1866d044a634b508e3 |
User & Date: | js on 2010-04-10 21:29:39 |
Other Links: | manifest | tags |
Context
2010-04-10
| ||
21:35 | Add a few defines that Win32 needs. check-in: 5dc16f28aa user: js tags: trunk | |
21:29 |
Greatly improve OFThread. This fixes a lot of issues that happened in the real world. check-in: ea96fd1e24 user: js tags: trunk | |
16:46 | Improve error handling with sockets. check-in: baad47ed5b user: js tags: trunk | |
Changes
Modified src/OFExceptions.h from [ae635852ff] to [2ecc9888d8].
︙ | ︙ | |||
864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 | /** * \return The errno from when the exception was created */ - (int)errNo; @end /** * \brief An exception indicating that joining a thread failed. */ @interface OFThreadJoinFailedException: OFException {} @end /** * \brief An exception indicating that locking a mutex failed. */ @interface OFMutexLockFailedException: OFException {} @end /** | > > > > > > > > > > > > | 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 | /** * \return The errno from when the exception was created */ - (int)errNo; @end /** * \brief An exception indicating that starting a thread failed. */ @interface OFThreadStartFailedException: OFException {} @end /** * \brief An exception indicating that joining a thread failed. */ @interface OFThreadJoinFailedException: OFException {} @end /** * \brief An exception indicating that a thread is still running. */ @interface OFThreadStillRunningException: OFException {} @end /** * \brief An exception indicating that locking a mutex failed. */ @interface OFMutexLockFailedException: OFException {} @end /** |
︙ | ︙ |
Modified src/OFExceptions.m from [c18e0d43e4] to [67a9a0c742].
︙ | ︙ | |||
1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 | } - (int)errNo { return err; } @end @implementation OFThreadJoinFailedException - (OFString*)string { if (string != nil) return string; string = [[OFString alloc] initWithFormat: @"Joining a thread of class %s failed! Most likely, another thread " @"already waits for the thread to join.", [class_ className]]; return string; } @end @implementation OFMutexLockFailedException - (OFString*)string { | > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 | } - (int)errNo { return err; } @end @implementation OFThreadStartFailedException - (OFString*)string { if (string != nil) return string; string = [[OFString alloc] initWithFormat: @"Starting a thread of class %s failed!", [class_ className]]; return string; } @end @implementation OFThreadJoinFailedException - (OFString*)string { if (string != nil) return string; string = [[OFString alloc] initWithFormat: @"Joining a thread of class %s failed! Most likely, another thread " @"already waits for the thread to join.", [class_ className]]; return string; } @end @implementation OFThreadStillRunningException - (OFString*)string { if (string != nil) return string; string = [[OFString alloc] initWithFormat: @"Deallocation of a thread of type %s was tried, even though it " @"was still running", [class_ className]]; return string; } @end @implementation OFMutexLockFailedException - (OFString*)string { |
︙ | ︙ |
Modified src/OFThread.h from [bc1c5f6169] to [413f614157].
︙ | ︙ | |||
57 58 59 60 61 62 63 | * To use it, you should create a new class derived from it and reimplement * main. */ @interface OFThread: OFObject { id object; of_thread_t thread; | < > > > > > | 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | * 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 retval; } /** * \param obj An object that is passed to the main method as a copy or nil * \return A new autoreleased thread */ |
︙ | ︙ | |||
88 89 90 91 92 93 94 95 96 97 98 99 100 101 | /** * 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 as a copy or nil * \return An initialized OFThread. */ - initWithObject: (OFObject <OFCopying>*)obj; /** | > > > > > > > > > > > > > > > > > | | > > > > > > > > > > > | | 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 | /** * Returns the object for the specified Thread Local Storage key. * * \param key The Thread Local Storage key */ + (id)objectForTLSKey: (OFTLSKey*)key; /** * \return The current thread or nil if we are in the main thread */ + (OFThread*)currentThread; /** * Terminates the current thread, letting it return nil. */ + (void)terminate; /** * Terminates the current thread, letting it return the specified object. * * \param The object which the terminated thread will return */ + (void)terminateWithObject: (id)obj; /** * \param obj An object that is passed to the main method as a copy or nil * \return An initialized OFThread. */ - initWithObject: (OFObject <OFCopying>*)obj; /** * The run 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. * * \return The object the join method should return when called for this thread */ - (id)run; /** * This routine is exectued when the thread's run method has finished executing * or terminate has been called. */ - (void)handleTermination; /** * Starts the thread. */ - start; /** * Joins a thread. * * \return The object returned by the main method of the thread. */ - (id)join; @end /** * \brief A class for creating mutual exclusions. */ @interface OFMutex: OFObject { |
︙ | ︙ |
Modified src/OFThread.m from [6fc1e51add] to [4081c149ee].
︙ | ︙ | |||
15 16 17 18 19 20 21 22 23 | #import "OFList.h" #import "OFAutoreleasePool.h" #import "OFExceptions.h" #import "threading.h" static OFList *tlskeys; static id | > | > > > > | > > > > > > > > > > > > > > > | 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 | #import "OFList.h" #import "OFAutoreleasePool.h" #import "OFExceptions.h" #import "threading.h" static OFList *tlskeys; static of_tlskey_t thread_self; static id call_run(id obj) { if (!of_tlskey_set(thread_self, obj)) @throw [OFInitializationFailedException newWithClass: [obj class]]; /* * Nasty workaround for thread implementations which can't return a * value on join. */ ((OFThread*)obj)->retval = [[obj run] retain]; [obj handleTermination]; ((OFThread*)obj)->running = OF_THREAD_WAITING_FOR_JOIN; [OFTLSKey callAllDestructors]; [OFAutoreleasePool releaseAll]; [obj release]; return 0; } @implementation OFThread + (void)initialize { if (self != [OFThread class]) return; if (!of_tlskey_new(&thread_self)) @throw [OFInitializationFailedException newWithClass: self]; } + threadWithObject: (OFObject <OFCopying>*)obj { return [[[self alloc] initWithObject: obj] autorelease]; } + setObject: (OFObject*)obj forTLSKey: (OFTLSKey*)key |
︙ | ︙ | |||
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | return self; } + (id)objectForTLSKey: (OFTLSKey*)key { return [[of_tlskey_get(key->key) retain] autorelease]; } - init { @throw [OFNotImplementedException newWithClass: isa selector: _cmd]; } - initWithObject: (OFObject <OFCopying>*)obj { self = [super init]; object = [obj retain]; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | < < > > | > | > | | > | < | > > > > > > | | | > > | < < < < < | < > > > | 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 | return self; } + (id)objectForTLSKey: (OFTLSKey*)key { return [[of_tlskey_get(key->key) retain] autorelease]; } + (OFThread*)currentThread { return of_tlskey_get(thread_self); } + (void)terminate { [self terminateWithObject: nil]; } + (void)terminateWithObject: (id)obj { OFThread *thread = of_tlskey_get(thread_self); if (thread != nil) { thread->retval = [obj retain]; [thread handleTermination]; thread->running = OF_THREAD_WAITING_FOR_JOIN; } [OFTLSKey callAllDestructors]; [OFAutoreleasePool releaseAll]; [thread release]; of_thread_exit(); } - init { @throw [OFNotImplementedException newWithClass: isa selector: _cmd]; } - initWithObject: (OFObject <OFCopying>*)obj { self = [super init]; object = [obj retain]; return self; } - (id)run { @throw [OFNotImplementedException newWithClass: isa selector: _cmd]; return nil; } - (void)handleTermination { } - start { if (!of_thread_new(&thread, call_run, self)) @throw [OFThreadStartFailedException newWithClass: isa]; running = OF_THREAD_RUNNING; [self retain]; return self; } - (id)join { if (running != OF_THREAD_WAITING_FOR_JOIN || !of_thread_join(thread)) @throw [OFThreadJoinFailedException newWithClass: isa]; running = OF_THREAD_NOT_RUNNING; return retval; } - (void)dealloc { if (running == OF_THREAD_RUNNING) @throw [OFThreadStillRunningException newWithClass: isa]; [object release]; [retval release]; [super dealloc]; } @end @implementation OFTLSKey + (void)initialize { |
︙ | ︙ |
Modified src/threading.h from [ce91e6e1f3] to [49e86ee69a].
︙ | ︙ | |||
74 75 76 77 78 79 80 | CloseHandle(thread); return YES; #endif } | | | | < | < < < < | 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | CloseHandle(thread); return YES; #endif } static OF_INLINE void of_thread_exit() { #if defined(OF_HAVE_PTHREADS) pthread_exit(NULL); #elif defined(_WIN32) ExitThread(0); #endif } static OF_INLINE BOOL of_mutex_new(of_mutex_t *mutex) { #if defined(OF_HAVE_PTHREADS) |
︙ | ︙ |
Modified tests/OFThreadTests.m from [40840a8d67] to [0e44f6026c].
︙ | ︙ | |||
20 21 22 23 24 25 26 | static OFString *module = @"OFThread"; @interface TestThread: OFThread @end @implementation TestThread | | > > | 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 | static OFString *module = @"OFThread"; @interface TestThread: OFThread @end @implementation TestThread - (id)run { 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(@"-[run]", [t start]) TEST(@"-[join]", [[t join] isEqual: @"success"]) TEST(@"OFTLSKey's +[tlsKey]", (key = [OFTLSKey tlsKey])) TEST(@"+[setObject:forTLSKey:]", [OFThread setObject: @"foo" forTLSKey: key]) |
︙ | ︙ |