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
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
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-15 13:46:51 +00:00
GSRegisterCurrentThread ( ) ;
2011-07-11 15:12:47 +00:00
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-08-02 08:33:33 +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" ] )
{
2011-09-29 17:04:13 +00:00
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. Please see README.initialize for more information." ) ;
2011-03-16 12:17:02 +00:00
}
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
}
2011-07-15 13:46:51 +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
}