2001-12-17 14:31:42 +00:00
/ * * Control of executable units within a shared virtual memory space
2000-04-19 12:29:17 +00:00
Copyright ( C ) 1996 -2000 Free Software Foundation , Inc .
1996-02-13 15:40:05 +00:00
(NSBecomingMultiThreaded, NSThreadExiting): Initialize the
notification strings as static strings, not in +initialize.
(thread_id_2_nsthread): Renamed from THREAD_LIST. Keep the collection
of NSThread's as a maptable, not a NSArray that takes linear time to
search!
(thread_lock): Renamed from THREAD_LIST_LOCK.
(entered_multi_threaded_state): Renamed from ENTERED_MULTI-THREADED_STATE.
([NSThread +initialize]): Don't initialize notification strings here.
Don't autorelease the lock!
([NSThread -init]): Initialize _thread_autorelease_pool. Set our
thread data to self, for easy, efficient access to this NSThread
object later. Put ourselves in the thread collection here, not in
+detach...
([NSThread +currentThread]): This will be called often and needs to be
fast. Reimplemented so we don't have to acquire a lock and step
through an NSArray of threads; instead, just look ourselves up with
the objc_thread_get_data(), and furthermore, no lock required.
([NSThread +detachNewThreadSelector:toTarget:withObject:]): Avoid race
condition, don't create new NSThread object here.
([NSThread +sleepUntilDate:]): Call -notImplemented:.
([NSThread +exit]): Properly post NSThreadExiting notification, making
sure not to hold the lock while we do so. Get the NSThread object
efficiently.
([NSThread -threadId]): Removed unnecessary private method.
([NSThread -setThreadId]): Likewise.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@1530 72102866-910b-0410-8b05-ffd578937521
1996-05-13 15:53:36 +00:00
Original Author : Scott Christley < scottc @ net - community . com >
Rewritten by : Andrew Kachites McCallum < mccallum @ gnu . ai . mit . edu >
Created : 1996
1999-05-10 06:45:36 +00:00
Rewritten by : Richard Frith - Macdonald < richard @ brainstorm . co . uk >
to add optimisations features for faster thread access .
2000-11-12 07:41:24 +00:00
Modified by : Nicola Pero < n . pero @ mi . flashnet . it >
2005-02-22 11:22:44 +00:00
to add GNUstep extensions allowing to interact with threads created
2000-11-12 07:41:24 +00:00
by external libraries / code ( eg , a Java Virtual Machine ) .
2005-02-22 11:22:44 +00:00
1996-02-13 15:40:05 +00:00
This file is part of the GNUstep Objective - C Library .
This library is free software ; you can redistribute it and / or
2007-09-14 11:36:11 +00:00
modify it under the terms of the GNU Lesser General Public
1996-02-13 15:40:05 +00:00
License as published by the Free Software Foundation ; either
2008-06-08 10:38:33 +00:00
version 2 of the License , or ( at your option ) any later version .
2005-02-22 11:22:44 +00:00
1996-02-13 15:40:05 +00:00
This library is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
Library General Public License for more details .
2007-09-14 11:36:11 +00:00
You should have received a copy of the GNU Lesser General Public
1996-02-13 15:40:05 +00:00
License along with this library ; if not , write to the Free
2006-06-04 06:42:10 +00:00
Software Foundation , Inc . , 51 Franklin Street , Fifth Floor ,
Boston , MA 02111 USA .
2001-12-18 16:54:15 +00:00
< title > NSThread class reference < / title >
$ Date $ $ Revision $
2005-02-22 11:22:44 +00:00
* /
1996-02-13 15:40:05 +00:00
2010-02-19 08:12:46 +00:00
# import "common.h"
2010-02-14 10:48:10 +00:00
# define EXPOSE_NSThread _IVARS 1
2002-05-02 21:22:06 +00:00
# ifdef HAVE_UNISTD _H
1999-06-24 19:30:29 +00:00
# include < unistd . h >
2002-02-20 06:42:05 +00:00
# endif
2003-07-17 09:00:31 +00:00
# ifdef HAVE_NANOSLEEP
# include < time . h >
# endif
2007-12-27 07:02:27 +00:00
# ifdef HAVE_SYS _TIME _H
# include < sys / time . h >
# endif
# ifdef HAVE_SYS _RESOURCE _H
# include < sys / resource . h >
# endif
# ifdef HAVE_PTHREAD _H
# include < pthread . h >
# endif
2008-09-23 08:10:59 +00:00
# ifdef HAVE_SYS _FILE _H
# include < sys / file . h >
# endif
# ifdef HAVE_SYS _FCNTL _H
2008-09-18 08:22:53 +00:00
# include < sys / fcntl . h >
2008-09-23 08:10:59 +00:00
# endif
# include < errno . h >
2008-09-18 08:22:53 +00:00
# ifdef __POSIX _SOURCE
# define NBLK_OPT O_NONBLOCK
# else
# define NBLK_OPT FNDELAY
# endif
2005-02-23 16:05:09 +00:00
2010-02-17 11:47:06 +00:00
# import "Foundation/NSException.h"
# import "Foundation/NSThread.h"
# import "Foundation/NSLock.h"
# import "Foundation/NSNotification.h"
# import "Foundation/NSNotificationQueue.h"
# import "Foundation/NSRunLoop.h"
# import "Foundation/NSConnection.h"
# import "Foundation/NSInvocation.h"
2011-03-16 12:17:02 +00:00
# import "Foundation/NSUserDefaults.h"
2011-05-26 13:24:13 +00:00
# import "Foundation/NSGarbageCollector.h"
1996-02-13 15:40:05 +00:00
2010-02-17 11:47:06 +00:00
# import "GSPrivate.h"
# import "GSRunLoopCtxt.h"
2002-11-03 18:56:46 +00:00
2009-01-13 15:57:38 +00:00
# if GS_WITH _GC
2011-02-27 17:53:14 +00:00
# include < gc / gc . h >
2009-01-13 15:57:38 +00:00
# endif
2011-05-26 13:24:13 +00:00
# if __OBJC _GC __
# include < objc / objc - auto . h >
# endif
2009-01-13 15:57:38 +00:00
2011-07-11 14:31:36 +00:00
# if defined ( __FreeBSD __ ) || defined ( __OpenBSD __ )
# include < pthread_np . h >
# define IS_MAIN _PTHREAD ( pthread_main _np ( ) = = 1 )
# else
# define IS_MAIN _PTHREAD ( 1 )
# endif
* Source/NSLock.m
* Headers/Foundation/NSLock.h
Completely rewritten implementations of NSLock.h classes. These are now
faster, more complete, OS X-compatible, and most importantly actually
work. The old ones, for example, called functions that were not
implemented on Windows.
* Source/NSThread.m
Call pthread functions directly in NSThread instead of via the libobjc
abstraction layer. Also fixed a few issues, such as GC not being
initialized properly for NSThread subclasses that override -main (Javaism
supported by OS X) and tidies up the code in several places, removing
premature optimizations, especially those that introduce a test for an
unlikely case at the start of a method and thus slow everything down.
As a result of this change, GNUstep now depends on an implementation of
POSIX threads. This is included as standard on all modern UNIX systems,
and as an option on less-modern UNIX systems and non-UNIX systems,
including Windows. If you are building GNUstep on Windows, please install
the pthreads-win32 package, available from:
http://sourceware.org/pthreads-win32/
PLEASE TEST THIS! There may be some code that depended on the old
behaviour. I have been running the new NSLock implementation on FreeBSD
for a few weeks without issue; please report to me any problems that you
have on your platform.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@28598 72102866-910b-0410-8b05-ffd578937521
2009-09-02 13:03:13 +00:00
// Some older BSD systems used a non - standard range of thread priorities .
// Use these if they exist , otherwise define standard ones .
# ifndef PTHREAD_MAX _PRIORITY
# define PTHREAD_MAX _PRIORITY 31
# endif
# ifndef PTHREAD_MIN _PRIORITY
# define PTHREAD_MIN _PRIORITY 0
# endif
2009-09-09 08:21:51 +00:00
2006-03-08 11:28:59 +00:00
@ interface NSAutoreleasePool ( NSThread )
+ ( void ) _endThread : ( NSThread * ) thread ;
@ end
2001-03-19 12:20:21 +00:00
static Class threadClass = Nil ;
2002-08-07 13:29:31 +00:00
static NSNotificationCenter * nc = nil ;
2001-03-19 12:20:21 +00:00
2005-07-08 11:48:37 +00:00
/ * *
* This class performs a dual function . . .
* < p >
* As a class , it is responsible for handling incoming events from
* the main runloop on a special inputFd . This consumes any bytes
* written to wake the main runloop . < br / >
* During initialisation , the default runloop is set up to watch
* for data arriving on inputFd .
* < / p >
* < p >
* As instances , each instance retains perform receiver and argument
* values as long as they are needed , and handles locking to support
2008-02-08 13:35:50 +00:00
* methods which want to block until an action has been performed .
2005-07-08 11:48:37 +00:00
* < / p >
* < p >
* The initialize method of this class is called before any new threads
* run .
* < / p >
* /
@ interface GSPerformHolder : NSObject
{
id receiver ;
id argument ;
SEL selector ;
NSConditionLock * lock ; // Not retained .
2008-03-17 15:23:11 +00:00
NSArray * modes ;
2008-03-18 05:45:05 +00:00
BOOL invalidated ;
2005-07-08 11:48:37 +00:00
}
+ ( GSPerformHolder * ) newForReceiver : ( id ) r
argument : ( id ) a
selector : ( SEL ) s
modes : ( NSArray * ) m
lock : ( NSConditionLock * ) l ;
- ( void ) fire ;
2008-03-18 05:45:05 +00:00
- ( void ) invalidate ;
- ( BOOL ) isInvalidated ;
2008-03-17 15:23:11 +00:00
- ( NSArray * ) modes ;
2005-07-08 11:48:37 +00:00
@ end
2003-07-20 06:37:25 +00:00
/ * *
* Sleep until the current date / time is the specified time interval
* past the reference date / time . < br / >
* Implemented as a function taking an NSTimeInterval argument in order
* to avoid objc messaging and object allocation / deallocation ( NSDate )
* overheads . < br / >
* Used to implement [ NSThread + sleepUntilDate : ]
2009-09-08 17:56:58 +00:00
* If the date is in the past , this function simply allows other threads
* ( if any ) to run .
2003-07-20 06:37:25 +00:00
* /
void
GSSleepUntilIntervalSinceReferenceDate ( NSTimeInterval when )
{
NSTimeInterval delay ;
// delay is always the number of seconds we still need to wait
2010-12-27 07:03:50 +00:00
delay = when - GSPrivateTimeNow ( ) ;
2009-09-09 08:21:51 +00:00
if ( delay <= 0.0 )
2009-09-08 17:56:58 +00:00
{
sched_yield ( ) ;
return ;
}
2003-07-20 06:37:25 +00:00
# ifdef HAVE_NANOSLEEP
// Avoid any possibility of overflow by sleeping in chunks .
while ( delay > 32768 )
{
struct timespec request ;
request . tv_sec = ( time_t ) 32768 ;
request . tv_nsec = ( long ) 0 ;
nanosleep ( & request , 0 ) ;
2010-12-27 07:03:50 +00:00
delay = when - GSPrivateTimeNow ( ) ;
2003-07-20 06:37:25 +00:00
}
if ( delay > 0 )
{
struct timespec request ;
struct timespec remainder ;
request . tv_sec = ( time_t ) delay ;
request . tv_nsec = ( long ) ( ( delay - request . tv_sec ) * 1000000000 ) ;
remainder . tv_sec = 0 ;
remainder . tv_nsec = 0 ;
/ *
* With nanosleep , we can restart the sleep after a signal by using
* the remainder information . . . so we can be sure to sleep to the
* desired limit without having to re - generate the delay needed .
* /
while ( nanosleep ( & request , & remainder ) < 0
&& ( remainder . tv_sec > 0 || remainder . tv_nsec > 0 ) )
{
request . tv_sec = remainder . tv_sec ;
request . tv_nsec = remainder . tv_nsec ;
remainder . tv_sec = 0 ;
remainder . tv_nsec = 0 ;
}
}
# else
/ *
* Avoid integer overflow by breaking up long sleeps .
* /
while ( delay > 30.0 * 60.0 )
{
// sleep 30 minutes
2010-03-19 12:10:11 +00:00
# if defined ( __MINGW __ )
2003-07-20 06:37:25 +00:00
Sleep ( 30 * 60 * 1000 ) ;
# else
sleep ( 30 * 60 ) ;
# endif
2010-12-27 07:03:50 +00:00
delay = when - GSPrivateTimeNow ( ) ;
2003-07-20 06:37:25 +00:00
}
/ *
* sleeping may return early because of signals , so we need to re - calculate
* the required delay and check to see if we need to sleep again .
* /
while ( delay > 0 )
{
2010-03-19 12:10:11 +00:00
# if defined ( __MINGW __ )
2010-02-03 09:45:45 +00:00
# if defined ( HAVE_USLEEP )
/ * On windows usleep ( ) seems to perform a busy wait . . . so we only
* use it for short delays . . . otherwise use the less accurate Sleep ( )
* /
if ( delay > 0.1 )
{
Sleep ( ( NSInteger ) ( delay * 1000 ) ) ;
}
else
{
usleep ( ( NSInteger ) ( delay * 1000000 ) ) ;
}
# else
2010-02-03 09:31:59 +00:00
Sleep ( ( NSInteger ) ( delay * 1000 ) ) ;
2010-02-03 09:45:45 +00:00
# endif / * HAVE_USLEEP * /
# else
# if defined ( HAVE_USLEEP )
2009-02-23 20:42:32 +00:00
usleep ( ( NSInteger ) ( delay * 1000000 ) ) ;
2003-07-20 06:37:25 +00:00
# else
2009-02-23 20:42:32 +00:00
sleep ( ( NSInteger ) delay ) ;
2010-02-03 09:45:45 +00:00
# endif / * HAVE_USLEEP * /
# endif / * __MINGW __ * /
2010-12-27 07:03:50 +00:00
delay = when - GSPrivateTimeNow ( ) ;
2003-07-20 06:37:25 +00:00
}
2010-02-03 09:45:45 +00:00
# endif / * HAVE_NANOSLEEP * /
2003-07-20 06:37:25 +00:00
}
2002-11-03 18:56:46 +00:00
static NSArray *
2003-12-23 17:41:38 +00:00
commonModes ( void )
2002-11-03 18:56:46 +00:00
{
static NSArray * modes = nil ;
if ( modes = = nil )
{
[ gnustep_global _lock lock ] ;
if ( modes = = nil )
{
Class c = NSClassFromString ( @ "NSApplication" ) ;
SEL s = @ selector ( allRunLoopModes ) ;
if ( c ! = 0 && [ c respondsToSelector : s ] )
{
modes = RETAIN ( [ c performSelector : s ] ) ;
}
else
{
modes = [ [ NSArray alloc ] initWithObjects :
NSDefaultRunLoopMode , NSConnectionReplyMode , nil ] ;
}
}
[ gnustep_global _lock unlock ] ;
}
return modes ;
}
2000-04-19 12:29:17 +00:00
/ *
* Flag indicating whether the objc runtime ever went multi - threaded .
* /
static BOOL entered_multi _threaded _state = NO ;
1996-02-13 15:40:05 +00:00
2009-09-08 20:32:52 +00:00
static NSThread * defaultThread ;
1996-02-13 15:40:05 +00:00
2009-09-08 20:32:52 +00:00
static pthread_key _t thread_object _key ;
2002-05-03 08:17:04 +00:00
/ * *
2009-09-08 20:32:52 +00:00
* Pthread cleanup call .
*
* We should normally not get here . . . because threads should exit properly
* and clean up , so that this function doesn ' t get called . However if a
* thread terminates for some reason without calling the exit method , we
* can at least log it .
*
* We can ' t do anything more than that since at the point
* when this function is called , the thread specific data is no longer
* available , so the currentThread method will always fail and the
* repercussions of that would well be a crash .
*
* As a special case , we ignore the exit of the default thread . . . that one
* will usually terminate without calling the exit method as it ends the
* whole process by returning from the ' main ' function .
2000-04-19 12:29:17 +00:00
* /
2009-09-08 20:32:52 +00:00
static void exitedThread ( void * thread )
1999-04-19 14:29:52 +00:00
{
2010-02-04 18:04:13 +00:00
if ( thread ! = defaultThread )
2009-09-08 20:32:52 +00:00
{
fprintf ( stderr , "WARNING thread %p terminated without calling +exit!\n" ,
thread ) ;
}
1999-04-19 14:29:52 +00:00
}
2002-05-03 08:17:04 +00:00
/ * *
2009-09-08 20:32:52 +00:00
* These functions needed because sending messages to classes is a seriously
* slow process with gcc and the gnu runtime .
2000-04-19 12:29:17 +00:00
* /
* Source/NSLock.m
* Headers/Foundation/NSLock.h
Completely rewritten implementations of NSLock.h classes. These are now
faster, more complete, OS X-compatible, and most importantly actually
work. The old ones, for example, called functions that were not
implemented on Windows.
* Source/NSThread.m
Call pthread functions directly in NSThread instead of via the libobjc
abstraction layer. Also fixed a few issues, such as GC not being
initialized properly for NSThread subclasses that override -main (Javaism
supported by OS X) and tidies up the code in several places, removing
premature optimizations, especially those that introduce a test for an
unlikely case at the start of a method and thus slow everything down.
As a result of this change, GNUstep now depends on an implementation of
POSIX threads. This is included as standard on all modern UNIX systems,
and as an option on less-modern UNIX systems and non-UNIX systems,
including Windows. If you are building GNUstep on Windows, please install
the pthreads-win32 package, available from:
http://sourceware.org/pthreads-win32/
PLEASE TEST THIS! There may be some code that depended on the old
behaviour. I have been running the new NSLock implementation on FreeBSD
for a few weeks without issue; please report to me any problems that you
have on your platform.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@28598 72102866-910b-0410-8b05-ffd578937521
2009-09-02 13:03:13 +00:00
inline NSThread *
GSCurrentThread ( void )
{
2011-07-11 14:31:36 +00:00
NSThread * thr = pthread_getspecific ( thread_object _key ) ;
if ( nil = = thr )
2009-09-08 20:32:52 +00:00
{
2011-07-11 15:12:47 +00:00
assert ( GSRegisterCurrentThread ( ) && @ "Failed to register thread" ) ;
thr = pthread_getspecific ( thread_object _key ) ;
2011-07-12 11:40:15 +00:00
if ( ( nil = = defaultThread ) && IS_MAIN _PTHREAD )
2011-07-11 14:31:36 +00:00
{
2011-07-11 15:12:47 +00:00
defaultThread = [ thr retain ] ;
2011-07-11 14:31:36 +00:00
}
2009-09-08 20:32:52 +00:00
}
2011-07-11 15:12:47 +00:00
assert ( nil ! = thr && @ "No main thread" ) ;
2011-07-11 14:31:36 +00:00
return thr ;
* Source/NSLock.m
* Headers/Foundation/NSLock.h
Completely rewritten implementations of NSLock.h classes. These are now
faster, more complete, OS X-compatible, and most importantly actually
work. The old ones, for example, called functions that were not
implemented on Windows.
* Source/NSThread.m
Call pthread functions directly in NSThread instead of via the libobjc
abstraction layer. Also fixed a few issues, such as GC not being
initialized properly for NSThread subclasses that override -main (Javaism
supported by OS X) and tidies up the code in several places, removing
premature optimizations, especially those that introduce a test for an
unlikely case at the start of a method and thus slow everything down.
As a result of this change, GNUstep now depends on an implementation of
POSIX threads. This is included as standard on all modern UNIX systems,
and as an option on less-modern UNIX systems and non-UNIX systems,
including Windows. If you are building GNUstep on Windows, please install
the pthreads-win32 package, available from:
http://sourceware.org/pthreads-win32/
PLEASE TEST THIS! There may be some code that depended on the old
behaviour. I have been running the new NSLock implementation on FreeBSD
for a few weeks without issue; please report to me any problems that you
have on your platform.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@28598 72102866-910b-0410-8b05-ffd578937521
2009-09-02 13:03:13 +00:00
}
2009-09-08 20:32:52 +00:00
1999-04-19 14:29:52 +00:00
NSMutableDictionary *
2002-10-30 07:45:59 +00:00
GSDictionaryForThread ( NSThread * t )
1999-04-19 14:29:52 +00:00
{
2009-09-08 20:32:52 +00:00
if ( nil = = t )
{
t = GSCurrentThread ( ) ;
}
return [ t threadDictionary ] ;
1999-04-19 14:29:52 +00:00
}
2002-10-30 07:45:59 +00:00
/ * *
* Fast access function for thread dictionary of current thread .
* /
NSMutableDictionary *
2003-12-23 17:41:38 +00:00
GSCurrentThreadDictionary ( void )
2002-10-30 07:45:59 +00:00
{
return GSDictionaryForThread ( nil ) ;
}
2000-04-19 12:29:17 +00:00
/ *
* Callback function so send notifications on becoming multi - threaded .
* /
static void
2003-12-23 17:41:38 +00:00
gnustep_base _thread _callback ( void )
1998-05-29 15:25:41 +00:00
{
1999-06-22 15:06:21 +00:00
/ *
2003-09-30 18:19:03 +00:00
* Protect this function with locking . . . to avoid any possibility
* of multiple threads registering with the system simultaneously ,
* and so that all NSWillBecomeMultiThreadedNotifications are sent
* out before any second thread can interfere with anything .
1999-06-22 15:06:21 +00:00
* /
2000-04-19 12:29:17 +00:00
if ( entered_multi _threaded _state = = NO )
1998-05-29 15:25:41 +00:00
{
2003-09-30 18:19:03 +00:00
[ gnustep_global _lock lock ] ;
if ( entered_multi _threaded _state = = NO )
2002-08-07 13:29:31 +00:00
{
2004-03-12 16:51:30 +00:00
/ *
* For apple compatibility . . . and to make things easier for
* code called indirectly within a will - become - multi - threaded
* notification handler , we set the flag to say we are multi
* threaded BEFORE sending the notifications .
* /
entered_multi _threaded _state = YES ;
2009-02-10 12:16:40 +00:00
# if GS_WITH _GC && defined ( HAVE_GC _ALLOW _REGISTER _THREADS )
/ * This function needs to be called before going multi - threaded
* so that the garbage collection library knows to support
* registration of new threads .
* /
GS_allow _register _threads ( ) ;
# endif
2003-09-30 18:19:03 +00:00
NS_DURING
{
[ GSPerformHolder class ] ; // Force initialization
/ *
* Post a notification if this is the first new thread
* to be created .
* Won ' t work properly if threads are not all created
* by this class , but it ' s better than nothing .
* /
if ( nc = = nil )
{
2004-11-10 11:45:08 +00:00
nc = RETAIN ( [ NSNotificationCenter defaultCenter ] ) ;
2003-09-30 18:19:03 +00:00
}
2011-03-05 13:11:47 +00:00
# if ! defined ( HAVE_INITIALIZE )
2011-03-16 12:17:02 +00:00
if ( NO = = [ [ NSUserDefaults standardUserDefaults ]
boolForKey : @ "GSSilenceInitializeWarning" ] )
{
NSLog ( @ "WARNING your program is becoming multi-threaded, but you are using an ObjectiveC runtime library which does not have a thread-safe implementation of the +initialize method. This means that any classes not already used may be incorrectly initialised, potentially causing strange behaviors and crashes.\nTo put this into context, the runtime bug has been knoown for several years and only rarely causes problems ... the easy workaround being to ensure that any classes used by a new thread have already been used in the main thread before the new thread starts.\nIf you are worried, please build/run GNUstep with a runtime which supports the +initialize method. The GNUstep stable runtime (libobjc) and experimental runtime (libobjc2), available from the GNUstep website and subversion repository, should both work.\nTo disable this warning (eg. for an application which does not suffer any problems caused by this runtime bug), please set the GSSilenceInitializeWarning user default to YES." ) ;
}
2011-03-05 13:11:47 +00:00
# endif
2003-09-30 18:19:03 +00:00
[ nc postNotificationName : NSWillBecomeMultiThreadedNotification
object : nil
userInfo : nil ] ;
}
NS_HANDLER
{
2003-09-30 18:57:49 +00:00
fprintf ( stderr ,
2003-12-23 17:41:38 +00:00
"ALERT ... exception while becoming multi-threaded ... system may not be\n"
"properly initialised.\n" ) ;
2003-09-30 18:57:49 +00:00
fflush ( stderr ) ;
2003-09-30 18:19:03 +00:00
}
NS_ENDHANDLER
2002-08-07 13:29:31 +00:00
}
2003-09-30 18:19:03 +00:00
[ gnustep_global _lock unlock ] ;
1998-05-29 15:25:41 +00:00
}
}
1996-07-15 18:41:44 +00:00
(NSBecomingMultiThreaded, NSThreadExiting): Initialize the
notification strings as static strings, not in +initialize.
(thread_id_2_nsthread): Renamed from THREAD_LIST. Keep the collection
of NSThread's as a maptable, not a NSArray that takes linear time to
search!
(thread_lock): Renamed from THREAD_LIST_LOCK.
(entered_multi_threaded_state): Renamed from ENTERED_MULTI-THREADED_STATE.
([NSThread +initialize]): Don't initialize notification strings here.
Don't autorelease the lock!
([NSThread -init]): Initialize _thread_autorelease_pool. Set our
thread data to self, for easy, efficient access to this NSThread
object later. Put ourselves in the thread collection here, not in
+detach...
([NSThread +currentThread]): This will be called often and needs to be
fast. Reimplemented so we don't have to acquire a lock and step
through an NSArray of threads; instead, just look ourselves up with
the objc_thread_get_data(), and furthermore, no lock required.
([NSThread +detachNewThreadSelector:toTarget:withObject:]): Avoid race
condition, don't create new NSThread object here.
([NSThread +sleepUntilDate:]): Call -notImplemented:.
([NSThread +exit]): Properly post NSThreadExiting notification, making
sure not to hold the lock while we do so. Get the NSThread object
efficiently.
([NSThread -threadId]): Removed unnecessary private method.
([NSThread -setThreadId]): Likewise.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@1530 72102866-910b-0410-8b05-ffd578937521
1996-05-13 15:53:36 +00:00
@ implementation NSThread
1996-02-13 15:40:05 +00:00
2010-04-16 18:18:43 +00:00
static void
setThreadForCurrentThread ( NSThread * t )
* Source/NSLock.m
* Headers/Foundation/NSLock.h
Completely rewritten implementations of NSLock.h classes. These are now
faster, more complete, OS X-compatible, and most importantly actually
work. The old ones, for example, called functions that were not
implemented on Windows.
* Source/NSThread.m
Call pthread functions directly in NSThread instead of via the libobjc
abstraction layer. Also fixed a few issues, such as GC not being
initialized properly for NSThread subclasses that override -main (Javaism
supported by OS X) and tidies up the code in several places, removing
premature optimizations, especially those that introduce a test for an
unlikely case at the start of a method and thus slow everything down.
As a result of this change, GNUstep now depends on an implementation of
POSIX threads. This is included as standard on all modern UNIX systems,
and as an option on less-modern UNIX systems and non-UNIX systems,
including Windows. If you are building GNUstep on Windows, please install
the pthreads-win32 package, available from:
http://sourceware.org/pthreads-win32/
PLEASE TEST THIS! There may be some code that depended on the old
behaviour. I have been running the new NSLock implementation on FreeBSD
for a few weeks without issue; please report to me any problems that you
have on your platform.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@28598 72102866-910b-0410-8b05-ffd578937521
2009-09-02 13:03:13 +00:00
{
2011-05-26 13:24:13 +00:00
[ [ NSGarbageCollector defaultCollector ] disableCollectorForPointer : t ] ;
* Source/NSLock.m
* Headers/Foundation/NSLock.h
Completely rewritten implementations of NSLock.h classes. These are now
faster, more complete, OS X-compatible, and most importantly actually
work. The old ones, for example, called functions that were not
implemented on Windows.
* Source/NSThread.m
Call pthread functions directly in NSThread instead of via the libobjc
abstraction layer. Also fixed a few issues, such as GC not being
initialized properly for NSThread subclasses that override -main (Javaism
supported by OS X) and tidies up the code in several places, removing
premature optimizations, especially those that introduce a test for an
unlikely case at the start of a method and thus slow everything down.
As a result of this change, GNUstep now depends on an implementation of
POSIX threads. This is included as standard on all modern UNIX systems,
and as an option on less-modern UNIX systems and non-UNIX systems,
including Windows. If you are building GNUstep on Windows, please install
the pthreads-win32 package, available from:
http://sourceware.org/pthreads-win32/
PLEASE TEST THIS! There may be some code that depended on the old
behaviour. I have been running the new NSLock implementation on FreeBSD
for a few weeks without issue; please report to me any problems that you
have on your platform.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@28598 72102866-910b-0410-8b05-ffd578937521
2009-09-02 13:03:13 +00:00
pthread_setspecific ( thread_object _key , t ) ;
gnustep_base _thread _callback ( ) ;
}
2010-04-16 18:18:43 +00:00
static void
unregisterActiveThread ( NSThread * thread )
{
if ( thread -> _active = = YES )
{
/ *
* Set the thread to be inactive to avoid any possibility of recursion .
* /
thread -> _active = NO ;
thread -> _finished = YES ;
/ *
* Let observers know this thread is exiting .
* /
if ( nc = = nil )
{
nc = RETAIN ( [ NSNotificationCenter defaultCenter ] ) ;
}
[ nc postNotificationName : NSThreadWillExitNotification
object : thread
userInfo : nil ] ;
[ ( GSRunLoopThreadInfo * ) thread -> _runLoopInfo invalidate ] ;
[ thread release ] ;
2011-05-26 13:24:13 +00:00
[ [ NSGarbageCollector defaultCollector ] enableCollectorForPointer : thread ] ;
2010-04-16 18:18:43 +00:00
pthread_setspecific ( thread_object _key , nil ) ;
}
}
2007-11-25 14:25:26 +00:00
+ ( NSArray * ) callStackReturnAddresses
{
2007-12-03 14:13:57 +00:00
NSMutableArray * stack = GSPrivateStackAddresses ( ) ;
return stack ;
2007-11-25 14:25:26 +00:00
}
2009-09-08 20:32:52 +00:00
+ ( BOOL ) _createThreadForCurrentPthread
(NSBecomingMultiThreaded, NSThreadExiting): Initialize the
notification strings as static strings, not in +initialize.
(thread_id_2_nsthread): Renamed from THREAD_LIST. Keep the collection
of NSThread's as a maptable, not a NSArray that takes linear time to
search!
(thread_lock): Renamed from THREAD_LIST_LOCK.
(entered_multi_threaded_state): Renamed from ENTERED_MULTI-THREADED_STATE.
([NSThread +initialize]): Don't initialize notification strings here.
Don't autorelease the lock!
([NSThread -init]): Initialize _thread_autorelease_pool. Set our
thread data to self, for easy, efficient access to this NSThread
object later. Put ourselves in the thread collection here, not in
+detach...
([NSThread +currentThread]): This will be called often and needs to be
fast. Reimplemented so we don't have to acquire a lock and step
through an NSArray of threads; instead, just look ourselves up with
the objc_thread_get_data(), and furthermore, no lock required.
([NSThread +detachNewThreadSelector:toTarget:withObject:]): Avoid race
condition, don't create new NSThread object here.
([NSThread +sleepUntilDate:]): Call -notImplemented:.
([NSThread +exit]): Properly post NSThreadExiting notification, making
sure not to hold the lock while we do so. Get the NSThread object
efficiently.
([NSThread -threadId]): Removed unnecessary private method.
([NSThread -setThreadId]): Likewise.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@1530 72102866-910b-0410-8b05-ffd578937521
1996-05-13 15:53:36 +00:00
{
* Source/NSLock.m
* Headers/Foundation/NSLock.h
Completely rewritten implementations of NSLock.h classes. These are now
faster, more complete, OS X-compatible, and most importantly actually
work. The old ones, for example, called functions that were not
implemented on Windows.
* Source/NSThread.m
Call pthread functions directly in NSThread instead of via the libobjc
abstraction layer. Also fixed a few issues, such as GC not being
initialized properly for NSThread subclasses that override -main (Javaism
supported by OS X) and tidies up the code in several places, removing
premature optimizations, especially those that introduce a test for an
unlikely case at the start of a method and thus slow everything down.
As a result of this change, GNUstep now depends on an implementation of
POSIX threads. This is included as standard on all modern UNIX systems,
and as an option on less-modern UNIX systems and non-UNIX systems,
including Windows. If you are building GNUstep on Windows, please install
the pthreads-win32 package, available from:
http://sourceware.org/pthreads-win32/
PLEASE TEST THIS! There may be some code that depended on the old
behaviour. I have been running the new NSLock implementation on FreeBSD
for a few weeks without issue; please report to me any problems that you
have on your platform.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@28598 72102866-910b-0410-8b05-ffd578937521
2009-09-02 13:03:13 +00:00
NSThread * t = pthread_getspecific ( thread_object _key ) ;
2009-09-08 20:32:52 +00:00
2003-07-25 09:27:44 +00:00
if ( t = = nil )
2000-08-07 22:00:31 +00:00
{
2011-02-11 19:08:32 +00:00
t = [ self new ] ;
t -> _active = YES ;
2011-05-26 13:24:13 +00:00
[ [ NSGarbageCollector defaultCollector ] disableCollectorForPointer : t ] ;
2011-02-11 19:08:32 +00:00
pthread_setspecific ( thread_object _key , t ) ;
2011-02-12 09:00:18 +00:00
GS_CONSUMED ( t ) ;
2011-02-11 19:08:32 +00:00
return YES ;
2000-08-07 22:00:31 +00:00
}
* Source/NSLock.m
* Headers/Foundation/NSLock.h
Completely rewritten implementations of NSLock.h classes. These are now
faster, more complete, OS X-compatible, and most importantly actually
work. The old ones, for example, called functions that were not
implemented on Windows.
* Source/NSThread.m
Call pthread functions directly in NSThread instead of via the libobjc
abstraction layer. Also fixed a few issues, such as GC not being
initialized properly for NSThread subclasses that override -main (Javaism
supported by OS X) and tidies up the code in several places, removing
premature optimizations, especially those that introduce a test for an
unlikely case at the start of a method and thus slow everything down.
As a result of this change, GNUstep now depends on an implementation of
POSIX threads. This is included as standard on all modern UNIX systems,
and as an option on less-modern UNIX systems and non-UNIX systems,
including Windows. If you are building GNUstep on Windows, please install
the pthreads-win32 package, available from:
http://sourceware.org/pthreads-win32/
PLEASE TEST THIS! There may be some code that depended on the old
behaviour. I have been running the new NSLock implementation on FreeBSD
for a few weeks without issue; please report to me any problems that you
have on your platform.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@28598 72102866-910b-0410-8b05-ffd578937521
2009-09-02 13:03:13 +00:00
return NO ;
}
+ ( NSThread * ) currentThread
{
2011-07-11 14:31:36 +00:00
return GSCurrentThread ( ) ;
(NSBecomingMultiThreaded, NSThreadExiting): Initialize the
notification strings as static strings, not in +initialize.
(thread_id_2_nsthread): Renamed from THREAD_LIST. Keep the collection
of NSThread's as a maptable, not a NSArray that takes linear time to
search!
(thread_lock): Renamed from THREAD_LIST_LOCK.
(entered_multi_threaded_state): Renamed from ENTERED_MULTI-THREADED_STATE.
([NSThread +initialize]): Don't initialize notification strings here.
Don't autorelease the lock!
([NSThread -init]): Initialize _thread_autorelease_pool. Set our
thread data to self, for easy, efficient access to this NSThread
object later. Put ourselves in the thread collection here, not in
+detach...
([NSThread +currentThread]): This will be called often and needs to be
fast. Reimplemented so we don't have to acquire a lock and step
through an NSArray of threads; instead, just look ourselves up with
the objc_thread_get_data(), and furthermore, no lock required.
([NSThread +detachNewThreadSelector:toTarget:withObject:]): Avoid race
condition, don't create new NSThread object here.
([NSThread +sleepUntilDate:]): Call -notImplemented:.
([NSThread +exit]): Properly post NSThreadExiting notification, making
sure not to hold the lock while we do so. Get the NSThread object
efficiently.
([NSThread -threadId]): Removed unnecessary private method.
([NSThread -setThreadId]): Likewise.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@1530 72102866-910b-0410-8b05-ffd578937521
1996-05-13 15:53:36 +00:00
}
1996-03-19 01:45:25 +00:00
1999-05-10 06:45:36 +00:00
+ ( void ) detachNewThreadSelector : ( SEL ) aSelector
toTarget : ( id ) aTarget
withObject : ( id ) anArgument
(NSBecomingMultiThreaded, NSThreadExiting): Initialize the
notification strings as static strings, not in +initialize.
(thread_id_2_nsthread): Renamed from THREAD_LIST. Keep the collection
of NSThread's as a maptable, not a NSArray that takes linear time to
search!
(thread_lock): Renamed from THREAD_LIST_LOCK.
(entered_multi_threaded_state): Renamed from ENTERED_MULTI-THREADED_STATE.
([NSThread +initialize]): Don't initialize notification strings here.
Don't autorelease the lock!
([NSThread -init]): Initialize _thread_autorelease_pool. Set our
thread data to self, for easy, efficient access to this NSThread
object later. Put ourselves in the thread collection here, not in
+detach...
([NSThread +currentThread]): This will be called often and needs to be
fast. Reimplemented so we don't have to acquire a lock and step
through an NSArray of threads; instead, just look ourselves up with
the objc_thread_get_data(), and furthermore, no lock required.
([NSThread +detachNewThreadSelector:toTarget:withObject:]): Avoid race
condition, don't create new NSThread object here.
([NSThread +sleepUntilDate:]): Call -notImplemented:.
([NSThread +exit]): Properly post NSThreadExiting notification, making
sure not to hold the lock while we do so. Get the NSThread object
efficiently.
([NSThread -threadId]): Removed unnecessary private method.
([NSThread -setThreadId]): Likewise.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@1530 72102866-910b-0410-8b05-ffd578937521
1996-05-13 15:53:36 +00:00
{
2000-04-19 12:29:17 +00:00
NSThread * thread ;
1999-06-22 15:06:21 +00:00
/ *
2000-04-19 12:29:17 +00:00
* Create the new thread .
1999-06-22 15:06:21 +00:00
* /
* Source/NSLock.m
* Headers/Foundation/NSLock.h
Completely rewritten implementations of NSLock.h classes. These are now
faster, more complete, OS X-compatible, and most importantly actually
work. The old ones, for example, called functions that were not
implemented on Windows.
* Source/NSThread.m
Call pthread functions directly in NSThread instead of via the libobjc
abstraction layer. Also fixed a few issues, such as GC not being
initialized properly for NSThread subclasses that override -main (Javaism
supported by OS X) and tidies up the code in several places, removing
premature optimizations, especially those that introduce a test for an
unlikely case at the start of a method and thus slow everything down.
As a result of this change, GNUstep now depends on an implementation of
POSIX threads. This is included as standard on all modern UNIX systems,
and as an option on less-modern UNIX systems and non-UNIX systems,
including Windows. If you are building GNUstep on Windows, please install
the pthreads-win32 package, available from:
http://sourceware.org/pthreads-win32/
PLEASE TEST THIS! There may be some code that depended on the old
behaviour. I have been running the new NSLock implementation on FreeBSD
for a few weeks without issue; please report to me any problems that you
have on your platform.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@28598 72102866-910b-0410-8b05-ffd578937521
2009-09-02 13:03:13 +00:00
thread = [ [ NSThread alloc ] initWithTarget : aTarget
selector : aSelector
object : anArgument ] ;
1999-07-14 16:28:43 +00:00
2007-12-24 17:31:52 +00:00
[ thread start ] ;
RELEASE ( thread ) ;
2000-04-19 12:29:17 +00:00
}
+ ( void ) exit
{
2009-09-08 20:32:52 +00:00
NSThread * t ;
2000-04-19 12:29:17 +00:00
t = GSCurrentThread ( ) ;
if ( t -> _active = = YES )
{
2010-04-16 18:18:43 +00:00
unregisterActiveThread ( t ) ;
2000-04-19 12:29:17 +00:00
2010-02-02 14:25:58 +00:00
if ( t = = defaultThread || defaultThread = = nil )
{
/ * For the default thread , we exit the process .
* /
exit ( 0 ) ;
}
else
{
pthread_exit ( NULL ) ;
}
2000-04-19 12:29:17 +00:00
}
1996-02-13 15:40:05 +00:00
}
2000-04-19 12:29:17 +00:00
/ *
* Class initialization
* /
+ ( void ) initialize
{
if ( self = = [ NSThread class ] )
{
2009-09-08 20:32:52 +00:00
if ( pthread_key _create ( & thread_object _key , exitedThread ) )
{
[ NSException raise : NSInternalInconsistencyException
format : @ "Unable to create thread key!" ] ;
}
2000-04-19 12:29:17 +00:00
/ *
* Ensure that the default thread exists .
* /
2001-03-19 12:20:21 +00:00
threadClass = self ;
2010-02-25 18:49:31 +00:00
2011-07-11 14:31:36 +00:00
GSCurrentThread ( ) ;
2000-04-19 12:29:17 +00:00
}
}
(NSBecomingMultiThreaded, NSThreadExiting): Initialize the
notification strings as static strings, not in +initialize.
(thread_id_2_nsthread): Renamed from THREAD_LIST. Keep the collection
of NSThread's as a maptable, not a NSArray that takes linear time to
search!
(thread_lock): Renamed from THREAD_LIST_LOCK.
(entered_multi_threaded_state): Renamed from ENTERED_MULTI-THREADED_STATE.
([NSThread +initialize]): Don't initialize notification strings here.
Don't autorelease the lock!
([NSThread -init]): Initialize _thread_autorelease_pool. Set our
thread data to self, for easy, efficient access to this NSThread
object later. Put ourselves in the thread collection here, not in
+detach...
([NSThread +currentThread]): This will be called often and needs to be
fast. Reimplemented so we don't have to acquire a lock and step
through an NSArray of threads; instead, just look ourselves up with
the objc_thread_get_data(), and furthermore, no lock required.
([NSThread +detachNewThreadSelector:toTarget:withObject:]): Avoid race
condition, don't create new NSThread object here.
([NSThread +sleepUntilDate:]): Call -notImplemented:.
([NSThread +exit]): Properly post NSThreadExiting notification, making
sure not to hold the lock while we do so. Get the NSThread object
efficiently.
([NSThread -threadId]): Removed unnecessary private method.
([NSThread -setThreadId]): Likewise.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@1530 72102866-910b-0410-8b05-ffd578937521
1996-05-13 15:53:36 +00:00
2008-03-18 05:45:05 +00:00
+ ( BOOL ) isMainThread
{
return ( GSCurrentThread ( ) = = defaultThread ? YES : NO ) ;
}
(NSBecomingMultiThreaded, NSThreadExiting): Initialize the
notification strings as static strings, not in +initialize.
(thread_id_2_nsthread): Renamed from THREAD_LIST. Keep the collection
of NSThread's as a maptable, not a NSArray that takes linear time to
search!
(thread_lock): Renamed from THREAD_LIST_LOCK.
(entered_multi_threaded_state): Renamed from ENTERED_MULTI-THREADED_STATE.
([NSThread +initialize]): Don't initialize notification strings here.
Don't autorelease the lock!
([NSThread -init]): Initialize _thread_autorelease_pool. Set our
thread data to self, for easy, efficient access to this NSThread
object later. Put ourselves in the thread collection here, not in
+detach...
([NSThread +currentThread]): This will be called often and needs to be
fast. Reimplemented so we don't have to acquire a lock and step
through an NSArray of threads; instead, just look ourselves up with
the objc_thread_get_data(), and furthermore, no lock required.
([NSThread +detachNewThreadSelector:toTarget:withObject:]): Avoid race
condition, don't create new NSThread object here.
([NSThread +sleepUntilDate:]): Call -notImplemented:.
([NSThread +exit]): Properly post NSThreadExiting notification, making
sure not to hold the lock while we do so. Get the NSThread object
efficiently.
([NSThread -threadId]): Removed unnecessary private method.
([NSThread -setThreadId]): Likewise.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@1530 72102866-910b-0410-8b05-ffd578937521
1996-05-13 15:53:36 +00:00
+ ( BOOL ) isMultiThreaded
1996-02-13 15:40:05 +00:00
{
(NSBecomingMultiThreaded, NSThreadExiting): Initialize the
notification strings as static strings, not in +initialize.
(thread_id_2_nsthread): Renamed from THREAD_LIST. Keep the collection
of NSThread's as a maptable, not a NSArray that takes linear time to
search!
(thread_lock): Renamed from THREAD_LIST_LOCK.
(entered_multi_threaded_state): Renamed from ENTERED_MULTI-THREADED_STATE.
([NSThread +initialize]): Don't initialize notification strings here.
Don't autorelease the lock!
([NSThread -init]): Initialize _thread_autorelease_pool. Set our
thread data to self, for easy, efficient access to this NSThread
object later. Put ourselves in the thread collection here, not in
+detach...
([NSThread +currentThread]): This will be called often and needs to be
fast. Reimplemented so we don't have to acquire a lock and step
through an NSArray of threads; instead, just look ourselves up with
the objc_thread_get_data(), and furthermore, no lock required.
([NSThread +detachNewThreadSelector:toTarget:withObject:]): Avoid race
condition, don't create new NSThread object here.
([NSThread +sleepUntilDate:]): Call -notImplemented:.
([NSThread +exit]): Properly post NSThreadExiting notification, making
sure not to hold the lock while we do so. Get the NSThread object
efficiently.
([NSThread -threadId]): Removed unnecessary private method.
([NSThread -setThreadId]): Likewise.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@1530 72102866-910b-0410-8b05-ffd578937521
1996-05-13 15:53:36 +00:00
return entered_multi _threaded _state ;
1996-02-13 15:40:05 +00:00
}
2007-11-25 14:25:26 +00:00
+ ( NSThread * ) mainThread
{
return defaultThread ;
}
2002-08-27 17:02:05 +00:00
/ * *
* Set the priority of the current thread . This is a value in the
* range 0.0 ( lowest ) to 1.0 ( highest ) which is mapped to the underlying
* Source/NSLock.m
* Headers/Foundation/NSLock.h
Completely rewritten implementations of NSLock.h classes. These are now
faster, more complete, OS X-compatible, and most importantly actually
work. The old ones, for example, called functions that were not
implemented on Windows.
* Source/NSThread.m
Call pthread functions directly in NSThread instead of via the libobjc
abstraction layer. Also fixed a few issues, such as GC not being
initialized properly for NSThread subclasses that override -main (Javaism
supported by OS X) and tidies up the code in several places, removing
premature optimizations, especially those that introduce a test for an
unlikely case at the start of a method and thus slow everything down.
As a result of this change, GNUstep now depends on an implementation of
POSIX threads. This is included as standard on all modern UNIX systems,
and as an option on less-modern UNIX systems and non-UNIX systems,
including Windows. If you are building GNUstep on Windows, please install
the pthreads-win32 package, available from:
http://sourceware.org/pthreads-win32/
PLEASE TEST THIS! There may be some code that depended on the old
behaviour. I have been running the new NSLock implementation on FreeBSD
for a few weeks without issue; please report to me any problems that you
have on your platform.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@28598 72102866-910b-0410-8b05-ffd578937521
2009-09-02 13:03:13 +00:00
* system priorities .
2002-08-27 17:02:05 +00:00
* /
+ ( void ) setThreadPriority : ( double ) pri
{
* Source/NSLock.m
* Headers/Foundation/NSLock.h
Completely rewritten implementations of NSLock.h classes. These are now
faster, more complete, OS X-compatible, and most importantly actually
work. The old ones, for example, called functions that were not
implemented on Windows.
* Source/NSThread.m
Call pthread functions directly in NSThread instead of via the libobjc
abstraction layer. Also fixed a few issues, such as GC not being
initialized properly for NSThread subclasses that override -main (Javaism
supported by OS X) and tidies up the code in several places, removing
premature optimizations, especially those that introduce a test for an
unlikely case at the start of a method and thus slow everything down.
As a result of this change, GNUstep now depends on an implementation of
POSIX threads. This is included as standard on all modern UNIX systems,
and as an option on less-modern UNIX systems and non-UNIX systems,
including Windows. If you are building GNUstep on Windows, please install
the pthreads-win32 package, available from:
http://sourceware.org/pthreads-win32/
PLEASE TEST THIS! There may be some code that depended on the old
behaviour. I have been running the new NSLock implementation on FreeBSD
for a few weeks without issue; please report to me any problems that you
have on your platform.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@28598 72102866-910b-0410-8b05-ffd578937521
2009-09-02 13:03:13 +00:00
# ifdef _POSIX _THREAD _PRIORITY _SCHEDULING
int policy ;
struct sched_param param ;
2002-08-27 17:02:05 +00:00
* Source/NSLock.m
* Headers/Foundation/NSLock.h
Completely rewritten implementations of NSLock.h classes. These are now
faster, more complete, OS X-compatible, and most importantly actually
work. The old ones, for example, called functions that were not
implemented on Windows.
* Source/NSThread.m
Call pthread functions directly in NSThread instead of via the libobjc
abstraction layer. Also fixed a few issues, such as GC not being
initialized properly for NSThread subclasses that override -main (Javaism
supported by OS X) and tidies up the code in several places, removing
premature optimizations, especially those that introduce a test for an
unlikely case at the start of a method and thus slow everything down.
As a result of this change, GNUstep now depends on an implementation of
POSIX threads. This is included as standard on all modern UNIX systems,
and as an option on less-modern UNIX systems and non-UNIX systems,
including Windows. If you are building GNUstep on Windows, please install
the pthreads-win32 package, available from:
http://sourceware.org/pthreads-win32/
PLEASE TEST THIS! There may be some code that depended on the old
behaviour. I have been running the new NSLock implementation on FreeBSD
for a few weeks without issue; please report to me any problems that you
have on your platform.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@28598 72102866-910b-0410-8b05-ffd578937521
2009-09-02 13:03:13 +00:00
// Clamp pri into the required range .
if ( pri > 1 ) { pri = 1 ; }
if ( pri < 0 ) { pri = 0 ; }
// Scale pri based on the range of the host system .
pri * = ( PTHREAD_MAX _PRIORITY - PTHREAD_MIN _PRIORITY ) ;
pri + = PTHREAD_MIN _PRIORITY ;
2002-08-27 17:02:05 +00:00
* Source/NSLock.m
* Headers/Foundation/NSLock.h
Completely rewritten implementations of NSLock.h classes. These are now
faster, more complete, OS X-compatible, and most importantly actually
work. The old ones, for example, called functions that were not
implemented on Windows.
* Source/NSThread.m
Call pthread functions directly in NSThread instead of via the libobjc
abstraction layer. Also fixed a few issues, such as GC not being
initialized properly for NSThread subclasses that override -main (Javaism
supported by OS X) and tidies up the code in several places, removing
premature optimizations, especially those that introduce a test for an
unlikely case at the start of a method and thus slow everything down.
As a result of this change, GNUstep now depends on an implementation of
POSIX threads. This is included as standard on all modern UNIX systems,
and as an option on less-modern UNIX systems and non-UNIX systems,
including Windows. If you are building GNUstep on Windows, please install
the pthreads-win32 package, available from:
http://sourceware.org/pthreads-win32/
PLEASE TEST THIS! There may be some code that depended on the old
behaviour. I have been running the new NSLock implementation on FreeBSD
for a few weeks without issue; please report to me any problems that you
have on your platform.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@28598 72102866-910b-0410-8b05-ffd578937521
2009-09-02 13:03:13 +00:00
pthread_getschedparam ( pthread_self ( ) , & policy , & param ) ;
param . sched_priority = pri ;
pthread_setschedparam ( pthread_self ( ) , policy , & param ) ;
# endif
2002-08-27 17:02:05 +00:00
}
2007-11-25 14:25:26 +00:00
+ ( void ) sleepForTimeInterval : ( NSTimeInterval ) ti
{
2010-12-27 07:03:50 +00:00
GSSleepUntilIntervalSinceReferenceDate ( GSPrivateTimeNow ( ) + ti ) ;
2007-11-25 14:25:26 +00:00
}
2002-08-27 17:02:05 +00:00
/ * *
* Delaying a thread . . . pause until the specified date .
1997-09-01 21:59:51 +00:00
* /
(NSBecomingMultiThreaded, NSThreadExiting): Initialize the
notification strings as static strings, not in +initialize.
(thread_id_2_nsthread): Renamed from THREAD_LIST. Keep the collection
of NSThread's as a maptable, not a NSArray that takes linear time to
search!
(thread_lock): Renamed from THREAD_LIST_LOCK.
(entered_multi_threaded_state): Renamed from ENTERED_MULTI-THREADED_STATE.
([NSThread +initialize]): Don't initialize notification strings here.
Don't autorelease the lock!
([NSThread -init]): Initialize _thread_autorelease_pool. Set our
thread data to self, for easy, efficient access to this NSThread
object later. Put ourselves in the thread collection here, not in
+detach...
([NSThread +currentThread]): This will be called often and needs to be
fast. Reimplemented so we don't have to acquire a lock and step
through an NSArray of threads; instead, just look ourselves up with
the objc_thread_get_data(), and furthermore, no lock required.
([NSThread +detachNewThreadSelector:toTarget:withObject:]): Avoid race
condition, don't create new NSThread object here.
([NSThread +sleepUntilDate:]): Call -notImplemented:.
([NSThread +exit]): Properly post NSThreadExiting notification, making
sure not to hold the lock while we do so. Get the NSThread object
efficiently.
([NSThread -threadId]): Removed unnecessary private method.
([NSThread -setThreadId]): Likewise.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@1530 72102866-910b-0410-8b05-ffd578937521
1996-05-13 15:53:36 +00:00
+ ( void ) sleepUntilDate : ( NSDate * ) date
1996-02-13 15:40:05 +00:00
{
2003-07-20 06:37:25 +00:00
GSSleepUntilIntervalSinceReferenceDate ( [ date timeIntervalSinceReferenceDate ] ) ;
1996-02-13 15:40:05 +00:00
}
2003-07-20 06:37:25 +00:00
2002-08-27 17:02:05 +00:00
/ * *
* Return the priority of the current thread .
* /
+ ( double ) threadPriority
{
* Source/NSLock.m
* Headers/Foundation/NSLock.h
Completely rewritten implementations of NSLock.h classes. These are now
faster, more complete, OS X-compatible, and most importantly actually
work. The old ones, for example, called functions that were not
implemented on Windows.
* Source/NSThread.m
Call pthread functions directly in NSThread instead of via the libobjc
abstraction layer. Also fixed a few issues, such as GC not being
initialized properly for NSThread subclasses that override -main (Javaism
supported by OS X) and tidies up the code in several places, removing
premature optimizations, especially those that introduce a test for an
unlikely case at the start of a method and thus slow everything down.
As a result of this change, GNUstep now depends on an implementation of
POSIX threads. This is included as standard on all modern UNIX systems,
and as an option on less-modern UNIX systems and non-UNIX systems,
including Windows. If you are building GNUstep on Windows, please install
the pthreads-win32 package, available from:
http://sourceware.org/pthreads-win32/
PLEASE TEST THIS! There may be some code that depended on the old
behaviour. I have been running the new NSLock implementation on FreeBSD
for a few weeks without issue; please report to me any problems that you
have on your platform.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@28598 72102866-910b-0410-8b05-ffd578937521
2009-09-02 13:03:13 +00:00
double pri = 0 ;
# ifdef _POSIX _THREAD _PRIORITY _SCHEDULING
int policy ;
struct sched_param param ;
pthread_getschedparam ( pthread_self ( ) , & policy , & param ) ;
pri = param . sched_priority ;
// Scale pri based on the range of the host system .
pri - = PTHREAD_MIN _PRIORITY ;
pri / = ( PTHREAD_MAX _PRIORITY - PTHREAD_MIN _PRIORITY ) ;
# else
# warning Your pthread implementation does not support thread priorities
# endif
return pri ;
2002-08-27 17:02:05 +00:00
}
2000-04-19 12:29:17 +00:00
/ *
* Thread instance methods .
* /
2007-11-25 14:25:26 +00:00
- ( void ) cancel
{
_cancelled = YES ;
}
2000-04-19 12:29:17 +00:00
- ( void ) dealloc
1996-02-13 15:40:05 +00:00
{
2000-04-19 12:29:17 +00:00
if ( _active = = YES )
{
[ NSException raise : NSInternalInconsistencyException
format : @ "Deallocating an active thread without [+exit]!" ] ;
}
2008-03-17 15:23:11 +00:00
if ( _runLoopInfo ! = 0 )
{
GSRunLoopThreadInfo * info = ( GSRunLoopThreadInfo * ) _runLoopInfo ;
_runLoopInfo = 0 ;
[ info release ] ;
}
2000-04-19 12:29:17 +00:00
DESTROY ( _thread _dictionary ) ;
DESTROY ( _target ) ;
DESTROY ( _arg ) ;
2007-11-25 14:25:26 +00:00
DESTROY ( _name ) ;
2006-01-19 06:15:27 +00:00
if ( _autorelease _vars . pool_cache ! = 0 )
{
[ NSAutoreleasePool _endThread : self ] ;
}
2000-11-22 08:41:07 +00:00
2001-03-17 10:18:09 +00:00
if ( _thread _dictionary ! = nil )
{
/ *
* Try again to get rid of thread dictionary .
* /
DESTROY ( _thread _dictionary ) ;
2006-01-19 06:15:27 +00:00
if ( _autorelease _vars . pool_cache ! = 0 )
{
[ NSAutoreleasePool _endThread : self ] ;
}
2001-03-17 10:18:09 +00:00
if ( _thread _dictionary ! = nil )
{
NSLog ( @ "Oops - leak - thread dictionary is %@" , _thread _dictionary ) ;
2006-01-19 06:15:27 +00:00
if ( _autorelease _vars . pool_cache ! = 0 )
{
[ NSAutoreleasePool _endThread : self ] ;
}
2001-03-17 10:18:09 +00:00
}
}
2007-12-25 20:31:24 +00:00
DESTROY ( _gcontext ) ;
2009-10-10 08:16:17 +00:00
[ super dealloc ] ;
2000-04-19 12:29:17 +00:00
}
1996-03-19 01:45:25 +00:00
2000-04-19 12:29:17 +00:00
- ( id ) init
{
2009-09-08 20:32:52 +00:00
init_autorelease _thread _vars ( & _autorelease _vars ) ;
2007-11-25 14:25:26 +00:00
return self ;
2000-04-19 12:29:17 +00:00
}
(NSBecomingMultiThreaded, NSThreadExiting): Initialize the
notification strings as static strings, not in +initialize.
(thread_id_2_nsthread): Renamed from THREAD_LIST. Keep the collection
of NSThread's as a maptable, not a NSArray that takes linear time to
search!
(thread_lock): Renamed from THREAD_LIST_LOCK.
(entered_multi_threaded_state): Renamed from ENTERED_MULTI-THREADED_STATE.
([NSThread +initialize]): Don't initialize notification strings here.
Don't autorelease the lock!
([NSThread -init]): Initialize _thread_autorelease_pool. Set our
thread data to self, for easy, efficient access to this NSThread
object later. Put ourselves in the thread collection here, not in
+detach...
([NSThread +currentThread]): This will be called often and needs to be
fast. Reimplemented so we don't have to acquire a lock and step
through an NSArray of threads; instead, just look ourselves up with
the objc_thread_get_data(), and furthermore, no lock required.
([NSThread +detachNewThreadSelector:toTarget:withObject:]): Avoid race
condition, don't create new NSThread object here.
([NSThread +sleepUntilDate:]): Call -notImplemented:.
([NSThread +exit]): Properly post NSThreadExiting notification, making
sure not to hold the lock while we do so. Get the NSThread object
efficiently.
([NSThread -threadId]): Removed unnecessary private method.
([NSThread -setThreadId]): Likewise.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@1530 72102866-910b-0410-8b05-ffd578937521
1996-05-13 15:53:36 +00:00
2007-11-25 14:25:26 +00:00
- ( id ) initWithTarget : ( id ) aTarget
selector : ( SEL ) aSelector
object : ( id ) anArgument
2000-04-19 12:29:17 +00:00
{
/ * initialize our ivars . * /
2007-11-25 14:25:26 +00:00
_selector = aSelector ;
_target = RETAIN ( aTarget ) ;
_arg = RETAIN ( anArgument ) ;
2000-04-19 12:29:17 +00:00
init_autorelease _thread _vars ( & _autorelease _vars ) ;
return self ;
}
(NSBecomingMultiThreaded, NSThreadExiting): Initialize the
notification strings as static strings, not in +initialize.
(thread_id_2_nsthread): Renamed from THREAD_LIST. Keep the collection
of NSThread's as a maptable, not a NSArray that takes linear time to
search!
(thread_lock): Renamed from THREAD_LIST_LOCK.
(entered_multi_threaded_state): Renamed from ENTERED_MULTI-THREADED_STATE.
([NSThread +initialize]): Don't initialize notification strings here.
Don't autorelease the lock!
([NSThread -init]): Initialize _thread_autorelease_pool. Set our
thread data to self, for easy, efficient access to this NSThread
object later. Put ourselves in the thread collection here, not in
+detach...
([NSThread +currentThread]): This will be called often and needs to be
fast. Reimplemented so we don't have to acquire a lock and step
through an NSArray of threads; instead, just look ourselves up with
the objc_thread_get_data(), and furthermore, no lock required.
([NSThread +detachNewThreadSelector:toTarget:withObject:]): Avoid race
condition, don't create new NSThread object here.
([NSThread +sleepUntilDate:]): Call -notImplemented:.
([NSThread +exit]): Properly post NSThreadExiting notification, making
sure not to hold the lock while we do so. Get the NSThread object
efficiently.
([NSThread -threadId]): Removed unnecessary private method.
([NSThread -setThreadId]): Likewise.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@1530 72102866-910b-0410-8b05-ffd578937521
1996-05-13 15:53:36 +00:00
2007-11-25 14:25:26 +00:00
- ( BOOL ) isCancelled
{
return _cancelled ;
}
- ( BOOL ) isExecuting
{
return _active ;
}
2008-03-18 05:45:05 +00:00
- ( BOOL ) isFinished
{
return _finished ;
}
2007-11-25 14:25:26 +00:00
- ( BOOL ) isMainThread
{
return ( self = = defaultThread ? YES : NO ) ;
}
2007-11-25 14:49:05 +00:00
- ( void ) main
{
2007-12-24 17:31:52 +00:00
if ( _active = = NO )
{
[ NSException raise : NSInternalInconsistencyException
format : @ "[%@-$@] called on inactive thread" ,
NSStringFromClass ( [ self class ] ) ,
NSStringFromSelector ( _cmd ) ] ;
}
* Source/NSLock.m
* Headers/Foundation/NSLock.h
Completely rewritten implementations of NSLock.h classes. These are now
faster, more complete, OS X-compatible, and most importantly actually
work. The old ones, for example, called functions that were not
implemented on Windows.
* Source/NSThread.m
Call pthread functions directly in NSThread instead of via the libobjc
abstraction layer. Also fixed a few issues, such as GC not being
initialized properly for NSThread subclasses that override -main (Javaism
supported by OS X) and tidies up the code in several places, removing
premature optimizations, especially those that introduce a test for an
unlikely case at the start of a method and thus slow everything down.
As a result of this change, GNUstep now depends on an implementation of
POSIX threads. This is included as standard on all modern UNIX systems,
and as an option on less-modern UNIX systems and non-UNIX systems,
including Windows. If you are building GNUstep on Windows, please install
the pthreads-win32 package, available from:
http://sourceware.org/pthreads-win32/
PLEASE TEST THIS! There may be some code that depended on the old
behaviour. I have been running the new NSLock implementation on FreeBSD
for a few weeks without issue; please report to me any problems that you
have on your platform.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@28598 72102866-910b-0410-8b05-ffd578937521
2009-09-02 13:03:13 +00:00
[ _target performSelector : _selector withObject : _arg ] ;
}
- ( NSString * ) name
{
return _name ;
}
- ( void ) setName : ( NSString * ) aName
{
ASSIGN ( _name , aName ) ;
}
- ( void ) setStackSize : ( NSUInteger ) stackSize
{
_stackSize = stackSize ;
}
- ( NSUInteger ) stackSize
{
return _stackSize ;
}
/ * *
* Trampoline function called to launch the thread
* /
static void * nsthreadLauncher ( void * thread )
{
NSThread * t = ( NSThread * ) thread ;
setThreadForCurrentThread ( t ) ;
2011-05-26 13:24:13 +00:00
# if __OBJC _GC __
objc_registerThreadWithCollector ( ) ;
# endif
2009-01-13 15:57:38 +00:00
# if GS_WITH _GC && defined ( HAVE_GC _REGISTER _MY _THREAD )
2009-02-10 12:16:40 +00:00
{
struct GC_stack _base base ;
if ( GC_get _stack _base ( & base ) = = GC_SUCCESS )
{
int result ;
2009-02-10 14:35:12 +00:00
result = GC_register _my _thread ( & base ) ;
2009-02-10 12:16:40 +00:00
if ( result ! = GC_SUCCESS && result ! = GC_DUPLICATE )
{
fprintf ( stderr , "Argh ... no thread support in garbage collection library\n" ) ;
}
}
else
{
fprintf ( stderr , "Unable to determine stack base to register new thread for garbage collection\n" ) ;
}
}
2009-01-13 15:57:38 +00:00
# endif
2009-02-10 12:16:40 +00:00
2007-12-24 17:31:52 +00:00
/ *
* Let observers know a new thread is starting .
* /
if ( nc = = nil )
{
nc = RETAIN ( [ NSNotificationCenter defaultCenter ] ) ;
}
[ nc postNotificationName : NSThreadDidStartNotification
* Source/NSLock.m
* Headers/Foundation/NSLock.h
Completely rewritten implementations of NSLock.h classes. These are now
faster, more complete, OS X-compatible, and most importantly actually
work. The old ones, for example, called functions that were not
implemented on Windows.
* Source/NSThread.m
Call pthread functions directly in NSThread instead of via the libobjc
abstraction layer. Also fixed a few issues, such as GC not being
initialized properly for NSThread subclasses that override -main (Javaism
supported by OS X) and tidies up the code in several places, removing
premature optimizations, especially those that introduce a test for an
unlikely case at the start of a method and thus slow everything down.
As a result of this change, GNUstep now depends on an implementation of
POSIX threads. This is included as standard on all modern UNIX systems,
and as an option on less-modern UNIX systems and non-UNIX systems,
including Windows. If you are building GNUstep on Windows, please install
the pthreads-win32 package, available from:
http://sourceware.org/pthreads-win32/
PLEASE TEST THIS! There may be some code that depended on the old
behaviour. I have been running the new NSLock implementation on FreeBSD
for a few weeks without issue; please report to me any problems that you
have on your platform.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@28598 72102866-910b-0410-8b05-ffd578937521
2009-09-02 13:03:13 +00:00
object : t
2007-12-24 17:31:52 +00:00
userInfo : nil ] ;
* Source/NSLock.m
* Headers/Foundation/NSLock.h
Completely rewritten implementations of NSLock.h classes. These are now
faster, more complete, OS X-compatible, and most importantly actually
work. The old ones, for example, called functions that were not
implemented on Windows.
* Source/NSThread.m
Call pthread functions directly in NSThread instead of via the libobjc
abstraction layer. Also fixed a few issues, such as GC not being
initialized properly for NSThread subclasses that override -main (Javaism
supported by OS X) and tidies up the code in several places, removing
premature optimizations, especially those that introduce a test for an
unlikely case at the start of a method and thus slow everything down.
As a result of this change, GNUstep now depends on an implementation of
POSIX threads. This is included as standard on all modern UNIX systems,
and as an option on less-modern UNIX systems and non-UNIX systems,
including Windows. If you are building GNUstep on Windows, please install
the pthreads-win32 package, available from:
http://sourceware.org/pthreads-win32/
PLEASE TEST THIS! There may be some code that depended on the old
behaviour. I have been running the new NSLock implementation on FreeBSD
for a few weeks without issue; please report to me any problems that you
have on your platform.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@28598 72102866-910b-0410-8b05-ffd578937521
2009-09-02 13:03:13 +00:00
[ t main ] ;
2007-12-24 17:31:52 +00:00
[ NSThread exit ] ;
* Source/NSLock.m
* Headers/Foundation/NSLock.h
Completely rewritten implementations of NSLock.h classes. These are now
faster, more complete, OS X-compatible, and most importantly actually
work. The old ones, for example, called functions that were not
implemented on Windows.
* Source/NSThread.m
Call pthread functions directly in NSThread instead of via the libobjc
abstraction layer. Also fixed a few issues, such as GC not being
initialized properly for NSThread subclasses that override -main (Javaism
supported by OS X) and tidies up the code in several places, removing
premature optimizations, especially those that introduce a test for an
unlikely case at the start of a method and thus slow everything down.
As a result of this change, GNUstep now depends on an implementation of
POSIX threads. This is included as standard on all modern UNIX systems,
and as an option on less-modern UNIX systems and non-UNIX systems,
including Windows. If you are building GNUstep on Windows, please install
the pthreads-win32 package, available from:
http://sourceware.org/pthreads-win32/
PLEASE TEST THIS! There may be some code that depended on the old
behaviour. I have been running the new NSLock implementation on FreeBSD
for a few weeks without issue; please report to me any problems that you
have on your platform.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@28598 72102866-910b-0410-8b05-ffd578937521
2009-09-02 13:03:13 +00:00
// Not reached
return NULL ;
2007-11-25 14:25:26 +00:00
}
- ( void ) start
2000-04-19 12:29:17 +00:00
{
2009-09-27 19:31:31 +00:00
pthread_attr _t attr ;
pthread_t thr ;
2007-12-24 20:51:19 +00:00
if ( _active = = YES )
2002-08-07 13:29:31 +00:00
{
2007-12-24 20:51:19 +00:00
[ NSException raise : NSInternalInconsistencyException
format : @ "[%@-$@] called on active thread" ,
NSStringFromClass ( [ self class ] ) ,
NSStringFromSelector ( _cmd ) ] ;
}
if ( _cancelled = = YES )
{
[ NSException raise : NSInternalInconsistencyException
format : @ "[%@-$@] called on cancelled thread" ,
NSStringFromClass ( [ self class ] ) ,
NSStringFromSelector ( _cmd ) ] ;
}
2008-03-18 05:45:05 +00:00
if ( _finished = = YES )
{
[ NSException raise : NSInternalInconsistencyException
format : @ "[%@-$@] called on finished thread" ,
NSStringFromClass ( [ self class ] ) ,
NSStringFromSelector ( _cmd ) ] ;
}
2000-11-12 07:41:24 +00:00
2007-12-24 20:51:19 +00:00
/ * Make sure the notification is posted BEFORE the new thread starts .
* /
gnustep_base _thread _callback ( ) ;
2007-12-24 17:31:52 +00:00
2007-12-24 20:51:19 +00:00
/ * The thread must persist until it finishes executing .
* /
2011-02-28 19:49:57 +00:00
[ self retain ] ;
2007-12-24 17:31:52 +00:00
2007-12-24 20:51:19 +00:00
/ * Mark the thread as active whiul it ' s running .
* /
_active = YES ;
2008-01-06 08:56:59 +00:00
errno = 0 ;
* Source/NSLock.m
* Headers/Foundation/NSLock.h
Completely rewritten implementations of NSLock.h classes. These are now
faster, more complete, OS X-compatible, and most importantly actually
work. The old ones, for example, called functions that were not
implemented on Windows.
* Source/NSThread.m
Call pthread functions directly in NSThread instead of via the libobjc
abstraction layer. Also fixed a few issues, such as GC not being
initialized properly for NSThread subclasses that override -main (Javaism
supported by OS X) and tidies up the code in several places, removing
premature optimizations, especially those that introduce a test for an
unlikely case at the start of a method and thus slow everything down.
As a result of this change, GNUstep now depends on an implementation of
POSIX threads. This is included as standard on all modern UNIX systems,
and as an option on less-modern UNIX systems and non-UNIX systems,
including Windows. If you are building GNUstep on Windows, please install
the pthreads-win32 package, available from:
http://sourceware.org/pthreads-win32/
PLEASE TEST THIS! There may be some code that depended on the old
behaviour. I have been running the new NSLock implementation on FreeBSD
for a few weeks without issue; please report to me any problems that you
have on your platform.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@28598 72102866-910b-0410-8b05-ffd578937521
2009-09-02 13:03:13 +00:00
pthread_attr _init ( & attr ) ;
2009-09-27 19:31:31 +00:00
/ * Create this thread detached , because we never use the return state from
* threads .
* /
* Source/NSLock.m
* Headers/Foundation/NSLock.h
Completely rewritten implementations of NSLock.h classes. These are now
faster, more complete, OS X-compatible, and most importantly actually
work. The old ones, for example, called functions that were not
implemented on Windows.
* Source/NSThread.m
Call pthread functions directly in NSThread instead of via the libobjc
abstraction layer. Also fixed a few issues, such as GC not being
initialized properly for NSThread subclasses that override -main (Javaism
supported by OS X) and tidies up the code in several places, removing
premature optimizations, especially those that introduce a test for an
unlikely case at the start of a method and thus slow everything down.
As a result of this change, GNUstep now depends on an implementation of
POSIX threads. This is included as standard on all modern UNIX systems,
and as an option on less-modern UNIX systems and non-UNIX systems,
including Windows. If you are building GNUstep on Windows, please install
the pthreads-win32 package, available from:
http://sourceware.org/pthreads-win32/
PLEASE TEST THIS! There may be some code that depended on the old
behaviour. I have been running the new NSLock implementation on FreeBSD
for a few weeks without issue; please report to me any problems that you
have on your platform.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@28598 72102866-910b-0410-8b05-ffd578937521
2009-09-02 13:03:13 +00:00
pthread_attr _setdetachstate ( & attr , PTHREAD_CREATE _DETACHED ) ;
2009-09-27 19:31:31 +00:00
/ * Set the stack size when the thread is created . Unlike the old setrlimit
* code , this actually works .
* /
* Source/NSLock.m
* Headers/Foundation/NSLock.h
Completely rewritten implementations of NSLock.h classes. These are now
faster, more complete, OS X-compatible, and most importantly actually
work. The old ones, for example, called functions that were not
implemented on Windows.
* Source/NSThread.m
Call pthread functions directly in NSThread instead of via the libobjc
abstraction layer. Also fixed a few issues, such as GC not being
initialized properly for NSThread subclasses that override -main (Javaism
supported by OS X) and tidies up the code in several places, removing
premature optimizations, especially those that introduce a test for an
unlikely case at the start of a method and thus slow everything down.
As a result of this change, GNUstep now depends on an implementation of
POSIX threads. This is included as standard on all modern UNIX systems,
and as an option on less-modern UNIX systems and non-UNIX systems,
including Windows. If you are building GNUstep on Windows, please install
the pthreads-win32 package, available from:
http://sourceware.org/pthreads-win32/
PLEASE TEST THIS! There may be some code that depended on the old
behaviour. I have been running the new NSLock implementation on FreeBSD
for a few weeks without issue; please report to me any problems that you
have on your platform.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@28598 72102866-910b-0410-8b05-ffd578937521
2009-09-02 13:03:13 +00:00
if ( _stackSize > 0 )
{
pthread_attr _setstacksize ( & attr , _stackSize ) ;
}
if ( pthread_create ( & thr , & attr , nsthreadLauncher , self ) )
2007-12-24 20:51:19 +00:00
{
2010-02-25 18:49:31 +00:00
DESTROY ( self ) ;
2007-12-24 20:51:19 +00:00
[ NSException raise : NSInternalInconsistencyException
2008-01-06 08:56:59 +00:00
format : @ "Unable to detach thread (last error %@)" ,
2007-12-25 14:13:18 +00:00
[ NSError _last ] ] ;
2007-12-24 17:31:52 +00:00
}
2000-04-19 12:29:17 +00:00
}
1996-03-19 01:45:25 +00:00
2002-08-27 17:02:05 +00:00
/ * *
* Return the thread dictionary . This dictionary can be used to store
* arbitrary thread specific data . < br / >
2000-04-19 12:29:17 +00:00
* NB . This cannot be autoreleased , since we cannot be sure that the
* autorelease pool for the thread will continue to exist for the entire
* life of the thread !
* /
- ( NSMutableDictionary * ) threadDictionary
{
2001-03-17 10:18:09 +00:00
if ( _thread _dictionary = = nil )
2000-04-19 12:29:17 +00:00
{
_thread _dictionary = [ NSMutableDictionary new ] ;
}
return _thread _dictionary ;
1996-02-13 15:40:05 +00:00
}
1996-03-19 01:45:25 +00:00
@ end
2000-04-19 12:29:17 +00:00
2002-10-30 07:45:59 +00:00
2008-03-17 15:23:11 +00:00
@ implementation GSRunLoopThreadInfo
- ( void ) addPerformer : ( id ) performer
2002-11-02 16:53:48 +00:00
{
2008-03-17 15:23:11 +00:00
[ lock lock ] ;
[ performers addObject : performer ] ;
2010-03-19 12:10:11 +00:00
# if defined ( __MINGW __ )
2005-02-23 16:05:09 +00:00
if ( SetEvent ( event ) = = 0 )
{
2006-10-20 10:56:27 +00:00
NSLog ( @ "Set event failed - %@" , [ NSError _last ] ) ;
2005-02-23 16:05:09 +00:00
}
# else
2010-08-30 19:16:30 +00:00
/ * The write could concievably fail if the pipe is full .
* In that case we need to release the lock teporarily to allow the other
* thread to consume data from the pipe . It ' s possible that the thread
* and its runloop might stop during that . . . so we need to check that
* outputFd is still valid .
2010-08-30 17:27:11 +00:00
* /
2010-08-30 19:16:30 +00:00
while ( outputFd >= 0 && write ( outputFd , "0" , 1 ) ! = 1 )
{
[ lock unlock ] ;
[ lock lock ] ;
}
2005-02-23 16:05:09 +00:00
# endif
2008-09-18 08:22:53 +00:00
[ lock unlock ] ;
2008-03-17 15:23:11 +00:00
}
2005-02-23 16:05:09 +00:00
2008-03-17 15:23:11 +00:00
- ( void ) dealloc
{
2008-03-18 05:45:05 +00:00
[ self invalidate ] ;
2011-04-03 19:14:29 +00:00
DESTROY ( performers ) ;
2008-03-17 15:23:11 +00:00
DESTROY ( lock ) ;
DESTROY ( loop ) ;
[ super dealloc ] ;
}
2002-11-02 16:53:48 +00:00
2008-03-17 15:23:11 +00:00
- ( id ) init
{
2010-03-19 12:10:11 +00:00
# ifdef __MINGW __
2008-03-17 15:23:11 +00:00
if ( ( event = CreateEvent ( NULL , TRUE , FALSE , NULL ) ) = = INVALID_HANDLE _VALUE )
{
2010-02-25 18:49:31 +00:00
DESTROY ( self ) ;
2008-03-17 15:23:11 +00:00
[ NSException raise : NSInternalInconsistencyException
format : @ "Failed to create event to handle perform in thread" ] ;
}
# else
int fd [ 2 ] ;
if ( pipe ( fd ) = = 0 )
{
2008-09-18 08:22:53 +00:00
int e ;
2008-03-17 15:23:11 +00:00
inputFd = fd [ 0 ] ;
outputFd = fd [ 1 ] ;
2008-09-18 08:22:53 +00:00
if ( ( e = fcntl ( inputFd , F_GETFL , 0 ) ) >= 0 )
{
e | = NBLK_OPT ;
if ( fcntl ( inputFd , F_SETFL , e ) < 0 )
{
[ NSException raise : NSInternalInconsistencyException
format : @ "Failed to set non block flag for perform in thread" ] ;
}
}
else
{
[ NSException raise : NSInternalInconsistencyException
format : @ "Failed to get non block flag for perform in thread" ] ;
}
2010-08-30 17:27:11 +00:00
if ( ( e = fcntl ( outputFd , F_GETFL , 0 ) ) >= 0 )
{
e | = NBLK_OPT ;
if ( fcntl ( outputFd , F_SETFL , e ) < 0 )
{
[ NSException raise : NSInternalInconsistencyException
format : @ "Failed to set non block flag for perform in thread" ] ;
}
}
else
{
[ NSException raise : NSInternalInconsistencyException
format : @ "Failed to get non block flag for perform in thread" ] ;
}
2008-03-17 15:23:11 +00:00
}
else
{
2010-02-25 18:49:31 +00:00
DESTROY ( self ) ;
2008-03-17 15:23:11 +00:00
[ NSException raise : NSInternalInconsistencyException
format : @ "Failed to create pipe to handle perform in thread" ] ;
}
# endif
lock = [ NSLock new ] ;
performers = [ NSMutableArray new ] ;
return self ;
2002-11-02 16:53:48 +00:00
}
2008-03-18 05:45:05 +00:00
- ( void ) invalidate
{
[ lock lock ] ;
[ performers makeObjectsPerformSelector : @ selector ( invalidate ) ] ;
[ performers removeAllObjects ] ;
2010-03-19 12:10:11 +00:00
# ifdef __MINGW __
2008-03-18 05:55:32 +00:00
if ( event ! = INVALID_HANDLE _VALUE )
{
CloseHandle ( event ) ;
2010-03-08 12:36:37 +00:00
event = INVALID_HANDLE _VALUE ;
2008-03-18 05:55:32 +00:00
}
# else
if ( inputFd >= 0 )
{
close ( inputFd ) ;
inputFd = -1 ;
}
if ( outputFd >= 0 )
{
close ( outputFd ) ;
outputFd = -1 ;
}
# endif
2008-09-18 08:22:53 +00:00
[ lock unlock ] ;
2008-03-18 05:45:05 +00:00
}
2008-03-17 15:23:11 +00:00
- ( void ) fire
2002-11-02 16:53:48 +00:00
{
2005-02-23 16:05:09 +00:00
NSArray * toDo ;
2003-04-06 07:14:50 +00:00
unsigned int i ;
unsigned int c ;
2002-11-03 18:56:46 +00:00
2008-09-18 08:22:53 +00:00
[ lock lock ] ;
2010-03-19 12:10:11 +00:00
# if defined ( __MINGW __ )
2008-03-18 05:55:32 +00:00
if ( event ! = INVALID_HANDLE _VALUE )
2005-02-23 16:05:09 +00:00
{
2008-03-18 05:55:32 +00:00
if ( ResetEvent ( event ) = = 0 )
{
NSLog ( @ "Reset event failed - %@" , [ NSError _last ] ) ;
}
2005-02-23 16:05:09 +00:00
}
# else
2008-03-18 05:55:32 +00:00
if ( inputFd >= 0 )
2005-02-23 16:05:09 +00:00
{
2010-08-30 17:27:11 +00:00
char buf [ BUFSIZ ] ;
/ * We don ' t care how much we read . If there have been multiple
* performers queued then there will be multiple bytes available ,
* but we always handle all available performers , so we can also
* read all available bytes .
* The descriptor is non - blocking . . . so it ' s safe to ask for more
* bytes than are available .
* /
while ( read ( inputFd , buf , sizeof ( buf ) ) > 0 )
;
2005-02-23 16:05:09 +00:00
}
# endif
2011-02-09 10:10:04 +00:00
c = [ performers count ] ;
if ( 0 = = c )
{
/ * We deal with all available performers each time we fire , so
* it ' s likely that we will fire when we have no performers left .
* In that case we can skip the copying and emptying of the array .
* /
[ lock unlock ] ;
return ;
}
2008-03-17 15:23:11 +00:00
toDo = [ NSArray arrayWithArray : performers ] ;
[ performers removeAllObjects ] ;
[ lock unlock ] ;
2005-02-23 16:05:09 +00:00
2003-04-06 07:14:50 +00:00
for ( i = 0 ; i < c ; i + + )
2002-11-02 16:53:48 +00:00
{
2005-02-23 16:05:09 +00:00
GSPerformHolder * h = [ toDo objectAtIndex : i ] ;
2002-11-03 18:56:46 +00:00
[ loop performSelector : @ selector ( fire )
target : h
argument : nil
order : 0
2008-03-17 15:23:11 +00:00
modes : [ h modes ] ] ;
}
}
@ end
GSRunLoopThreadInfo *
GSRunLoopInfoForThread ( NSThread * aThread )
{
GSRunLoopThreadInfo * info ;
if ( aThread = = nil )
{
aThread = GSCurrentThread ( ) ;
2008-09-23 08:10:59 +00:00
}
2010-02-14 10:48:10 +00:00
if ( aThread -> _runLoopInfo = = nil )
2008-09-23 08:10:59 +00:00
{
2009-05-24 04:22:09 +00:00
[ gnustep_global _lock lock ] ;
2010-02-14 10:48:10 +00:00
if ( aThread -> _runLoopInfo = = nil )
2009-05-24 04:22:09 +00:00
{
2010-02-14 10:48:10 +00:00
aThread -> _runLoopInfo = [ GSRunLoopThreadInfo new ] ;
2009-05-24 04:22:09 +00:00
}
[ gnustep_global _lock unlock ] ;
2002-11-02 16:53:48 +00:00
}
2010-02-14 10:48:10 +00:00
info = aThread -> _runLoopInfo ;
2008-03-17 15:23:11 +00:00
return info ;
}
@ implementation GSPerformHolder
+ ( GSPerformHolder * ) newForReceiver : ( id ) r
argument : ( id ) a
selector : ( SEL ) s
modes : ( NSArray * ) m
lock : ( NSConditionLock * ) l
{
GSPerformHolder * h ;
h = ( GSPerformHolder * ) NSAllocateObject ( self , 0 , NSDefaultMallocZone ( ) ) ;
h -> receiver = RETAIN ( r ) ;
h -> argument = RETAIN ( a ) ;
h -> selector = s ;
h -> modes = RETAIN ( m ) ;
h -> lock = l ;
return h ;
2002-11-02 16:53:48 +00:00
}
2002-11-03 18:56:46 +00:00
- ( void ) dealloc
{
DESTROY ( receiver ) ;
DESTROY ( argument ) ;
DESTROY ( modes ) ;
if ( lock ! = nil )
{
[ lock lock ] ;
[ lock unlockWithCondition : 1 ] ;
lock = nil ;
}
NSDeallocateObject ( self ) ;
2006-06-04 06:42:10 +00:00
GSNOSUPERDEALLOC ;
2002-11-03 18:56:46 +00:00
}
- ( void ) fire
{
2008-03-17 15:23:11 +00:00
GSRunLoopThreadInfo * threadInfo ;
2002-11-03 18:56:46 +00:00
if ( receiver = = nil )
{
return ; // Already fired !
}
2008-03-17 15:23:11 +00:00
threadInfo = GSRunLoopInfoForThread ( GSCurrentThread ( ) ) ;
[ threadInfo -> loop cancelPerformSelectorsWithTarget : self ] ;
2002-11-03 18:56:46 +00:00
[ receiver performSelector : selector withObject : argument ] ;
DESTROY ( receiver ) ;
DESTROY ( argument ) ;
DESTROY ( modes ) ;
2008-03-18 05:45:05 +00:00
if ( lock ! = nil )
2002-11-03 18:56:46 +00:00
{
2002-12-08 20:18:34 +00:00
NSConditionLock * l = lock ;
2002-11-03 18:56:46 +00:00
[ lock lock ] ;
lock = nil ;
2002-12-08 20:18:34 +00:00
[ l unlockWithCondition : 1 ] ;
2002-11-03 18:56:46 +00:00
}
}
2008-03-17 15:23:11 +00:00
2008-03-18 05:45:05 +00:00
- ( void ) invalidate
{
if ( invalidated = = NO )
{
invalidated = YES ;
DESTROY ( receiver ) ;
if ( lock ! = nil )
{
NSConditionLock * l = lock ;
[ lock lock ] ;
lock = nil ;
[ l unlockWithCondition : 1 ] ;
}
}
}
- ( BOOL ) isInvalidated
{
return invalidated ;
}
2008-03-17 15:23:11 +00:00
- ( NSArray * ) modes
{
return modes ;
}
2002-11-03 18:56:46 +00:00
@ end
2002-11-02 16:53:48 +00:00
2008-03-17 15:23:11 +00:00
@ implementation NSObject ( NSThreadPerformAdditions )
2002-10-30 07:45:59 +00:00
- ( void ) performSelectorOnMainThread : ( SEL ) aSelector
withObject : ( id ) anObject
waitUntilDone : ( BOOL ) aFlag
2002-11-03 18:56:46 +00:00
modes : ( NSArray * ) anArray
2002-10-30 07:45:59 +00:00
{
2008-09-23 08:10:59 +00:00
/ * 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 .
* /
if ( defaultThread = = nil )
{
[ NSThread currentThread ] ;
}
2008-03-17 15:23:11 +00:00
[ self performSelector : aSelector
onThread : defaultThread
withObject : anObject
waitUntilDone : aFlag
modes : anArray ] ;
}
- ( void ) performSelectorOnMainThread : ( SEL ) aSelector
withObject : ( id ) anObject
waitUntilDone : ( BOOL ) aFlag
{
[ self performSelectorOnMainThread : aSelector
withObject : anObject
waitUntilDone : aFlag
modes : commonModes ( ) ] ;
}
- ( void ) performSelector : ( SEL ) aSelector
onThread : ( NSThread * ) aThread
withObject : ( id ) anObject
waitUntilDone : ( BOOL ) aFlag
modes : ( NSArray * ) anArray
{
GSRunLoopThreadInfo * info ;
NSThread * t ;
2002-10-30 07:45:59 +00:00
2002-11-03 18:56:46 +00:00
if ( [ anArray count ] = = 0 )
{
return ;
}
t = GSCurrentThread ( ) ;
2008-03-17 15:23:11 +00:00
if ( aThread = = nil )
2002-10-30 07:45:59 +00:00
{
2008-03-17 15:23:11 +00:00
aThread = t ;
}
info = GSRunLoopInfoForThread ( aThread ) ;
if ( t = = aThread )
{
2008-03-18 05:45:05 +00:00
/ * Perform in current thread .
* /
2008-03-17 15:23:11 +00:00
if ( aFlag = = YES || info -> loop = = nil )
2002-11-02 16:53:48 +00:00
{
2008-03-18 05:45:05 +00:00
/ * Wait until done or no run loop .
* /
2002-11-02 16:53:48 +00:00
[ self performSelector : aSelector withObject : anObject ] ;
}
else
{
2008-03-18 05:45:05 +00:00
/ * Don ' t wait . . . schedule operation in run loop .
* /
2008-03-17 15:23:11 +00:00
[ info -> loop performSelector : aSelector
target : self
argument : anObject
order : 0
modes : anArray ] ;
2002-11-02 16:53:48 +00:00
}
2002-10-30 07:45:59 +00:00
}
else
{
2008-03-17 15:23:11 +00:00
GSPerformHolder * h ;
2002-11-03 18:56:46 +00:00
NSConditionLock * l = nil ;
2002-10-30 07:45:59 +00:00
2008-03-18 05:45:05 +00:00
if ( [ t isFinished ] = = YES )
{
[ NSException raise : NSInternalInconsistencyException
format : @ "perform on finished thread" ] ;
}
2002-10-30 07:45:59 +00:00
if ( aFlag = = YES )
{
2002-11-02 16:53:48 +00:00
l = [ [ NSConditionLock alloc ] init ] ;
2002-10-30 07:45:59 +00:00
}
2005-02-22 11:22:44 +00:00
2002-10-30 07:45:59 +00:00
h = [ GSPerformHolder newForReceiver : self
2002-11-03 18:56:46 +00:00
argument : anObject
selector : aSelector
modes : anArray
lock : l ] ;
2008-03-17 15:23:11 +00:00
[ info addPerformer : h ] ;
if ( l ! = nil )
2002-10-30 07:45:59 +00:00
{
2002-11-03 18:56:46 +00:00
[ l lockWhenCondition : 1 ] ;
2002-10-30 12:37:21 +00:00
[ l unlock ] ;
RELEASE ( l ) ;
2008-03-18 05:45:05 +00:00
if ( [ h isInvalidated ] = = YES )
{
[ NSException raise : NSInternalInconsistencyException
format : @ "perform on finished thread" ] ;
RELEASE ( h ) ;
}
2002-10-30 07:45:59 +00:00
}
2008-03-17 15:23:11 +00:00
RELEASE ( h ) ;
2002-10-30 07:45:59 +00:00
}
}
2008-03-17 15:23:11 +00:00
- ( void ) performSelector : ( SEL ) aSelector
onThread : ( NSThread * ) aThread
withObject : ( id ) anObject
waitUntilDone : ( BOOL ) aFlag
2002-10-30 07:45:59 +00:00
{
2008-03-17 15:23:11 +00:00
[ self performSelector : aSelector
onThread : aThread
withObject : anObject
waitUntilDone : aFlag
modes : commonModes ( ) ] ;
2002-10-30 07:45:59 +00:00
}
@ end
2002-11-03 19:09:39 +00:00
2002-08-20 10:22:05 +00:00
/ * *
* < p >
* This function is provided to let threads started by some other
* software library register themselves to be used with the
* GNUstep system . All such threads should call this function
* before attempting to use any GNUstep objects .
* < / p >
* < p >
* Returns < code > YES < / code > if the thread can be registered ,
* < code > NO < / code > if it is already registered .
* < / p >
* < p >
* Sends out a < code > NSWillBecomeMultiThreadedNotification < / code >
* if the process was not already multithreaded .
* < / p >
* /
2001-03-19 12:20:21 +00:00
BOOL
GSRegisterCurrentThread ( void )
2000-11-12 07:41:24 +00:00
{
2009-09-08 20:32:52 +00:00
return [ NSThread _createThreadForCurrentPthread ] ;
2000-11-12 07:41:24 +00:00
}
2002-08-20 10:22:05 +00:00
/ * *
* < p >
* This function is provided to let threads started by some other
* software library unregister themselves from the GNUstep threading
2005-02-22 11:22:44 +00:00
* system .
2002-08-20 10:22:05 +00:00
* < / p >
* < p >
* Calling this function causes a
* < code > NSThreadWillExitNotification < / code >
* to be sent out , and destroys the GNUstep NSThread object
2010-04-16 18:18:43 +00:00
* associated with the thread ( like [ NSThread + exit ] ) but does
* not exit the underlying thread .
2002-08-20 10:22:05 +00:00
* < / p >
* /
2001-03-19 12:20:21 +00:00
void
GSUnregisterCurrentThread ( void )
2000-11-12 07:41:24 +00:00
{
2010-04-16 18:18:43 +00:00
unregisterActiveThread ( GSCurrentThread ( ) ) ;
2000-11-12 07:41:24 +00:00
}