1 /* Control of executable units within a shared virtual memory space 2 Copyright (C) 1996 Free Software Foundation, Inc. 3 4 Original Author: Scott Christley <scottc@net-community.com> 5 Rewritten by: Andrew McCallum <mccallum@gnu.ai.mit.edu> 6 Created: 1996 7 8 This file is part of the GNUstep Objective-C Library. 9 10 This library is free software; you can redistribute it and/or 11 modify it under the terms of the GNU Lesser General Public 12 License as published by the Free Software Foundation; either 13 version 2 of the License, or (at your option) any later version. 14 15 This library is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 Lesser General Public License for more details. 19 20 You should have received a copy of the GNU Lesser General Public 21 License along with this library; if not, write to the Free 22 Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 23 Boston, MA 02110 USA. 24 */ 25 26 #ifndef __NSThread_h_GNUSTEP_BASE_INCLUDE 27 #define __NSThread_h_GNUSTEP_BASE_INCLUDE 28 #import <GNUstepBase/GSVersionMacros.h> 29 30 #if defined(GNUSTEP_BASE_INTERNAL) 31 #import "Foundation/NSAutoreleasePool.h" // for struct autorelease_thread_vars 32 #import "Foundation/NSException.h" // for NSHandler 33 #else 34 #import <Foundation/NSAutoreleasePool.h> 35 #import <Foundation/NSException.h> 36 #endif 37 38 @class NSArray; 39 @class NSDate; 40 @class NSMutableDictionary; 41 42 #if defined(__cplusplus) 43 extern "C" { 44 #endif 45 46 /** 47 * This class encapsulates OpenStep threading. See [NSLock] and its 48 * subclasses for handling synchronisation between threads.<br /> 49 * Each process begins with a main thread and additional threads can 50 * be created using NSThread. The GNUstep implementation of OpenStep 51 * has been carefully designed so that the internals of the base 52 * library do not use threading (except for methods which explicitly 53 * deal with threads of course) so that you can write applications 54 * without threading. Non-threaded applications are more efficient 55 * (no locking is required) and are easier to debug during development. 56 */ 57 @interface NSThread : NSObject 58 { 59 #if GS_EXPOSE(NSThread) 60 @public 61 id _target; 62 id _arg; 63 SEL _selector; 64 NSString *_name; 65 NSUInteger _stackSize; 66 BOOL _cancelled; 67 BOOL _active; 68 BOOL _finished; 69 NSHandler *_exception_handler; // Not retained. 70 NSMutableDictionary *_thread_dictionary; 71 struct autorelease_thread_vars _autorelease_vars; 72 id _gcontext; 73 void *_runLoopInfo; // Per-thread runloop related info. 74 #endif 75 #if GS_NONFRAGILE 76 # if defined(GS_NSThread_IVARS) 77 @public GS_NSThread_IVARS; 78 # endif 79 #else 80 /* Pointer to private additional data used to avoid breaking ABI 81 * when we don't have the non-fragile ABI available. 82 * Use this mechanism rather than changing the instance variable 83 * layout (see Source/GSInternal.h for details). 84 */ 85 @private id _internal GS_UNUSED_IVAR; 86 #endif 87 } 88 89 /** 90 * <p> 91 * Returns the NSThread object corresponding to the current thread. 92 * </p> 93 * <p> 94 * NB. In GNUstep the library internals use the GSCurrentThread() 95 * function as a more efficient mechanism for doing this job - so 96 * you cannot use a category to override this method and expect 97 * the library internals to use your implementation. 98 * </p> 99 */ 100 + (NSThread*) currentThread; 101 102 /** 103 * <p>Create a new thread - use this method rather than alloc-init. The new 104 * thread will begin executing the message given by aSelector, aTarget, and 105 * anArgument. This should have no return value, and must set up an 106 * autorelease pool if retain/release memory management is used. It should 107 * free this pool before it finishes execution.</p> 108 */ 109 + (void) detachNewThreadSelector: (SEL)aSelector 110 toTarget: (id)aTarget 111 withObject: (id)anArgument; 112 113 /** 114 * Terminates the current thread.<br /> 115 * Normally you don't need to call this method explicitly, 116 * since exiting the method with which the thread was detached 117 * causes this method to be called automatically. 118 */ 119 + (void) exit; 120 121 /** 122 * Returns a flag to say whether the application is multi-threaded or not.<br /> 123 * An application is considered to be multi-threaded if any thread other 124 * than the main thread has been started, irrespective of whether that 125 * thread has since terminated.<br /> 126 * NB. This method returns YES if called within a handler processing 127 * <code>NSWillBecomeMultiThreadedNotification</code> 128 */ 129 + (BOOL) isMultiThreaded; 130 + (void) sleepUntilDate: (NSDate*)date; 131 132 - (NSMutableDictionary*) threadDictionary; 133 134 #if OS_API_VERSION(MAC_OS_X_VERSION_10_2,GS_API_LATEST) \ 135 && GS_API_VERSION( 10200,GS_API_LATEST) 136 + (void) setThreadPriority: (double)pri; 137 + (double) threadPriority; 138 #endif 139 140 #if OS_API_VERSION(MAC_OS_X_VERSION_10_5,GS_API_LATEST) \ 141 && GS_API_VERSION( 11501,GS_API_LATEST) 142 143 /** Returns an array of the call stack return addresses. 144 */ 145 + (NSArray*) callStackReturnAddresses; 146 147 /** Returns a boolean indicating whether this thread is the main thread of 148 * the process. 149 */ 150 + (BOOL) isMainThread; 151 152 /** Returns the main thread of the process. 153 */ 154 + (NSThread*) mainThread; 155 156 /** Suspends execution of the process for the specified period. 157 */ 158 + (void) sleepForTimeInterval: (NSTimeInterval)ti; 159 160 /** Cancels the receiving thread. 161 */ 162 - (void) cancel; 163 164 /** <init/> 165 */ 166 - (id) init; 167 168 /** Initialises the receiver to send the message aSelector to the object aTarget 169 * with the argument anArgument (which may be nil).<br /> 170 * The arguments aTarget and aSelector are retained while the thread is 171 * running. 172 */ 173 - (id) initWithTarget: (id)aTarget 174 selector: (SEL)aSelector 175 object: (id)anArgument; 176 177 /** Returns a boolean indicating whether the receiving 178 * thread has been cancelled. 179 */ 180 - (BOOL) isCancelled; 181 182 /** Returns a boolean indicating whether the receiving 183 * thread has been started (and has not yet finished or been cancelled). 184 */ 185 - (BOOL) isExecuting; 186 187 /** Returns a boolean indicating whether the receiving 188 * thread has completed executing. 189 */ 190 - (BOOL) isFinished; 191 192 /** Returns a boolean indicating whether this thread is the main thread of 193 * the process. 194 */ 195 - (BOOL) isMainThread; 196 197 /** FIXME ... what does this do? 198 */ 199 - (void) main; 200 201 /** Returns the name of the receiver. 202 */ 203 - (NSString*) name; 204 205 /** Sets the name of the receiver. 206 */ 207 - (void) setName: (NSString*)aName; 208 209 /** Sets the size of the receiver's stack. 210 */ 211 - (void) setStackSize: (NSUInteger)stackSize; 212 213 /** Returns the size of the receiver's stack. 214 */ 215 - (NSUInteger) stackSize; 216 217 /** Starts the receiver executing. 218 */ 219 - (void) start; 220 #endif 221 222 @end 223 224 /** 225 * Extra methods to permit messages to be sent to an object such that they 226 * are executed in <em>another</em> thread.<br /> 227 * The main thread is the thread in which the GNUstep system is started, 228 * and where the GNUstep gui is used, it is the thread in which gui 229 * drawing operations <strong>must</strong> be performed. 230 */ 231 @interface NSObject(NSThreadPerformAdditions) 232 #if GS_API_VERSION(MAC_OS_X_VERSION_10_2, GS_API_LATEST) 233 /** 234 * <p>This method performs aSelector on the receiver, passing anObject as 235 * an argument, but does so in the main thread of the program. The receiver 236 * and anObject are both retained until the method is performed. 237 * </p> 238 * <p>The selector is performed when the runloop of the main thread next 239 * runs in one of the modes specified in anArray.<br /> 240 * Where this method has been called more than once before the runloop 241 * of the main thread runs in the required mode, the order in which the 242 * operations in the main thread is done is the same as that in which 243 * they were added using this method. 244 * </p> 245 * <p>If there are no modes in anArray, 246 * the method has no effect and simply returns immediately. 247 * </p> 248 * <p>The argument aFlag specifies whether the method should wait until 249 * the selector has been performed before returning.<br /> 250 * <strong>NB.</strong> This method does <em>not</em> cause the runloop of 251 * the main thread to be run ... so if the runloop is not executed by some 252 * code in the main thread, the thread waiting for the perform to complete 253 * will block forever. 254 * </p> 255 * <p>As a special case, if aFlag == YES and the current thread is the main 256 * thread, the modes array is ignored and the selector is performed immediately. 257 * This behavior is necessary to avoid the main thread being blocked by 258 * waiting for a perform which will never happen because the runloop is 259 * not executing. 260 * </p> 261 */ 262 - (void) performSelectorOnMainThread: (SEL)aSelector 263 withObject: (id)anObject 264 waitUntilDone: (BOOL)aFlag 265 modes: (NSArray*)anArray; 266 /** 267 * Invokes -performSelectorOnMainThread:withObject:waitUntilDone:modes: 268 * using the supplied arguments and an array containing common modes.<br /> 269 * These modes consist of NSRunLoopMode, NSConnectionReplyMode, and if 270 * in an application, the NSApplication modes. 271 */ 272 - (void) performSelectorOnMainThread: (SEL)aSelector 273 withObject: (id)anObject 274 waitUntilDone: (BOOL)aFlag; 275 #endif 276 #if GS_API_VERSION(MAC_OS_X_VERSION_10_5, GS_API_LATEST) 277 /** 278 * <p>This method performs aSelector on the receiver, passing anObject as 279 * an argument, but does so in the specified thread. The receiver 280 * and anObject are both retained until the method is performed. 281 * </p> 282 * <p>The selector is performed when the runloop of aThread next 283 * runs in one of the modes specified in anArray.<br /> 284 * Where this method has been called more than once before the runloop 285 * of the thread runs in the required mode, the order in which the 286 * operations in the thread is done is the same as that in which 287 * they were added using this method. 288 * </p> 289 * <p>If there are no modes in anArray, 290 * the method has no effect and simply returns immediately. 291 * </p> 292 * <p>The argument aFlag specifies whether the method should wait until 293 * the selector has been performed before returning.<br /> 294 * <strong>NB.</strong> This method does <em>not</em> cause the runloop of 295 * aThread to be run ... so if the runloop is not executed by some 296 * code in aThread, the thread waiting for the perform to complete 297 * will block forever. 298 * </p> 299 * <p>As a special case, if aFlag == YES and the current thread is aThread, 300 * the modes array is ignored and the selector is performed immediately. 301 * This behavior is necessary to avoid the current thread being blocked by 302 * waiting for a perform which will never happen because the runloop is 303 * not executing. 304 * </p> 305 */ 306 - (void) performSelector: (SEL)aSelector 307 onThread: (NSThread*)aThread 308 withObject: (id)anObject 309 waitUntilDone: (BOOL)aFlag 310 modes: (NSArray*)anArray; 311 /** 312 * Invokes -performSelector:onThread:withObject:waitUntilDone:modes: 313 * using the supplied arguments and an array containing common modes.<br /> 314 * These modes consist of NSRunLoopMode, NSConnectionreplyMode, and if 315 * in an application, the NSApplication modes. 316 */ 317 - (void) performSelector: (SEL)aSelector 318 onThread: (NSThread*)aThread 319 withObject: (id)anObject 320 waitUntilDone: (BOOL)aFlag; 321 322 /** 323 * Creates and runs a new background thread sending aSelector to the receiver 324 * and passing anObject (which may be nil) as the argument. 325 */ 326 - (void) performSelectorInBackground: (SEL)aSelector 327 withObject: (id)anObject; 328 #endif 329 @end 330 331 @interface NSThread (CallStackSymbols) 332 #if GS_API_VERSION(MAC_OS_X_VERSION_10_6, GS_API_LATEST) 333 /** Returns an array of NSString objects representing the current stack 334 * in an implementation-defined format. May return an empty array if 335 * this feature is not available. 336 */ 337 + (NSArray *) callStackSymbols; 338 #endif 339 @end 340 341 #if GS_API_VERSION(GS_API_NONE, GS_API_NONE) 342 /* 343 * Don't use the following functions unless you really know what you are 344 * doing ! 345 * The following functions are low-levelish and special. 346 * They are meant to make it possible to run GNUstep code in threads 347 * created in completely different environment, eg inside a JVM. 348 * 349 * If you use them, make sure you initialize the NSThread class inside 350 * (what you consider to be your) main thread, before registering any 351 * other thread. To initialize NSThread, simply call GSCurrentThread 352 * (). The main thread will not need to be registered. 353 */ 354 355 /* 356 * Register an external thread (created using your OS thread interface 357 * directly) to GNUstep. This means that it creates a NSThread object 358 * corresponding to the current thread, and sets things up so that you 359 * can run GNUstep code inside the thread. If the thread was not 360 * known to GNUstep, this function registers it, and returns YES. If 361 * the thread was already known to GNUstep, this function does nothing 362 * and returns NO. */ 363 GS_EXPORT BOOL GSRegisterCurrentThread (void); 364 /* 365 * Unregister the current thread from GNUstep. You must only 366 * unregister threads which have been register using 367 * registerCurrentThread (). This method is basically the same as 368 * `+exit', but does not exit the thread - just destroys all objects 369 * associated with the thread. Warning: using any GNUstep code after 370 * this method call is not safe. Posts an NSThreadWillExit 371 * notification. */ 372 GS_EXPORT void GSUnregisterCurrentThread (void); 373 374 /* Internal API used by traced locks. 375 */ 376 @interface NSThread (GSLockInfo) 377 378 /* Removes the mutex (either as the one we are waiting for or as a held mutex. 379 * For internal use only ... do not call this method.<br /> 380 */ 381 - (NSString *) mutexDrop: (id)mutex; 382 383 /* Converts a waiting mutex to a held one (if mutex is nil), or increments 384 * the recursion count of a mutex already held by this thread.<br /> 385 * For internal use only ... do not call this method. 386 */ 387 - (NSString *) mutexHold: (id)mutex; 388 389 /* Register the mutex that the thread is waiting for.<br /> 390 * For internal use only ... do not call this method. 391 */ 392 - (NSString *) mutexWait: (id)mutex; 393 394 @end 395 396 #endif 397 398 /* 399 * Notification Strings. 400 * NSBecomingMultiThreaded and NSThreadExiting are defined for strict 401 * OpenStep compatibility, the actual notification names are the more 402 * modern OPENSTEP/MacOS versions. 403 */ 404 405 /** 406 * Notification posted the first time a new [NSThread] is created or a 407 * separate thread from another library is registered in an application. 408 * (The initial thread that a program starts with does <em>not</em> 409 * post this notification.) Before such a notification has been posted you 410 * can assume the application is in single-threaded mode and locks are not 411 * necessary. Afterwards multiple threads <em>may</em> be running. 412 */ 413 GS_EXPORT NSString* const NSWillBecomeMultiThreadedNotification; 414 #define NSBecomingMultiThreaded NSWillBecomeMultiThreadedNotification 415 416 /** 417 * Notification posted when an [NSThread] instance receives an exit message, 418 * or an external thread has been deregistered. 419 */ 420 GS_EXPORT NSString* const NSThreadWillExitNotification; 421 #define NSThreadExiting NSThreadWillExitNotification 422 423 #if GS_API_VERSION(GS_API_NONE, GS_API_NONE) 424 425 /** 426 * Notification posted whenever a new thread is started up. This is a 427 * GNUstep extension. 428 */ 429 GS_EXPORT NSString* const NSThreadDidStartNotification; 430 431 #endif 432 433 #if !NO_GNUSTEP 434 # if defined(GNUSTEP_BASE_INTERNAL) 435 # import "GNUstepBase/NSThread+GNUstepBase.h" 436 # else 437 # import <GNUstepBase/NSThread+GNUstepBase.h> 438 # endif 439 #endif 440 441 #if defined(__cplusplus) 442 } 443 #endif 444 445 #endif /* __NSThread_h_GNUSTEP_BASE_INCLUDE */ 446