mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 08:26:27 +00:00
Merge pull request #84 from gnustep/weak-table
Rework some of the weak handling for NS{Map,Hash}Table. @Richard, feel free to revert this and to provide a cleaner solution. I am no expert here, but part of this code looks correct and part just like a workaround for a deeper problem.
This commit is contained in:
commit
01e7ea8372
3 changed files with 37 additions and 35 deletions
|
@ -450,7 +450,7 @@ GSIMapAddNodeToMap(GSIMapTable map, GSIMapNode node)
|
|||
{
|
||||
GSIMapBucket bucket;
|
||||
|
||||
bucket = GSIMapBucketForKey(map, node->key);
|
||||
bucket = GSIMapBucketForKey(map, GSI_MAP_READ_KEY(map, &node->key));
|
||||
GSIMapAddNodeToBucket(bucket, node);
|
||||
map->nodeCount++;
|
||||
}
|
||||
|
@ -543,7 +543,7 @@ GSIMapRemangleBuckets(GSIMapTable map,
|
|||
GSIMapBucket bkt;
|
||||
|
||||
GSIMapRemoveNodeFromBucket(old_buckets, node);
|
||||
bkt = GSIMapPickBucket(GSI_MAP_HASH(map, node->key),
|
||||
bkt = GSIMapPickBucket(GSI_MAP_HASH(map, GSI_MAP_READ_KEY(map, &node->key)),
|
||||
new_buckets, new_bucketCount);
|
||||
GSIMapAddNodeToBucket(bkt, node);
|
||||
}
|
||||
|
@ -561,7 +561,7 @@ GSIMapRemangleBuckets(GSIMapTable map,
|
|||
GSIMapBucket bkt;
|
||||
|
||||
GSIMapRemoveNodeFromBucket(old_buckets, node);
|
||||
bkt = GSIMapPickBucket(GSI_MAP_HASH(map, node->key),
|
||||
bkt = GSIMapPickBucket(GSI_MAP_HASH(map, GSI_MAP_READ_KEY(map, &node->key)),
|
||||
new_buckets, new_bucketCount);
|
||||
GSIMapAddNodeToBucket(bkt, node);
|
||||
}
|
||||
|
|
|
@ -75,7 +75,9 @@ typedef GSIMapNode_t *GSIMapNode;
|
|||
#define GSI_MAP_KTYPES GSUNION_PTR | GSUNION_OBJ
|
||||
#define GSI_MAP_TABLE_T NSConcreteHashTable
|
||||
#define GSI_MAP_TABLE_S instanceSize
|
||||
|
||||
|
||||
#define IS_WEAK(M) \
|
||||
M->cb.pf.options & (NSPointerFunctionsZeroingWeakMemory | NSPointerFunctionsWeakMemory)
|
||||
#define GSI_MAP_HASH(M, X)\
|
||||
(M->legacy ? M->cb.old.hash(M, X.ptr) \
|
||||
: pointerFunctionsHash(&M->cb.pf, X.ptr))
|
||||
|
@ -84,13 +86,13 @@ typedef GSIMapNode_t *GSIMapNode;
|
|||
: pointerFunctionsEqual(&M->cb.pf, X.ptr, Y.ptr))
|
||||
#define GSI_MAP_RELEASE_KEY(M, X)\
|
||||
(M->legacy ? M->cb.old.release(M, X.ptr) \
|
||||
: pointerFunctionsRelinquish(&M->cb.pf, &X.ptr))
|
||||
: IS_WEAK(M) ? nil : pointerFunctionsRelinquish(&M->cb.pf, &X.ptr))
|
||||
#define GSI_MAP_RETAIN_KEY(M, X)\
|
||||
(M->legacy ? M->cb.old.retain(M, X.ptr) \
|
||||
: pointerFunctionsAcquire(&M->cb.pf, &X.ptr, X.ptr))
|
||||
: IS_WEAK(M) ? nil : pointerFunctionsAcquire(&M->cb.pf, &X.ptr, X.ptr))
|
||||
#define GSI_MAP_ZEROED(M)\
|
||||
(M->legacy ? 0 \
|
||||
: ((M->cb.pf.options & NSPointerFunctionsZeroingWeakMemory) ? YES : NO))
|
||||
: (IS_WEAK(M) ? YES : NO))
|
||||
|
||||
#define GSI_MAP_WRITE_KEY(M, addr, x) \
|
||||
if (M->legacy) \
|
||||
|
@ -100,9 +102,6 @@ typedef GSIMapNode_t *GSIMapNode;
|
|||
#define GSI_MAP_READ_KEY(M,addr) \
|
||||
(M->legacy ? *(addr) :\
|
||||
(typeof(*addr))pointerFunctionsRead(&M->cb.pf, (void**)addr))
|
||||
#define GSI_MAP_ZEROED(M)\
|
||||
(M->legacy ? 0 \
|
||||
: ((M->cb.pf.options & NSPointerFunctionsZeroingWeakMemory) ? YES : NO))
|
||||
|
||||
#define GSI_MAP_ENUMERATOR NSHashEnumerator
|
||||
|
||||
|
@ -628,7 +627,13 @@ NSNextHashEnumeratorItem(NSHashEnumerator *enumerator)
|
|||
}
|
||||
else
|
||||
{
|
||||
return n->key.ptr;
|
||||
NSConcreteHashTable *map = enumerator->map;
|
||||
GSIMapKey k = GSI_MAP_READ_KEY(map, &n->key);
|
||||
if (k.ptr == NULL)
|
||||
{
|
||||
return NSNextHashEnumeratorItem(enumerator);
|
||||
}
|
||||
return k.ptr;
|
||||
}
|
||||
}
|
||||
else if (enumerator->node != 0) // Got an enumerator object
|
||||
|
|
|
@ -81,6 +81,10 @@ typedef GSIMapNode_t *GSIMapNode;
|
|||
|
||||
#define GSI_MAP_KTYPES GSUNION_PTR | GSUNION_OBJ
|
||||
#define GSI_MAP_VTYPES GSUNION_PTR | GSUNION_OBJ
|
||||
#define IS_WEAK_KEY(M) \
|
||||
M->cb.pf.k.options & (NSPointerFunctionsZeroingWeakMemory | NSPointerFunctionsWeakMemory)
|
||||
#define IS_WEAK_VALUE(M) \
|
||||
M->cb.pf.v.options & (NSPointerFunctionsZeroingWeakMemory | NSPointerFunctionsWeakMemory)
|
||||
#define GSI_MAP_HASH(M, X)\
|
||||
(M->legacy ? M->cb.old.k.hash(M, X.ptr) \
|
||||
: pointerFunctionsHash(&M->cb.pf.k, X.ptr))
|
||||
|
@ -89,16 +93,16 @@ typedef GSIMapNode_t *GSIMapNode;
|
|||
: pointerFunctionsEqual(&M->cb.pf.k, X.ptr, Y.ptr))
|
||||
#define GSI_MAP_RELEASE_KEY(M, X)\
|
||||
(M->legacy ? M->cb.old.k.release(M, X.ptr) \
|
||||
: pointerFunctionsRelinquish(&M->cb.pf.k, &X.ptr))
|
||||
: IS_WEAK_KEY(M) ? nil : pointerFunctionsRelinquish(&M->cb.pf.k, &X.ptr))
|
||||
#define GSI_MAP_RETAIN_KEY(M, X)\
|
||||
(M->legacy ? M->cb.old.k.retain(M, X.ptr) \
|
||||
: pointerFunctionsAcquire(&M->cb.pf.k, &X.ptr, X.ptr))
|
||||
: IS_WEAK_KEY(M) ? nil : pointerFunctionsAcquire(&M->cb.pf.k, &X.ptr, X.ptr))
|
||||
#define GSI_MAP_RELEASE_VAL(M, X)\
|
||||
(M->legacy ? M->cb.old.v.release(M, X.ptr) \
|
||||
: pointerFunctionsRelinquish(&M->cb.pf.v, &X.ptr))
|
||||
: IS_WEAK_VALUE(M) ? nil : pointerFunctionsRelinquish(&M->cb.pf.v, &X.ptr))
|
||||
#define GSI_MAP_RETAIN_VAL(M, X)\
|
||||
(M->legacy ? M->cb.old.v.retain(M, X.ptr) \
|
||||
: pointerFunctionsAcquire(&M->cb.pf.v, &X.ptr, X.ptr))
|
||||
: IS_WEAK_VALUE(M) ? nil : pointerFunctionsAcquire(&M->cb.pf.v, &X.ptr, X.ptr))
|
||||
|
||||
/* 2013-05-25 Here are the macros originally added for GC/ARC ...
|
||||
* but they caused map table entries to be doubly retained :-(
|
||||
|
@ -120,12 +124,12 @@ typedef GSIMapNode_t *GSIMapNode;
|
|||
if (M->legacy) \
|
||||
*(addr) = x;\
|
||||
else\
|
||||
*(id*)(addr) = (x).obj;
|
||||
(IS_WEAK_KEY(M) ? pointerFunctionsAssign(&M->cb.pf.k, (void**)addr, (x).obj) : (*(id*)(addr) = (x).obj));
|
||||
#define GSI_MAP_WRITE_VAL(M, addr, x) \
|
||||
if (M->legacy) \
|
||||
*(addr) = x;\
|
||||
else\
|
||||
*(id*)(addr) = (x).obj;
|
||||
(IS_WEAK_VALUE(M) ? pointerFunctionsAssign(&M->cb.pf.v, (void**)addr, (x).obj) : (*(id*)(addr) = (x).obj));
|
||||
#define GSI_MAP_READ_KEY(M,addr) \
|
||||
(M->legacy ? *(addr)\
|
||||
: (typeof(*addr))pointerFunctionsRead(&M->cb.pf.k, (void**)addr))
|
||||
|
@ -134,8 +138,7 @@ typedef GSIMapNode_t *GSIMapNode;
|
|||
: (typeof(*addr))pointerFunctionsRead(&M->cb.pf.v, (void**)addr))
|
||||
#define GSI_MAP_ZEROED(M)\
|
||||
(M->legacy ? 0\
|
||||
: (((M->cb.pf.k.options | M->cb.pf.v.options)\
|
||||
& NSPointerFunctionsZeroingWeakMemory) ? YES : NO))
|
||||
: (IS_WEAK_KEY(M) || IS_WEAK_VALUE(M)) ? YES : NO)
|
||||
|
||||
#define GSI_MAP_ENUMERATOR NSMapEnumerator
|
||||
|
||||
|
@ -879,23 +882,17 @@ NSNextMapEnumeratorPair(NSMapEnumerator *enumerator,
|
|||
}
|
||||
else
|
||||
{
|
||||
if (key != 0)
|
||||
NSConcreteMapTable *map = enumerator->map;
|
||||
GSIMapKey k = GSI_MAP_READ_KEY(map, &n->key);
|
||||
GSIMapVal v = GSI_MAP_READ_VALUE(map, &n->value);
|
||||
if (k.ptr == NULL || v.ptr == NULL)
|
||||
{
|
||||
*key = n->key.ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
NSWarnFLog(@"Null key return address");
|
||||
return NSNextMapEnumeratorPair(enumerator, key, value);
|
||||
}
|
||||
|
||||
if (value != 0)
|
||||
{
|
||||
*value = n->value.ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
NSWarnFLog(@"Null value return address");
|
||||
}
|
||||
*key = k.ptr;
|
||||
*value = v.ptr;
|
||||
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
@ -1332,7 +1329,7 @@ const NSMapTableValueCallBacks NSOwnedPointerMapValueCallBacks =
|
|||
|
||||
if (node)
|
||||
{
|
||||
return node->value.obj;
|
||||
return GSI_MAP_READ_VALUE(self, &node->value).obj;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
|
@ -1384,7 +1381,7 @@ const NSMapTableValueCallBacks NSOwnedPointerMapValueCallBacks =
|
|||
node = GSIMapNodeForKey(self, (GSIMapKey)aKey);
|
||||
if (node)
|
||||
{
|
||||
if (node->value.obj != anObject)
|
||||
if (GSI_MAP_READ_VALUE(self, &node->value).obj != anObject)
|
||||
{
|
||||
GSI_MAP_RELEASE_VAL(self, node->value);
|
||||
node->value.obj = anObject;
|
||||
|
|
Loading…
Reference in a new issue