diff --git a/Headers/Foundation/NSRunLoop.h b/Headers/Foundation/NSRunLoop.h index b2957d9..6bf17ca 100644 --- a/Headers/Foundation/NSRunLoop.h +++ b/Headers/Foundation/NSRunLoop.h @@ -54,6 +54,7 @@ GS_EXPORT NSString * const NSDefaultRunLoopMode; } + (NSRunLoop*) currentRunLoop; ++ (NSRunLoop*) mainRunLoop; - (void) acceptInputForMode: (NSString*)mode beforeDate: (NSDate*)limit_date; diff --git a/Headers/GNUstepBase/NSThread+GNUstepBase.h b/Headers/GNUstepBase/NSThread+GNUstepBase.h index ef4b56c..100c29d 100644 --- a/Headers/GNUstepBase/NSThread+GNUstepBase.h +++ b/Headers/GNUstepBase/NSThread+GNUstepBase.h @@ -41,6 +41,7 @@ extern "C" { @end GS_EXPORT NSThread *GSCurrentThread(void); +GS_EXPORT BOOL GSIsMainThread(void); GS_EXPORT NSMutableDictionary *GSCurrentThreadDictionary(void); #endif /* OS_API_VERSION */ diff --git a/Source/NSObject.m b/Source/NSObject.m index 706c191..0fed1f7 100644 --- a/Source/NSObject.m +++ b/Source/NSObject.m @@ -1151,6 +1151,9 @@ static id gs_weak_load(id obj) GSPrivateDispatchInitialize(); #endif + /* Make sure that main thread is correctly set up. */ + GSCurrentThread(); + /* Now that we have a workign autorelease system and working string * classes we are able to set up notifications. */ diff --git a/Source/NSRunLoop.m b/Source/NSRunLoop.m index 42bfa32..e8d03e3 100644 --- a/Source/NSRunLoop.m +++ b/Source/NSRunLoop.m @@ -65,7 +65,8 @@ NSString * const NSDefaultRunLoopMode = @"NSDefaultRunLoopMode"; -static NSDate *theFuture = nil; +static NSDate *theFuture = nil; +static NSRunLoop *mainRunLoop = nil; @interface NSObject (OptionalPortRunLoop) - (void) getFds: (NSInteger*)fds count: (NSInteger*)count; @@ -722,7 +723,7 @@ static inline BOOL timerInvalidated(NSTimer *t) current = info->loop = [[self alloc] _init]; /* If this is the main thread, set up a housekeeping timer. */ - if ([GSCurrentThread() isMainThread] == YES) + if (GSIsMainThread() == YES) { NSAutoreleasePool *arp = [NSAutoreleasePool new]; GSRunLoopCtxt *context; @@ -766,11 +767,21 @@ static inline BOOL timerInvalidated(NSTimer *t) repeats: YES]; context->housekeeper = timer; [arp drain]; + + /* This is the run loop for the main thread: + * save it for everyone. + */ + mainRunLoop = current; } } return current; } ++ (NSRunLoop*) mainRunLoop +{ + return mainRunLoop; +} + - (id) init { DESTROY(self); diff --git a/Source/NSThread.m b/Source/NSThread.m index c3447bf..8bce09b 100644 --- a/Source/NSThread.m +++ b/Source/NSThread.m @@ -87,9 +87,12 @@ #if defined(__FreeBSD__) || defined(__OpenBSD__) # include -# define IS_MAIN_PTHREAD (pthread_main_np() == 1) +# define IS_MAIN_PTHREAD pthread_main_np() #else -# define IS_MAIN_PTHREAD (1) +# define MAIN_PTHREAD_NEEDS_LOAD 1 +# define IS_MAIN_PTHREAD pthread_equal(_main_pthread, pthread_self()) +/* clang is whining if it's static so make it global internal... */ +__attribute__((visibility("internal"))) pthread_t _main_pthread; #endif @@ -341,6 +344,12 @@ GSCurrentThread(void) return thr; } +inline BOOL +GSIsMainThread(void) +{ + return (GSCurrentThread() == defaultThread ? YES : NO); +} + NSMutableDictionary* GSDictionaryForThread(NSThread *t) { @@ -537,6 +546,13 @@ unregisterActiveThread(NSThread *thread) } } +#if MAIN_PTHREAD_NEEDS_LOAD ++ (void) load +{ + _main_pthread = pthread_self(); +} +#endif + /* * Class initialization */ @@ -1169,14 +1185,9 @@ GSRunLoopInfoForThread(NSThread *aThread) waitUntilDone: (BOOL)aFlag modes: (NSArray*)anArray { - /* It's possible that this method could be called before the NSThread - * class is initialised, so we check and make sure it's initiailised - * if necessary. + /* NSThread class is initialised in NSObject+initialize, + * so we don't need to check defaultThread initialization. */ - if (defaultThread == nil) - { - [NSThread currentThread]; - } [self performSelector: aSelector onThread: defaultThread withObject: anObject