* Headers/Additions/GNUstepBase/GSObjCRuntime.h

* Source/Additions//GSObjCRuntime.m
	(GSProtocolFromName): New function.
	(GSRegisterProtocol): Ditto.
	(gs_string_hash): New internal function.
	(gs_find_protocol_named_in_protocol_list): Ditto.
	(gs_find_protocol_named): Ditto.
	(gs_init_protocol_lock): Ditto.


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@19274 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
David Ayers 2004-05-09 19:29:16 +00:00
parent 39434f63e6
commit 3423dcf309
3 changed files with 216 additions and 2 deletions

View file

@ -1,10 +1,22 @@
2004-05-09 David Ayers <d.ayers@inode.at>
* Headers/Additions/GNUstepBase/GSObjCRuntime.h
* Source/Additions//GSObjCRuntime.m
(GSProtocolFromName): New function.
(GSRegisterProtocol): Ditto.
(gs_string_hash): New internal function.
(gs_find_protocol_named_in_protocol_list): Ditto.
(gs_find_protocol_named): Ditto.
(gs_init_protocol_lock): Ditto.
2004-05-07 23:48 Alexander Malmberg <alexander@malmberg.org>
* Resources/Languages/Hungarian: Add a missing ".
2004-05-06 David Ayers <d.ayers@inode.at>
* Headers/Additions/GNUstepBase/GSObjCRuntime.h/m:
* Headers/Additions/GNUstepBase/GSObjCRuntime.h:
* Source/Additions//GSObjCRuntime.m
(GSClassList): New function.
2004-05-07 Richard Frith-Macdonald <rfm@gnu.org>
@ -14,7 +26,8 @@
2004-05-06 David Ayers <d.ayers@inode.at>
* Headers/Additions/GNUstepBase/GSObjCRuntime.h/m
* Headers/Additions/GNUstepBase/GSObjCRuntime.h
* Source/Additions//GSObjCRuntime.m
(GSAllocateMutexAt): New function.
(_GSObjCRuntimeInitializer): Define local support class.

View file

