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