[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[RFC/base] GSAllocateMutexAt()
From: |
David Ayers |
Subject: |
[RFC/base] GSAllocateMutexAt() |
Date: |
Wed, 05 May 2004 19:53:34 +0200 |
User-agent: |
Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.6) Gecko/20040113 |
Hello everyone,
I'm hoping to flush a couple of my local changes back to -base(add) in
the coming days. As they will introduce new API, I'd like to give
everyone a quick chance to object or constructively criticize. These
will mostly be focused on GSObjCRuntime and it utilities. I've tried to
take care that most of the API is +load and thread safe. I've done some
testing with both -base and -baseadd/Cocoa.
To start off I'm adding:
void GSAllocateMutexAt(objc_mutex_t *location)
This function provided an API to initialize a mutex safely in +load
(without triggering any unrelated objc initialization like
NSObject/NSLock) even in a multithreaded environment. Currently this
patch assumes that NeXT_RUNTIME uses pthreads.h. If anyone is using
GNUstep with a NeXT_RUNTIME that uses a different threading library
please let me know.
Cheers,
David
Index: Headers/Additions/GNUstepBase/GSObjCRuntime.h
===================================================================
RCS file:
/cvsroot/gnustep/gnustep/core/base/Headers/Additions/GNUstepBase/GSObjCRuntime.h,v
retrieving revision 1.3
diff -u -r1.3 GSObjCRuntime.h
--- Headers/Additions/GNUstepBase/GSObjCRuntime.h 10 Sep 2003 09:29:39
-0000 1.3
+++ Headers/Additions/GNUstepBase/GSObjCRuntime.h 5 May 2004 17:50:03
-0000
@@ -468,6 +468,31 @@
GS_EXPORT void *
GSAutoreleasedBuffer(unsigned size);
+/**
+ * Allocate a new objc_mutex_t and store it in the location
+ * pointed to by request. A mutex is only created if the value
+ * pointed to by request is NULL. This function is thread safe
+ * in the sense that multiple threads my call this function with the same
+ * value of request and only one will actually set the mutex.
+ * It is the users responsibility that no one else attempts to set
+ * the mutex pointed to. This function should be
+ * used with objc_mutex_t variables which were statically initialized
+ * to NULL like:
+ * <example>
+ * void function (void)
+ * {
+ * static objc_mutex_t my_lock = NULL;
+ * if (my_lock == NULL)
+ * GSAllocateMutexAt(&my_lock);
+ * objc_mutex_lock(my_lock);
+ * do_work ();
+ * objc_mutex_unlock(my_lock);
+ * }
+ * </example>
+ */
+GS_EXPORT void
+GSAllocateMutexAt(objc_mutex_t *request);
+
/** Returns a system error message on a variety of systems
*/
GS_EXPORT const char *
Index: Headers/Additions/GNUstepBase/objc-gnu2next.h
===================================================================
RCS file:
/cvsroot/gnustep/gnustep/core/base/Headers/Additions/GNUstepBase/objc-gnu2next.h,v
retrieving revision 1.1
diff -u -r1.1 objc-gnu2next.h
--- Headers/Additions/GNUstepBase/objc-gnu2next.h 31 Jul 2003 23:49:29
-0000 1.1
+++ Headers/Additions/GNUstepBase/objc-gnu2next.h 5 May 2004 17:50:04
-0000
@@ -36,8 +36,8 @@
#include <ctype.h>
#include <stdio.h>
-/* Disable builtin functions for gcc < 3.x since it triggers a bad bug (even
some 3.x versions may have this
- bug) */
+/* Disable builtin functions for gcc < 3.x since it triggers a bad bug
+ (even some 3.x versions may have this bug). */
#if __GNUC__ < 3
#define __builtin_apply(a,b,c) 0
#define __builtin_apply_args() 0
@@ -191,6 +191,16 @@
extern void *(*_objc_realloc)(void *, size_t);
extern void *(*_objc_calloc)(size_t, size_t);
extern void (*_objc_free)(void *);
+
+
+/* threading functions */
+typedef void *objc_mutex_t;
+
+objc_mutex_t objc_mutex_allocate (void);
+int objc_mutex_deallocate (objc_mutex_t mutex);
+int objc_mutex_lock (objc_mutex_t mutex);
+int objc_mutex_unlock (objc_mutex_t mutex);
+int objc_mutex_trylock (objc_mutex_t mutex);
/* encoding functions */
extern int objc_sizeof_type(const char* type);
Index: Source/Additions/GSNextRuntime.m
===================================================================
RCS file: /cvsroot/gnustep/gnustep/core/base/Source/Additions/GSNextRuntime.m,v
retrieving revision 1.4
diff -u -r1.4 GSNextRuntime.m
--- Source/Additions/GSNextRuntime.m 31 Jul 2003 23:49:32 -0000 1.4
+++ Source/Additions/GSNextRuntime.m 5 May 2004 17:50:04 -0000
@@ -593,3 +593,59 @@
return temp;
}
+/*
+ * Functions for threading support.
+ */
+
+/* This currently assumes that the NeXT Runtime is using pthreads
+ as the underlying thread support. This is true for 'modern' NeXT
+ Runtime implementations but it may not be for older versions. */
+
+#include <pthread.h>
+
+objc_mutex_t
+objc_mutex_allocate(void)
+{
+ pthread_mutex_t *p;
+ p = (pthread_mutex_t *)calloc(1, sizeof(pthread_mutex_t));
+ if (pthread_mutex_init(p, NULL) != 0)
+ {
+ abort();
+ }
+ return (objc_mutex_t)p;
+}
+
+int
+objc_mutex_deallocate(objc_mutex_t mutex)
+{
+ int ret;
+ pthread_mutex_t *p = (pthread_mutex_t *)mutex;
+ ret = pthread_mutex_destroy(p);
+ if (ret == 0)
+ {
+ free(p);
+ }
+ return ret;
+}
+
+int
+objc_mutex_lock(objc_mutex_t mutex)
+{
+ pthread_mutex_t *p = (pthread_mutex_t *)mutex;
+ return pthread_mutex_lock(p);
+}
+
+int
+objc_mutex_unlock (objc_mutex_t mutex)
+{
+ pthread_mutex_t *p = (pthread_mutex_t *)mutex;
+ return pthread_mutex_unlock(p);
+}
+
+int
+objc_mutex_trylock (objc_mutex_t mutex)
+{
+ pthread_mutex_t *p = (pthread_mutex_t *)mutex;
+ return pthread_mutex_trylock(p);
+}
+
Index: Source/Additions/GSObjCRuntime.m
===================================================================
RCS file: /cvsroot/gnustep/gnustep/core/base/Source/Additions/GSObjCRuntime.m,v
retrieving revision 1.32
diff -u -r1.32 GSObjCRuntime.m
--- Source/Additions/GSObjCRuntime.m 15 Jan 2004 04:07:08 -0000 1.32
+++ Source/Additions/GSObjCRuntime.m 5 May 2004 17:50:04 -0000
@@ -59,6 +59,59 @@
@end
#endif
+static objc_mutex_t local_lock = NULL;
+
+/* This class it intended soley for thread safe / +load safe
+ initialization of the local lock.
+ It's a root class so it won't trigger the initialization
+ of any other class. */
+@interface _GSObjCRuntimeInitializer /* Root Class */
+{
+ Class isa;
+}
++ (Class)class;
+@end
+@implementation _GSObjCRuntimeInitializer
++ (void)initialize
+{
+ if (local_lock == NULL)
+ {
+ local_lock = objc_mutex_allocate();
+ }
+}
++ (Class)class
+{
+ return self;
+}
+@end
+
+void
+GSAllocateMutexAt(objc_mutex_t *request)
+{
+ if (request == NULL)
+ {
+ /* This could be called very early in process
+ initialization so many things may not have
+ been setup correctly yet. */
+ fprintf(stderr,
+ "Error: GSAllocateMutexAt() called with NULL pointer.\n");
+ abort();
+ }
+
+ if (local_lock == NULL)
+ {
+ /* Initialize in a thread safe way. */
+ [_GSObjCRuntimeInitializer class];
+ }
+
+ objc_mutex_lock(local_lock);
+ if (*request == NULL)
+ {
+ *request = objc_mutex_allocate();
+ }
+ objc_mutex_unlock(local_lock);
+}
+
/** Deprecated ... use GSObjCFindVariable() */
BOOL
GSFindInstanceVariable(id obj, const char *name,
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [RFC/base] GSAllocateMutexAt(),
David Ayers <=