src/macosx/native/sun/osxapp/ThreadUtilities.m

Print this page

        

*** 35,65 **** static JNIEnv *appKitEnv = NULL; static NSArray *sPerformModes = nil; static NSArray *sAWTPerformModes = nil; - static BOOL sCocoaComponentCompatibility = NO; - static NSTimeInterval sCocoaComponentCompatibilityTimeout = 0.5; static BOOL sLoggingEnabled = YES; #ifdef AWT_THREAD_ASSERTS_ENV_ASSERT int sAWTThreadAsserts = 0; #endif /* AWT_THREAD_ASSERTS_ENV_ASSERT */ - - // This is for backward compatibility for those people using CocoaComponent - // Since we've flipped the AWT threading model for Tiger (10.4), all the rules - // for CocoaComponent are wrong. - // So for existing CocoaComponent users, we can't be synchronous. - // Making things totally asynchronous breaks a _lot_, so we try to be - // synchronous and time out after a little bit. - #define NOT_READY 0 - #define READY 1 - #define IN_PROGRESS 2 - BOOL sInPerformFromJava = NO; - NSUInteger sPerformCount = 0; // This class is used so that performSelectorOnMainThread can be // controlled a little more easily by us. It has 2 roles. // The first is to set/unset a flag (sInPerformFromJava) that code can // check to see if we are in a synchronous perform initiated by a java thread. --- 35,51 ----
*** 71,82 **** BOOL fWait; } - (id) initWithTarget:(id)target selector:(SEL)selector arg:(id)arg wait:(BOOL)wait; - (void) perform; - - (void) performCompatible; - - (void) _performCompatible:(NSConditionLock *)resultLock; @end @implementation CPerformer --- 57,66 ----
*** 111,122 **** BOOL nestedPerform = sInPerformFromJava; if (fWait) { sInPerformFromJava = YES; } - sPerformCount++; - // Actually do the work (cheat to avoid a method call) @try { objc_msgSend(fTarget, fSelector, fArg); //[fTarget performSelector:fSelector withObject:fArg]; } @catch (NSException *e) { --- 95,104 ----
*** 126,198 **** if (!nestedPerform && fWait) { sInPerformFromJava = NO; } } } - - - (void) performCompatible { - // We check if we are on the AppKit thread because frequently, apps - // using CocoaComponent are doing things on the wrong thread! - if (pthread_main_np()) { - [fTarget performSelector:fSelector withObject:fArg]; - } else { - // Setup the lock - NSConditionLock *resultLock = - [[NSConditionLock alloc] initWithCondition:NOT_READY]; - - // Make sure that if we return early, nothing gets released out - // from under us - [resultLock retain]; - [fTarget retain]; - [fArg retain]; - [self retain]; - // Do an asynchronous perform to the main thread. - [self performSelectorOnMainThread:@selector(_performCompatible:) - withObject:resultLock waitUntilDone:NO modes:sAWTPerformModes]; - - // Wait for a little bit for it to finish - [resultLock lockWhenCondition:READY beforeDate:[NSDate dateWithTimeIntervalSinceNow:sCocoaComponentCompatibilityTimeout]]; - - // If the _performCompatible is actually in progress, - // we should let it finish - if ([resultLock condition] == IN_PROGRESS) { - [resultLock lockWhenCondition:READY]; - } - - if ([resultLock condition] == NOT_READY && sLoggingEnabled) { - NSLog(@"[Java CocoaComponent compatibility mode]: Operation timed out due to possible deadlock: selector '%@' on target '%@' with args '%@'", NSStringFromSelector(fSelector), fTarget, fArg); - } - - [resultLock unlock]; - [resultLock autorelease]; - } - } - - - (void) _performCompatible:(NSConditionLock *)resultLock { - // notify that the perform is in progress! - [resultLock lock]; - [resultLock unlockWithCondition:IN_PROGRESS]; - - sPerformCount++; - - // Actually do the work. - @try { - [fTarget performSelector:fSelector withObject:fArg]; - } @catch (NSException *e) { - NSLog(@"*** CPerformer: ignoring exception '%@' raised during performCompatible of selector '%@' on target '%@' with args '%@'", e, NSStringFromSelector(fSelector), fTarget, fArg); - } @finally { - // notify done! - [resultLock lock]; - [resultLock unlockWithCondition:READY]; - - // Clean up after ourselves - [resultLock autorelease]; - [fTarget autorelease]; - [fArg autorelease]; - [self autorelease]; - } - } @end @implementation ThreadUtilities --- 108,117 ----
*** 234,260 **** // performSelector... In particular, we define a special runloop mode // (AWTRunLoopMode) so that we can "block" the main thread against the // java event thread without deadlocking. See CToolkit.invokeAndWait. + (void)performOnMainThread:(SEL)aSelector onObject:(id)target withObject:(id)arg waitUntilDone:(BOOL)wait awtMode:(BOOL)inAWT { CPerformer *performer = [[CPerformer alloc] initWithTarget:target selector:aSelector arg:arg wait:wait]; - if (sCocoaComponentCompatibility && wait && inAWT) { - [performer performCompatible]; - [performer autorelease]; - } else { [performer performSelectorOnMainThread:@selector(perform) withObject:nil waitUntilDone:wait modes:((inAWT) ? sAWTPerformModes : sPerformModes)]; // AWT_THREADING Safe (cover method) [performer release]; - } } + (void)performOnMainThreadWaiting:(BOOL)wait block:(void (^)())block { if ([NSThread isMainThread] && wait == YES) { block(); } else { [JNFRunLoop performOnMainThreadWaiting:wait withBlock:block]; } } @end void OSXAPP_SetJavaVM(JavaVM *vm) { --- 153,182 ---- // performSelector... In particular, we define a special runloop mode // (AWTRunLoopMode) so that we can "block" the main thread against the // java event thread without deadlocking. See CToolkit.invokeAndWait. + (void)performOnMainThread:(SEL)aSelector onObject:(id)target withObject:(id)arg waitUntilDone:(BOOL)wait awtMode:(BOOL)inAWT { CPerformer *performer = [[CPerformer alloc] initWithTarget:target selector:aSelector arg:arg wait:wait]; [performer performSelectorOnMainThread:@selector(perform) withObject:nil waitUntilDone:wait modes:((inAWT) ? sAWTPerformModes : sPerformModes)]; // AWT_THREADING Safe (cover method) [performer release]; } + (void)performOnMainThreadWaiting:(BOOL)wait block:(void (^)())block { if ([NSThread isMainThread] && wait == YES) { block(); } else { [JNFRunLoop performOnMainThreadWaiting:wait withBlock:block]; } } + + (void)performOnMainThread:(SEL)aSelector on:(id)target withObject:(id)arg waitUntilDone:(BOOL)wait { + if ([NSThread isMainThread] && wait == YES) { + [target performSelector:aSelector withObject:arg]; + } else { + [JNFRunLoop performOnMainThread:aSelector on:target withObject:arg waitUntilDone:wait]; + } + } + @end void OSXAPP_SetJavaVM(JavaVM *vm) {