mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 16:33:29 +00:00
* 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:
parent
39434f63e6
commit
3423dcf309
3 changed files with 216 additions and 2 deletions
17
ChangeLog
17
ChangeLog
|
@ -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.
|
||||
|
||||
|
|
|
@ -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)"
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue