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"
|
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
|
|
|
|
|
#include <gc.h>
|
|
|
|
|
#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)
|
|
|
|
|
{
|
2009-09-08 20:32:52 +00:00
|
|
|
|
if (defaultThread == nil)
|
|
|
|
|
{
|
|
|
|
|
[NSThread currentThread];
|
|
|
|
|
}
|
|
|
|
|
return (NSThread*)pthread_getspecific(thread_object_key);
|
* 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.
|
|
|
|
|
*/
|
* 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
|
|
|
|
// FIXME: This code is complete nonsense; this can be called from
|
|
|
|
|
// any thread (and is when adding new foreign threads), so this
|
|
|
|
|
// will often be called from the wrong thread, delivering
|
|
|
|
|
// notifications to the wrong thread, and generally doing the
|
|
|
|
|
// wrong thing..
|
2003-09-30 18:19:03 +00:00
|
|
|
|
if (nc == nil)
|
|
|
|
|
{
|
2004-11-10 11:45:08 +00:00
|
|
|
|
nc = RETAIN([NSNotificationCenter defaultCenter]);
|
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
|
|
|
|
{
|
|
|
|
|
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];
|
|
|
|
|
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;
|
|
|
|
|
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
|
|
|
|
|
{
|
|
|
|
|
return (NSThread*)pthread_getspecific(thread_object_key);
|
(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
|
|
|
|
|
* 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 _createThreadForCurrentPthread];
|
|
|
|
|
defaultThread = [NSThread currentThread];
|
2009-09-05 17:28:01 +00:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* The objc runtime calls this callback AFTER creating a new thread -
|
|
|
|
|
* which is not correct for us, but does at least mean that we can tell
|
|
|
|
|
* if we have become multi-threaded due to a call to the runtime directly
|
|
|
|
|
* rather than via the NSThread class.
|
|
|
|
|
*/
|
2010-06-07 00:27:21 +00:00
|
|
|
|
#if defined(__GNUSTEP_RUNTIME__) || defined(NeXT_RUNTIME)
|
2010-06-03 17:35:45 +00:00
|
|
|
|
gnustep_base_thread_callback();
|
|
|
|
|
#else
|
2009-09-05 17:28:01 +00:00
|
|
|
|
objc_set_thread_callback(gnustep_base_thread_callback);
|
2010-06-03 17:35:45 +00:00
|
|
|
|
#endif
|
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, ¶m);
|
|
|
|
|
param.sched_priority = pri;
|
|
|
|
|
pthread_setschedparam(pthread_self(), policy, ¶m);
|
|
|
|
|
#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, ¶m);
|
|
|
|
|
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);
|
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.
|
|
|
|
|
*/
|
* 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
|
|
|
|
RETAIN(self);
|
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];
|
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
|
|
|
|
}
|