mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-23 00:41:02 +00:00
More garbage collection updates/fixes.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@27590 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
67c379bc7a
commit
940de12cab
10 changed files with 249 additions and 201 deletions
|
@ -1,3 +1,12 @@
|
|||
2009-01-13 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/NSGarbageCollector.m: Mark the two unimplemented methods.
|
||||
* Source/NSNotificationCenter.m: Automatically remove observers if
|
||||
they are collected by the GC system.
|
||||
* Source/NSThread.m: Make the GC system aware of each thread if poss.
|
||||
* Source/GSArray.m: Don't use inline array class with GC.
|
||||
* configure.ac: Add check for GC_register_my_thread
|
||||
|
||||
2009-01-12 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/GNUmakefile:
|
||||
|
|
|
@ -12,159 +12,6 @@
|
|||
/* Define if constructors are automatically loaded */
|
||||
#undef CON_AUTOLOAD
|
||||
|
||||
/* Built in default value for GNUstep config file */
|
||||
#undef GNUSTEP_TARGET_CONFIG_FILE
|
||||
|
||||
/* Built in default value for GNUstep local apps */
|
||||
#undef GNUSTEP_TARGET_LOCAL_ADMIN_APPS
|
||||
|
||||
/* Built in default value for GNUstep local tools */
|
||||
#undef GNUSTEP_TARGET_LOCAL_ADMIN_TOOLS
|
||||
|
||||
/* Built in default value for GNUstep local apps */
|
||||
#undef GNUSTEP_TARGET_LOCAL_APPS
|
||||
|
||||
/* Built in default value for GNUstep local documentation */
|
||||
#undef GNUSTEP_TARGET_LOCAL_DOC
|
||||
|
||||
/* Built in default value for GNUstep local info documentation */
|
||||
#undef GNUSTEP_TARGET_LOCAL_DOC_INFO
|
||||
|
||||
/* Built in default value for GNUstep local manpages documentation */
|
||||
#undef GNUSTEP_TARGET_LOCAL_DOC_MAN
|
||||
|
||||
/* Built in default value for GNUstep local headers */
|
||||
#undef GNUSTEP_TARGET_LOCAL_HEADERS
|
||||
|
||||
/* Built in default value for GNUstep local libraries */
|
||||
#undef GNUSTEP_TARGET_LOCAL_LIBRARIES
|
||||
|
||||
/* Built in default value for GNUstep local library */
|
||||
#undef GNUSTEP_TARGET_LOCAL_LIBRARY
|
||||
|
||||
/* Built in default value for GNUstep local tools */
|
||||
#undef GNUSTEP_TARGET_LOCAL_TOOLS
|
||||
|
||||
/* Built in default value for GNUstep Local Users directory */
|
||||
#undef GNUSTEP_TARGET_LOCAL_USERS_DIR
|
||||
|
||||
/* Built in default value for GNUstep local web apps */
|
||||
#undef GNUSTEP_TARGET_LOCAL_WEB_APPS
|
||||
|
||||
/* Built in default value for GNUstep Makefiles */
|
||||
#undef GNUSTEP_TARGET_MAKEFILES
|
||||
|
||||
/* Built in default value for GNUstep network apps */
|
||||
#undef GNUSTEP_TARGET_NETWORK_ADMIN_APPS
|
||||
|
||||
/* Built in default value for GNUstep system tools */
|
||||
#undef GNUSTEP_TARGET_NETWORK_ADMIN_TOOLS
|
||||
|
||||
/* Built in default value for GNUstep network apps */
|
||||
#undef GNUSTEP_TARGET_NETWORK_APPS
|
||||
|
||||
/* Built in default value for GNUstep network documentation */
|
||||
#undef GNUSTEP_TARGET_NETWORK_DOC
|
||||
|
||||
/* Built in default value for GNUstep network info documentation */
|
||||
#undef GNUSTEP_TARGET_NETWORK_DOC_INFO
|
||||
|
||||
/* Built in default value for GNUstep network manpages documentation */
|
||||
#undef GNUSTEP_TARGET_NETWORK_DOC_MAN
|
||||
|
||||
/* Built in default value for GNUstep network headers */
|
||||
#undef GNUSTEP_TARGET_NETWORK_HEADERS
|
||||
|
||||
/* Built in default value for GNUstep network libraries */
|
||||
#undef GNUSTEP_TARGET_NETWORK_LIBRARIES
|
||||
|
||||
/* Built in default value for GNUstep network library */
|
||||
#undef GNUSTEP_TARGET_NETWORK_LIBRARY
|
||||
|
||||
/* Built in default value for GNUstep network tools */
|
||||
#undef GNUSTEP_TARGET_NETWORK_TOOLS
|
||||
|
||||
/* Built in default value for GNUstep Network Users directory */
|
||||
#undef GNUSTEP_TARGET_NETWORK_USERS_DIR
|
||||
|
||||
/* Built in default value for GNUstep network web apps */
|
||||
#undef GNUSTEP_TARGET_NETWORK_WEB_APPS
|
||||
|
||||
/* Built in default value for GNUstep system apps */
|
||||
#undef GNUSTEP_TARGET_SYSTEM_ADMIN_APPS
|
||||
|
||||
/* Built in default value for GNUstep system tools */
|
||||
#undef GNUSTEP_TARGET_SYSTEM_ADMIN_TOOLS
|
||||
|
||||
/* Built in default value for GNUstep system apps */
|
||||
#undef GNUSTEP_TARGET_SYSTEM_APPS
|
||||
|
||||
/* Built in default value for GNUstep system documentation */
|
||||
#undef GNUSTEP_TARGET_SYSTEM_DOC
|
||||
|
||||
/* Built in default value for GNUstep system info documentation */
|
||||
#undef GNUSTEP_TARGET_SYSTEM_DOC_INFO
|
||||
|
||||
/* Built in default value for GNUstep system manpages documentation */
|
||||
#undef GNUSTEP_TARGET_SYSTEM_DOC_MAN
|
||||
|
||||
/* Built in default value for GNUstep system headers */
|
||||
#undef GNUSTEP_TARGET_SYSTEM_HEADERS
|
||||
|
||||
/* Built in default value for GNUstep system libraries */
|
||||
#undef GNUSTEP_TARGET_SYSTEM_LIBRARIES
|
||||
|
||||
/* Built in default value for GNUstep system library */
|
||||
#undef GNUSTEP_TARGET_SYSTEM_LIBRARY
|
||||
|
||||
/* Built in default value for GNUstep system tools */
|
||||
#undef GNUSTEP_TARGET_SYSTEM_TOOLS
|
||||
|
||||
/* Built in default value for GNUstep System Users directory */
|
||||
#undef GNUSTEP_TARGET_SYSTEM_USERS_DIR
|
||||
|
||||
/* Built in default value for GNUstep web apps */
|
||||
#undef GNUSTEP_TARGET_SYSTEM_WEB_APPS
|
||||
|
||||
/* Built in default value for GNUstep user config file */
|
||||
#undef GNUSTEP_TARGET_USER_CONFIG_FILE
|
||||
|
||||
/* Built in default value for GNUstep user defaults directory */
|
||||
#undef GNUSTEP_TARGET_USER_DEFAULTS_DIR
|
||||
|
||||
/* Built in default value for GNUstep user_dir admin apps */
|
||||
#undef GNUSTEP_TARGET_USER_DIR_ADMIN_APPS
|
||||
|
||||
/* Built in default value for GNUstep user_dir tools */
|
||||
#undef GNUSTEP_TARGET_USER_DIR_ADMIN_TOOLS
|
||||
|
||||
/* Built in default value for GNUstep user_dir apps */
|
||||
#undef GNUSTEP_TARGET_USER_DIR_APPS
|
||||
|
||||
/* Built in default value for GNUstep user_dir documentation */
|
||||
#undef GNUSTEP_TARGET_USER_DIR_DOC
|
||||
|
||||
/* Built in default value for GNUstep user_dir info documentation */
|
||||
#undef GNUSTEP_TARGET_USER_DIR_DOC_INFO
|
||||
|
||||
/* Built in default value for GNUstep user_dir manpages documentation */
|
||||
#undef GNUSTEP_TARGET_USER_DIR_DOC_MAN
|
||||
|
||||
/* Built in default value for GNUstep user_dir headers */
|
||||
#undef GNUSTEP_TARGET_USER_DIR_HEADERS
|
||||
|
||||
/* Built in default value for GNUstep user_dir libraries */
|
||||
#undef GNUSTEP_TARGET_USER_DIR_LIBRARIES
|
||||
|
||||
/* Built in default value for GNUstep user_dir library */
|
||||
#undef GNUSTEP_TARGET_USER_DIR_LIBRARY
|
||||
|
||||
/* Built in default value for GNUstep user_dir tools */
|
||||
#undef GNUSTEP_TARGET_USER_DIR_TOOLS
|
||||
|
||||
/* Built in default value for GNUstep user_dir web apps */
|
||||
#undef GNUSTEP_TARGET_USER_DIR_WEB_APPS
|
||||
|
||||
/* Define if this constant is defined */
|
||||
#undef HANDLE_LLONG_MAX
|
||||
|
||||
|
@ -199,6 +46,12 @@
|
|||
/* Define if libobjc has the __objc_msg_forward2 function */
|
||||
#undef HAVE_FORWARD2
|
||||
|
||||
/* Define to 1 if you have the <gc.h> header file. */
|
||||
#undef HAVE_GC_H
|
||||
|
||||
/* Define if GC_register_my_thread function is available */
|
||||
#undef HAVE_GC_REGISTER_MY_THREAD
|
||||
|
||||
/* Define to 1 if you have the `getcwd' function. */
|
||||
#undef HAVE_GETCWD
|
||||
|
||||
|
@ -600,9 +453,6 @@
|
|||
/* Define if your system needs to have short/int word aligned */
|
||||
#undef NEED_WORD_ALIGNMENT
|
||||
|
||||
/* Disable GNUSTEP_CONFIG_FILE environment variable */
|
||||
#undef OPTION_NO_ENVIRONMENT
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#undef PACKAGE_BUGREPORT
|
||||
|
||||
|
|
|
@ -43,7 +43,11 @@
|
|||
static SEL eqSel;
|
||||
static SEL oaiSel;
|
||||
|
||||
#if GS_WITH_GC
|
||||
static Class GSArrayClass;
|
||||
#else
|
||||
static Class GSInlineArrayClass;
|
||||
#endif
|
||||
|
||||
@class GSArray;
|
||||
|
||||
|
@ -75,7 +79,8 @@ static Class GSInlineArrayClass;
|
|||
[NSNumber numberWithUnsignedInt: _count], @"Count",
|
||||
self, @"Array", nil, nil];
|
||||
|
||||
reason = [NSString stringWithFormat: @"Index %d is out of range %d (in '%@')",
|
||||
reason = [NSString stringWithFormat:
|
||||
@"Index %d is out of range %d (in '%@')",
|
||||
index, _count, NSStringFromSelector(sel)];
|
||||
|
||||
exception = [NSException exceptionWithName: NSRangeException
|
||||
|
@ -91,7 +96,11 @@ static Class GSInlineArrayClass;
|
|||
[self setVersion: 1];
|
||||
eqSel = @selector(isEqual:);
|
||||
oaiSel = @selector(objectAtIndex:);
|
||||
#if GS_WITH_GC
|
||||
GSArrayClass = [GSArray class];
|
||||
#else
|
||||
GSInlineArrayClass = [GSInlineArray class];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -349,19 +358,29 @@ static Class GSInlineArrayClass;
|
|||
}
|
||||
@end
|
||||
|
||||
#if !GS_WITH_GC
|
||||
/* This class stores objects inline in data beyond the end of the instance.
|
||||
* However, when GC is enabled the object data is typed, and all data after
|
||||
* the end of the class is ignored by the garbage collector (which would
|
||||
* mean that objects in the array could be collected).
|
||||
* We therefore do not provide the class ewhan GC is being used.
|
||||
*/
|
||||
@interface GSInlineArray : GSArray
|
||||
{
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation GSInlineArray
|
||||
- (void) dealloc
|
||||
{
|
||||
if (_contents_array)
|
||||
{
|
||||
#if !GS_WITH_GC
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < _count; i++)
|
||||
{
|
||||
[_contents_array[i] release];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
NSDeallocateObject(self);
|
||||
GSNOSUPERDEALLOC;
|
||||
|
@ -392,6 +411,7 @@ static Class GSInlineArrayClass;
|
|||
return self;
|
||||
}
|
||||
@end
|
||||
#endif
|
||||
|
||||
@implementation GSMutableArray
|
||||
|
||||
|
@ -437,7 +457,11 @@ static Class GSInlineArrayClass;
|
|||
{
|
||||
NSArray *copy;
|
||||
|
||||
#if GS_WITH_GC
|
||||
copy = (id)NSAllocateObject(GSArrayClass, 0, zone);
|
||||
#else
|
||||
copy = (id)NSAllocateObject(GSInlineArrayClass, sizeof(id)*_count, zone);
|
||||
#endif
|
||||
return [copy initWithObjects: _contents_array count: _count];
|
||||
}
|
||||
|
||||
|
@ -1002,7 +1026,11 @@ static Class GSInlineArrayClass;
|
|||
|
||||
+ (void) initialize
|
||||
{
|
||||
#if GS_WITH_GC
|
||||
GSArrayClass = [GSArray class];
|
||||
#else
|
||||
GSInlineArrayClass = [GSInlineArray class];
|
||||
#endif
|
||||
}
|
||||
|
||||
- (id) autorelease
|
||||
|
@ -1039,13 +1067,21 @@ static Class GSInlineArrayClass;
|
|||
}
|
||||
else
|
||||
{
|
||||
GSInlineArray *a;
|
||||
unsigned c;
|
||||
#if GS_WITH_GC
|
||||
GSArray *a;
|
||||
|
||||
[aCoder decodeValueOfObjCType: @encode(unsigned) at: &c];
|
||||
a = (id)NSAllocateObject(GSArrayClass, 0, GSObjCZone(self));
|
||||
a->_contents_array = NSZoneMalloc(GSObjCZone(self), sizeof(id)*c);
|
||||
#else
|
||||
GSInlineArray *a;
|
||||
|
||||
[aCoder decodeValueOfObjCType: @encode(unsigned) at: &c];
|
||||
a = (id)NSAllocateObject(GSInlineArrayClass,
|
||||
sizeof(id)*c, GSObjCZone(self));
|
||||
a->_contents_array = (id*)&a[1];
|
||||
#endif
|
||||
if (c > 0)
|
||||
{
|
||||
[aCoder decodeArrayOfObjCType: @encode(id)
|
||||
|
@ -1059,8 +1095,12 @@ static Class GSInlineArrayClass;
|
|||
|
||||
- (id) initWithObjects: (id*)objects count: (unsigned)count
|
||||
{
|
||||
#if GS_WITH_GC
|
||||
self = (id)NSAllocateObject(GSArrayClass, 0, GSObjCZone(self));
|
||||
#else
|
||||
self = (id)NSAllocateObject(GSInlineArrayClass, sizeof(id)*count,
|
||||
GSObjCZone(self));
|
||||
#endif
|
||||
return [self initWithObjects: objects count: count];
|
||||
}
|
||||
|
||||
|
|
|
@ -73,11 +73,6 @@
|
|||
}
|
||||
@end
|
||||
|
||||
@interface GSInlineArray : GSArray
|
||||
{
|
||||
}
|
||||
@end
|
||||
|
||||
@interface GSPlaceholderArray : NSArray
|
||||
{
|
||||
}
|
||||
|
|
|
@ -84,7 +84,6 @@ extern void GSPropertyListMake(id,NSDictionary*,BOOL,BOOL,unsigned,id*);
|
|||
|
||||
static Class NSArrayClass;
|
||||
static Class GSArrayClass;
|
||||
static Class GSInlineArrayClass;
|
||||
static Class NSMutableArrayClass;
|
||||
static Class GSMutableArrayClass;
|
||||
static Class GSPlaceholderArrayClass;
|
||||
|
@ -125,7 +124,6 @@ static SEL rlSel;
|
|||
NSArrayClass = [NSArray class];
|
||||
NSMutableArrayClass = [NSMutableArray class];
|
||||
GSArrayClass = [GSArray class];
|
||||
GSInlineArrayClass = [GSInlineArray class];
|
||||
GSMutableArrayClass = [GSMutableArray class];
|
||||
GSPlaceholderArrayClass = [GSPlaceholderArray class];
|
||||
|
||||
|
|
|
@ -82,6 +82,7 @@ static unsigned disabled = 0;
|
|||
- (void) disableCollectorForPointer: (void *)ptr
|
||||
{
|
||||
// FIXME
|
||||
[self notImplemented: _cmd];
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -102,6 +103,7 @@ static unsigned disabled = 0;
|
|||
- (void) enableCollectorForPointer: (void *)ptr
|
||||
{
|
||||
// FIXME
|
||||
[self notImplemented: _cmd];
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,13 +30,22 @@
|
|||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "Foundation/NSNotification.h"
|
||||
#include "Foundation/NSException.h"
|
||||
#include "Foundation/NSLock.h"
|
||||
#include "Foundation/NSThread.h"
|
||||
#include "Foundation/NSDebug.h"
|
||||
#include "GNUstepBase/GSLock.h"
|
||||
#import "Foundation/NSNotification.h"
|
||||
#import "Foundation/NSException.h"
|
||||
#import "Foundation/NSLock.h"
|
||||
#import "Foundation/NSThread.h"
|
||||
#import "Foundation/NSDebug.h"
|
||||
#import "GNUstepBase/GSLock.h"
|
||||
|
||||
/* purgeCollected() returns a list of observations with any observations for
|
||||
* a collected observer removed.
|
||||
*/
|
||||
#if GS_WITH_GC
|
||||
#include <gc.h>
|
||||
#define purgeCollected(X) (X = listPurge(X, nil))
|
||||
#else
|
||||
#define purgeCollected(X) (X)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Concrete class implementing NSNotification.
|
||||
|
@ -425,6 +434,9 @@ static void obsFree(Observation *o)
|
|||
{
|
||||
NCTable *t = o->link;
|
||||
|
||||
#if GS_WITH_GC
|
||||
GC_unregister_disappearing_link((GC_PTR*)&o->observer);
|
||||
#endif
|
||||
o->link = (NCTable*)t->freeList;
|
||||
t->freeList = o;
|
||||
}
|
||||
|
@ -533,7 +545,7 @@ purgeMapNode(GSIMapTable map, GSIMapNode node, id observer)
|
|||
* I know of.
|
||||
*
|
||||
* We also use this trick to differentiate between map table keys that
|
||||
* should be treated as objects (notification names) and thise that
|
||||
* should be treated as objects (notification names) and those that
|
||||
* should be treated as pointers (notification objects)
|
||||
*/
|
||||
#define CHEATGC(X) (id)(((uintptr_t)X) | 1)
|
||||
|
@ -641,7 +653,10 @@ static NSNotificationCenter *default_center = nil;
|
|||
*
|
||||
* <p>The notification center does not retain observer or object. Therefore,
|
||||
* you should always send removeObserver: or removeObserver:name:object: to
|
||||
* the notification center before releasing these objects.</p>
|
||||
* the notification center before releasing these objects.<br />
|
||||
* As a convenience, when built with garbage collection, you do not need to
|
||||
* remove any garbage collected observer as the system will do it implicitly.
|
||||
* </p>
|
||||
*
|
||||
* <p>NB. For MacOS-X compatibility, adding an observer multiple times will
|
||||
* register it to receive multiple copies of any matching notification, however
|
||||
|
@ -687,8 +702,23 @@ static NSNotificationCenter *default_center = nil;
|
|||
o->retained = 0;
|
||||
o->next = 0;
|
||||
|
||||
#if GS_WITH_GC
|
||||
/* Ensure that if the observer is garbage collected, we clear the
|
||||
* oservation so that we don't end up sending notifications to the
|
||||
* deallocated object.
|
||||
* The observer must be a real GC-allocated object or this mechanism
|
||||
* can't be used.
|
||||
*/
|
||||
if (GC_base(observer) != 0)
|
||||
{
|
||||
GC_general_register_disappearing_link((GC_PTR*)&o->observer, observer);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (object != nil)
|
||||
object = CHEATGC(object);
|
||||
{
|
||||
object = CHEATGC(object);
|
||||
}
|
||||
|
||||
/*
|
||||
* Record the Observation in one of the linked lists.
|
||||
|
@ -943,6 +973,7 @@ static NSNotificationCenter *default_center = nil;
|
|||
*/
|
||||
- (void) _postAndRelease: (NSNotification*)notification
|
||||
{
|
||||
IF_NO_GC(GSGarbageCollector *collector = [NSGarbageCollector defaultCollector])
|
||||
Observation *o;
|
||||
unsigned count;
|
||||
NSString *name = [notification name];
|
||||
|
@ -952,6 +983,9 @@ static NSNotificationCenter *default_center = nil;
|
|||
GSIArrayItem i[64];
|
||||
GSIArray_t b;
|
||||
GSIArray a = &b;
|
||||
#if GS_WITH_GG
|
||||
GSGarbageCollector *collector = [NSGarbageCollector defaultCollector];
|
||||
#endif
|
||||
|
||||
if (name == nil)
|
||||
{
|
||||
|
@ -971,14 +1005,21 @@ static NSNotificationCenter *default_center = nil;
|
|||
GSIArrayInitWithZoneAndStaticCapacity(a, NSDefaultMallocZone(), 64, i);
|
||||
|
||||
/*
|
||||
* Lock the table of observers while we traverse it.
|
||||
* Lock the table of observations while we traverse it.
|
||||
*
|
||||
* The table of observations contains weak pointers which are zeroed when
|
||||
* the observers get garbage collected. So to avoid consistency problems
|
||||
* we disable gc while we copy all the observations we are interested in.
|
||||
*/
|
||||
lockNCTable(TABLE);
|
||||
#if GS_WITH_GG
|
||||
[collector disable];
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Find all the observers that specified neither NAME nor OBJECT.
|
||||
*/
|
||||
for (o = WILDCARD; o != ENDOBS; o = o->next)
|
||||
for (o = purgeCollected(WILDCARD); o != ENDOBS; o = o->next)
|
||||
{
|
||||
GSIArrayAddItem(a, (GSIArrayItem)o);
|
||||
}
|
||||
|
@ -991,7 +1032,7 @@ static NSNotificationCenter *default_center = nil;
|
|||
n = GSIMapNodeForSimpleKey(NAMELESS, (GSIMapKey)object);
|
||||
if (n != 0)
|
||||
{
|
||||
o = n->value.ext;
|
||||
o = purgeCollected(n->value.ext);
|
||||
while (o != ENDOBS)
|
||||
{
|
||||
GSIArrayAddItem(a, (GSIArrayItem)o);
|
||||
|
@ -1023,7 +1064,7 @@ static NSNotificationCenter *default_center = nil;
|
|||
n = GSIMapNodeForSimpleKey(m, (GSIMapKey)object);
|
||||
if (n != 0)
|
||||
{
|
||||
o = n->value.ext;
|
||||
o = purgeCollected(n->value.ext);
|
||||
while (o != ENDOBS)
|
||||
{
|
||||
GSIArrayAddItem(a, (GSIArrayItem)o);
|
||||
|
@ -1039,7 +1080,7 @@ static NSNotificationCenter *default_center = nil;
|
|||
n = GSIMapNodeForSimpleKey(m, (GSIMapKey)nil);
|
||||
if (n != 0)
|
||||
{
|
||||
o = n->value.ext;
|
||||
o = purgeCollected(n->value.ext);
|
||||
while (o != ENDOBS)
|
||||
{
|
||||
GSIArrayAddItem(a, (GSIArrayItem)o);
|
||||
|
@ -1047,13 +1088,17 @@ static NSNotificationCenter *default_center = nil;
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Finished with the table ... we can unlock it.
|
||||
* Finished with the table ... we can unlock it and re-enable garbage
|
||||
* collection, safe in the knowledge that the observers we will be
|
||||
* notifying won't get collected prematurely.
|
||||
*/
|
||||
#if GS_WITH_GG
|
||||
[collector enable];
|
||||
#endif
|
||||
unlockNCTable(TABLE);
|
||||
|
||||
/*
|
||||
|
|
|
@ -80,6 +80,10 @@
|
|||
#include "GSPrivate.h"
|
||||
#include "GSRunLoopCtxt.h"
|
||||
|
||||
#if GS_WITH_GC
|
||||
#include <gc.h>
|
||||
#endif
|
||||
|
||||
@interface NSAutoreleasePool (NSThread)
|
||||
+ (void) _endThread: (NSThread*)thread;
|
||||
@end
|
||||
|
@ -506,6 +510,9 @@ gnustep_base_thread_callback(void)
|
|||
|
||||
objc_thread_set_data (NULL);
|
||||
|
||||
#if GS_WITH_GC && defined(HAVE_GC_REGISTER_MY_THREAD)
|
||||
GC_unregister_my_thread();
|
||||
#endif
|
||||
/*
|
||||
* Tell the runtime to exit the thread
|
||||
*/
|
||||
|
@ -734,6 +741,9 @@ gnustep_base_thread_callback(void)
|
|||
NSStringFromSelector(_cmd)];
|
||||
}
|
||||
|
||||
#if GS_WITH_GC && defined(HAVE_GC_REGISTER_MY_THREAD)
|
||||
GC_register_my_thread();
|
||||
#endif
|
||||
#if defined(HAVE_SETRLIMIT) && defined(RLIMIT_STACK)
|
||||
if (_stackSize > 0)
|
||||
{
|
||||
|
|
119
configure
vendored
119
configure
vendored
|
@ -3468,11 +3468,9 @@ fi
|
|||
done
|
||||
|
||||
if test "$gc_ok" = no; then
|
||||
{ { echo "$as_me:$LINENO: error: Garbage collection was required, but the gc.h header" >&5
|
||||
echo "$as_me: error: Garbage collection was required, but the gc.h header" >&2;}
|
||||
{ { echo "$as_me:$LINENO: error: Garbage collection was required, but the gc.h header couldn't be found." >&5
|
||||
echo "$as_me: error: Garbage collection was required, but the gc.h header couldn't be found." >&2;}
|
||||
{ (exit 1); exit 1; }; }
|
||||
{ echo "$as_me:$LINENO: couldn't be found." >&5
|
||||
echo "$as_me: couldn't be found." >&6;}
|
||||
fi
|
||||
saved_LIBS="$LIBS"
|
||||
LIBS+=" -lgc"
|
||||
|
@ -3573,11 +3571,110 @@ else
|
|||
fi
|
||||
|
||||
if test "$gc_ok" = no; then
|
||||
{ { echo "$as_me:$LINENO: error: Garbage collection was required, but the gc library" >&5
|
||||
echo "$as_me: error: Garbage collection was required, but the gc library" >&2;}
|
||||
{ { echo "$as_me:$LINENO: error: Garbage collection was required, but the gc library couldn't be found." >&5
|
||||
echo "$as_me: error: Garbage collection was required, but the gc library couldn't be found." >&2;}
|
||||
{ (exit 1); exit 1; }; }
|
||||
{ echo "$as_me:$LINENO: couldn't be found." >&5
|
||||
echo "$as_me: couldn't be found." >&6;}
|
||||
fi
|
||||
echo "$as_me:$LINENO: checking for GC_register_my_thread" >&5
|
||||
echo $ECHO_N "checking for GC_register_my_thread... $ECHO_C" >&6
|
||||
if test "${ac_cv_func_GC_register_my_thread+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
/* Define GC_register_my_thread to an innocuous variant, in case <limits.h> declares GC_register_my_thread.
|
||||
For example, HP-UX 11i <limits.h> declares gettimeofday. */
|
||||
#define GC_register_my_thread innocuous_GC_register_my_thread
|
||||
|
||||
/* System header to define __stub macros and hopefully few prototypes,
|
||||
which can conflict with char GC_register_my_thread (); below.
|
||||
Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
|
||||
<limits.h> exists even on freestanding compilers. */
|
||||
|
||||
#ifdef __STDC__
|
||||
# include <limits.h>
|
||||
#else
|
||||
# include <assert.h>
|
||||
#endif
|
||||
|
||||
#undef GC_register_my_thread
|
||||
|
||||
/* Override any gcc2 internal prototype to avoid an error. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
/* We use char because int might match the return type of a gcc2
|
||||
builtin and then its argument prototype would still apply. */
|
||||
char GC_register_my_thread ();
|
||||
/* The GNU C library defines this for functions which it implements
|
||||
to always fail with ENOSYS. Some functions are actually named
|
||||
something starting with __ and the normal name is an alias. */
|
||||
#if defined (__stub_GC_register_my_thread) || defined (__stub___GC_register_my_thread)
|
||||
choke me
|
||||
#else
|
||||
char (*f) () = GC_register_my_thread;
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return f != GC_register_my_thread;
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext conftest$ac_exeext
|
||||
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
|
||||
(eval $ac_link) 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } &&
|
||||
{ ac_try='test -z "$ac_c_werror_flag"
|
||||
|| test ! -s conftest.err'
|
||||
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; } &&
|
||||
{ ac_try='test -s conftest$ac_exeext'
|
||||
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; }; then
|
||||
ac_cv_func_GC_register_my_thread=yes
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
ac_cv_func_GC_register_my_thread=no
|
||||
fi
|
||||
rm -f conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
fi
|
||||
echo "$as_me:$LINENO: result: $ac_cv_func_GC_register_my_thread" >&5
|
||||
echo "${ECHO_T}$ac_cv_func_GC_register_my_thread" >&6
|
||||
|
||||
if test "$ac_cv_func_GC_register_my_thread" = yes; then
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define HAVE_GC_REGISTER_MY_THREAD 1
|
||||
_ACEOF
|
||||
|
||||
else
|
||||
{ echo "$as_me:$LINENO: It looks like your libgc is quite old ... please use a newer one to support making the garbage collector aware of new threads." >&5
|
||||
echo "$as_me: It looks like your libgc is quite old ... please use a newer one to support making the garbage collector aware of new threads." >&6;}
|
||||
fi
|
||||
LIBS="-lobjc_gc -ldl"
|
||||
echo "$as_me:$LINENO: checking for class_ivar_set_gcinvisible" >&5
|
||||
|
@ -3677,11 +3774,9 @@ else
|
|||
fi
|
||||
|
||||
if test "$gc_ok" = no; then
|
||||
{ { echo "$as_me:$LINENO: error: Garbage collection was required, but the gc runtime" >&5
|
||||
echo "$as_me: error: Garbage collection was required, but the gc runtime" >&2;}
|
||||
{ { echo "$as_me:$LINENO: error: Garbage collection was required, but the gc runtime couldn't be found." >&5
|
||||
echo "$as_me: error: Garbage collection was required, but the gc runtime couldn't be found." >&2;}
|
||||
{ (exit 1); exit 1; }; }
|
||||
{ echo "$as_me:$LINENO: couldn't be found." >&5
|
||||
echo "$as_me: couldn't be found." >&6;}
|
||||
fi
|
||||
LIBS="$saved_LIBS"
|
||||
|
||||
|
|
16
configure.ac
16
configure.ac
|
@ -264,21 +264,25 @@ fi
|
|||
if test $OBJC_WITH_GC = yes; then
|
||||
AC_CHECK_HEADERS(gc.h, gc_ok=yes, gc_ok=no)
|
||||
if test "$gc_ok" = no; then
|
||||
AC_MSG_ERROR([Garbage collection was required, but the gc.h header])
|
||||
AC_MSG_NOTICE([couldn't be found.])
|
||||
AC_MSG_ERROR([Garbage collection was required, but the gc.h header couldn't be found.])
|
||||
fi
|
||||
saved_LIBS="$LIBS"
|
||||
LIBS+=" -lgc"
|
||||
AC_CHECK_FUNC(GC_malloc, gc_ok=yes, gc_ok=no)
|
||||
if test "$gc_ok" = no; then
|
||||
AC_MSG_ERROR([Garbage collection was required, but the gc library])
|
||||
AC_MSG_NOTICE([couldn't be found.])
|
||||
AC_MSG_ERROR([Garbage collection was required, but the gc library couldn't be found.])
|
||||
fi
|
||||
AC_CHECK_FUNC(GC_register_my_thread)
|
||||
if test "$ac_cv_func_GC_register_my_thread" = yes; then
|
||||
AC_DEFINE(HAVE_GC_REGISTER_MY_THREAD,1,
|
||||
[Define if GC_register_my_thread function is available])
|
||||
else
|
||||
AC_MSG_NOTICE([It looks like your libgc is quite old ... please use a newer one to support making the garbage collector aware of new threads.])
|
||||
fi
|
||||
LIBS="-lobjc_gc -ldl"
|
||||
AC_CHECK_FUNC(class_ivar_set_gcinvisible, gc_ok=yes, gc_ok=no)
|
||||
if test "$gc_ok" = no; then
|
||||
AC_MSG_ERROR([Garbage collection was required, but the gc runtime])
|
||||
AC_MSG_NOTICE([couldn't be found.])
|
||||
AC_MSG_ERROR([Garbage collection was required, but the gc runtime couldn't be found.])
|
||||
fi
|
||||
LIBS="$saved_LIBS"
|
||||
AC_SUBST(OBJC_WITH_GC)
|
||||
|
|
Loading…
Reference in a new issue