@ -337,6 +337,24 @@ GSTypesFromSelector(SEL this)
return sel_get_type(this);
}
/**
* Returns a protocol object with the corresponding name.
* This function searches the registered classes for any protocol
* with the supplied name. If one is found, it is cached in
* for future requests. If efficiency is a factor then use
* GSRegisterProtocol() to insert a protocol explicitly into the cache
* used by this function. If no protocol is found this function returns
* nil.
*/
GS_EXPORT Protocol *
GSProtocolFromName(const char *name);
/**
* Registers proto in the cache used by GSProtocolFromName().
*/
GS_EXPORT void
GSRegisterProtocol(Protocol *proto);
/*
* Unfortunately the definition of the symbol 'Method' "IVar(_t)"

View file

@ -49,6 +49,9 @@
#include "GNUstepBase/GSObjCRuntime.h"
#include "GNUstepBase/GNUstep.h"
#include "GNUstepBase/GSCategories.h"
#include <objc/Protocol.h>
#include <string.h>
@class NSNull;
@ -848,6 +851,186 @@ GSObjCGetInstanceVariableDefinition(Class class, NSString *name)
return GSCGetInstanceVariableDefinition(class, [name cString]);
}
typedef struct {
@defs(Protocol)
} *pcl;
GS_STATIC_INLINE unsigned int
gs_string_hash(const char *s)
{
unsigned int val = 0;
while (*s != 0)
{
val = (val << 5) + val + *s++;
}
return val;
}
GS_STATIC_INLINE pcl
gs_find_protocol_named_in_protocol_list(const char *name,
struct objc_protocol_list *pcllist)
{
pcl p = NULL;
size_t i;
while (pcllist != NULL)
{
for (i=0; i<pcllist->count; i++)
{
p = (pcl)pcllist->list[i];
if (strcmp(p->protocol_name, name) == 0)
{
return p;
}
}
pcllist = pcllist->next;
}
return NULL;
}
GS_STATIC_INLINE pcl
gs_find_protocol_named(const char *name)
{
pcl p = NULL;
Class cls;
#ifdef NeXT_RUNTIME
Class *clsList, *clsListStart;
unsigned int num;
/* Setting the clearCache flag is a noop for the Apple runtime. */
num = GSClassList(NULL, 0, NO);
clsList = objc_malloc(sizeof(Class) * (num + 1));
GSClassList(clsList, num, NO);
clsListStart = clsList;
while(p == NULL && (cls = *clsList++))
{
p = gs_find_protocol_named_in_protocol_list(name, cls->protocols);
}
objc_free(clsListStart);
#else
void *iterator = NULL;
while(p == NULL && (cls = objc_next_class(&iterator)))
{
p = gs_find_protocol_named_in_protocol_list(name, cls->protocols);
}
#endif
return p;
}
#define GSI_MAP_HAS_VALUE 1
#define GSI_MAP_RETAIN_KEY(M, X)
#define GSI_MAP_RETAIN_VAL(M, X)
#define GSI_MAP_RELEASE_KEY(M, X)
#define GSI_MAP_RELEASE_VAL(M, X)
#define GSI_MAP_HASH(M, X) (gs_string_hash(X.ptr))
#define GSI_MAP_EQUAL(M, X,Y) (strcmp(X.ptr, Y.ptr) == 0)
#define GSI_MAP_NOCLEAN 1
#define GSI_MAP_KTYPES GSUNION_PTR
#define GSI_MAP_VTYPES GSUNION_PTR
#include "GNUstepBase/GSIMap.h"
static GSIMapTable_t protocol_by_name;
static BOOL protocol_by_name_init = NO;
static volatile objc_mutex_t protocol_by_name_lock = NULL;
/* Not sure about the semantics of inlining
functions with static variables. */
static void
gs_init_protocol_lock(void)
{
if (protocol_by_name_lock == NULL)
{
GSAllocateMutexAt((void *)&protocol_by_name_lock);
objc_mutex_lock(protocol_by_name_lock);
if (protocol_by_name_init == NO)
{
GSIMapInitWithZoneAndCapacity (&protocol_by_name,
NSDefaultMallocZone(),
128);
protocol_by_name_init = YES;
}
objc_mutex_unlock(protocol_by_name_lock);
}
}
void
GSRegisterProtocol(Protocol *proto)
{
if (protocol_by_name_init == NO)
{
gs_init_protocol_lock();
}
if (proto != nil)
{
GSIMapNode node;
pcl p;
p = (pcl)proto;
objc_mutex_lock(protocol_by_name_lock);
node = GSIMapNodeForKey(&protocol_by_name,
(GSIMapKey) p->protocol_name);
if (node == 0)
{
GSIMapAddPairNoRetain(&protocol_by_name,
(GSIMapKey) (void *) p->protocol_name,
(GSIMapVal) (void *) p);
}
objc_mutex_unlock(protocol_by_name_lock);
}
}
Protocol *
GSProtocolFromName(const char *name)
{
GSIMapNode node;
pcl p;
if (protocol_by_name_init == NO)
{
gs_init_protocol_lock();
}
node = GSIMapNodeForKey(&protocol_by_name, (GSIMapKey) name);
if (node)
{
p = node->value.ptr;
}
else
{
objc_mutex_lock(protocol_by_name_lock);
node = GSIMapNodeForKey(&protocol_by_name, (GSIMapKey) name);
if (node)
{
p = node->value.ptr;
}
else
{
p = gs_find_protocol_named(name);
if (p)
{
/* Use the protocol's name to save us from allocating
a copy of the parameter 'name'. */
GSIMapAddPairNoRetain(&protocol_by_name,
(GSIMapKey) (void *) p->protocol_name,
(GSIMapVal) (void *) p);
}
}
objc_mutex_unlock(protocol_by_name_lock);
}
return (Protocol *)p;
}
/**