1 /*
   2  * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #ifndef __THREADUTILITIES_H
  27 #define __THREADUTILITIES_H
  28 
  29 #import <pthread.h>
  30 
  31 #import "AWT_debug.h"
  32 
  33 
  34 // --------------------------------------------------------------------------
  35 #ifndef PRODUCT_BUILD
  36 
  37 // Turn on the AWT thread assert mechanism. See below for different variants.
  38 // TODO: don't enable this for production builds...
  39 #define AWT_THREAD_ASSERTS
  40 
  41 #endif /* PRODUCT_BUILD */
  42 // --------------------------------------------------------------------------
  43 
  44 // --------------------------------------------------------------------------
  45 #ifdef AWT_THREAD_ASSERTS
  46 
  47 // Turn on to have awt thread asserts display a message on the console.
  48 #define AWT_THREAD_ASSERTS_MESSAGES
  49 
  50 // Turn on to have awt thread asserts use an environment variable switch to
  51 // determine if assert should really be called.
  52 //#define AWT_THREAD_ASSERTS_ENV_ASSERT
  53 
  54 // Define AWT_THREAD_ASSERTS_WAIT to make asserts halt the asserting thread
  55 // for debugging purposes.
  56 //#define AWT_THREAD_ASSERTS_WAIT
  57 
  58 #ifdef AWT_THREAD_ASSERTS_MESSAGES
  59 
  60 #define AWT_THREAD_ASSERTS_NOT_APPKIT_MESSAGE \
  61     AWT_DEBUG_LOG(@"Not running on AppKit thread 0 when expected.")
  62 
  63 #define AWT_THREAD_ASSERTS_ON_APPKIT_MESSAGE \
  64     AWT_DEBUG_LOG(@"Running on AppKit thread 0 when not expected.")
  65 
  66 #ifdef AWT_THREAD_ASSERTS_ENV_ASSERT
  67 
  68 extern int sAWTThreadAsserts;
  69 #define AWT_THREAD_ASSERTS_ENV_ASSERT_CHECK    \
  70 do {                                           \
  71     if (sAWTThreadAsserts) {                   \
  72         NSLog(@"\tPlease run this java program again with setenv COCOA_AWT_DISABLE_THREAD_ASSERTS to proceed with a warning."); \
  73         assert(NO);                            \
  74     }                                          \
  75 } while (0)
  76 
  77 #else
  78 
  79 #define AWT_THREAD_ASSERTS_ENV_ASSERT_CHECK do {} while (0)
  80 
  81 #endif /* AWT_THREAD_ASSERTS_ENV_ASSERT */
  82 
  83 #define AWT_ASSERT_APPKIT_THREAD               \
  84 do {                                           \
  85     if (pthread_main_np() == 0) {              \
  86         AWT_THREAD_ASSERTS_NOT_APPKIT_MESSAGE; \
  87         AWT_DEBUG_BUG_REPORT_MESSAGE;          \
  88         AWT_THREAD_ASSERTS_ENV_ASSERT_CHECK;   \
  89     }                                          \
  90 } while (0)
  91 
  92 #define AWT_ASSERT_NOT_APPKIT_THREAD           \
  93 do {                                           \
  94     if (pthread_main_np() != 0) {              \
  95         AWT_THREAD_ASSERTS_ON_APPKIT_MESSAGE;  \
  96         AWT_DEBUG_BUG_REPORT_MESSAGE;          \
  97         AWT_THREAD_ASSERTS_ENV_ASSERT_CHECK;   \
  98     }                                          \
  99 } while (0)
 100 
 101 #define AWT_ASSERT_ANY_THREAD
 102 
 103 #endif /* AWT_THREAD_ASSERTS_MESSAGES */
 104 
 105 #ifdef AWT_THREAD_ASSERTS_WAIT
 106 
 107 #define AWT_ASSERT_APPKIT_THREAD      \
 108 do {                                  \
 109     while (pthread_main_np() == 0) {} \
 110 } while (0)
 111 
 112 #define AWT_ASSERT_NOT_APPKIT_THREAD  \
 113 do {                                  \
 114     while (pthread_main_np() != 0) {} \
 115 } while (0)
 116 
 117 #define AWT_ASSERT_ANY_THREAD
 118 
 119 #endif /* AWT_THREAD_ASSERTS_WAIT */
 120 
 121 #else /* AWT_THREAD_ASSERTS */
 122 
 123 #define AWT_ASSERT_APPKIT_THREAD     do {} while (0)
 124 #define AWT_ASSERT_NOT_APPKIT_THREAD do {} while (0)
 125 #define AWT_ASSERT_ANY_THREAD
 126 
 127 #endif /* AWT_THREAD_ASSERTS */
 128 // --------------------------------------------------------------------------
 129 
 130 // This tracks if we are current inside of a performOnMainThread that is both waiting and in the AWTRunLoopMode
 131 extern BOOL sInPerformFromJava;
 132 
 133 // This is an empty Obj-C object just so that -performSelectorOnMainThread
 134 // can be used, and to use the Obj-C +initialize feature.
 135 __attribute__((visibility("default")))
 136 @interface ThreadUtilities : NSObject { }
 137 
 138 + (JNIEnv*)getJNIEnv;
 139 + (JNIEnv*)getJNIEnvUncached;
 140 
 141 + (void)performOnMainThread:(SEL)aSelector onObject:(id)target withObject:(id)arg waitUntilDone:(BOOL)wait awtMode:(BOOL)inAWT;
 142 + (void)performOnMainThreadWaiting:(BOOL)wait block:(void (^)())block;
 143 @end
 144 
 145 void OSXAPP_SetJavaVM(JavaVM *vm);
 146 
 147 #endif /* __THREADUTILITIES_H */