diff --git a/ChangeLog b/ChangeLog
index 2e6713ce2..175c5fbd0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2009-01-13 Richard Frith-Macdonald
+
+ * 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
* Source/GNUmakefile:
diff --git a/Headers/Additions/GNUstepBase/config.h.in b/Headers/Additions/GNUstepBase/config.h.in
index 4926e627e..b27c4a744 100644
--- a/Headers/Additions/GNUstepBase/config.h.in
+++ b/Headers/Additions/GNUstepBase/config.h.in
@@ -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 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
diff --git a/Source/GSArray.m b/Source/GSArray.m
index f78070dc9..7bc6c965d 100644
--- a/Source/GSArray.m
+++ b/Source/GSArray.m
@@ -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];
}
diff --git a/Source/GSPrivate.h b/Source/GSPrivate.h
index 1ab2ead63..a492d82e2 100644
--- a/Source/GSPrivate.h
+++ b/Source/GSPrivate.h
@@ -73,11 +73,6 @@
}
@end
-@interface GSInlineArray : GSArray
-{
-}
-@end
-
@interface GSPlaceholderArray : NSArray
{
}
diff --git a/Source/NSArray.m b/Source/NSArray.m
index 502d52648..b3390123e 100644
--- a/Source/NSArray.m
+++ b/Source/NSArray.m
@@ -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];
diff --git a/Source/NSGarbageCollector.m b/Source/NSGarbageCollector.m
index db3573aac..bffc15438 100644
--- a/Source/NSGarbageCollector.m
+++ b/Source/NSGarbageCollector.m
@@ -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;
}
diff --git a/Source/NSNotificationCenter.m b/Source/NSNotificationCenter.m
index 098816310..6ae28e02d 100644
--- a/Source/NSNotificationCenter.m
+++ b/Source/NSNotificationCenter.m
@@ -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
+#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;
*
* 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.
+ * the notification center before releasing these objects.
+ * 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.
+ *
*
* 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);
/*
diff --git a/Source/NSThread.m b/Source/NSThread.m
index 9131a91aa..7f7269dda 100644
--- a/Source/NSThread.m
+++ b/Source/NSThread.m
@@ -80,6 +80,10 @@
#include "GSPrivate.h"
#include "GSRunLoopCtxt.h"
+#if GS_WITH_GC
+#include
+#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)
{
diff --git a/configure b/configure
index 08ea94acc..fbdf055b7 100755
--- a/configure
+++ b/configure
@@ -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 declares GC_register_my_thread.
+ For example, HP-UX 11i 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 to if __STDC__ is defined, since
+ exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include
+#else
+# include
+#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"
diff --git a/configure.ac b/configure.ac
index 5d3f7135d..f499a55fb 100644
--- a/configure.ac
+++ b/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)