Reputation: 3993
The deployment target is 10.6, therefore manual memory management is required. The collection should take care of retaining/releasing GCD objects.
I believe custom callbacks for CFArray of CFDictionary would help, however I'm looking for a drop-in, well-tested solution
Upvotes: 0
Views: 374
Reputation: 27994
The callbacks and collection creation are straightforward:
static const void * dispatchObjectRetainCallBack(CFAllocatorRef allocator, const void *value)
{
if (value) {
dispatch_retain(value);
}
return value;
}
static void dispatchObjectReleaseCallBack(CFAllocatorRef allocator, const void *value)
{
if (value) {
dispatch_release(value);
}
}
CFMutableArrayRef CreateDispatchHoldingArray()
{
CFArrayCallBacks callBacks = {
0,
dispatchObjectRetainCallBack,
dispatchObjectReleaseCallBack,
NULL,
NULL
};
return CFArrayCreateMutable(kCFAllocatorDefault, 0, &callBacks);
}
CFMutableDictionaryRef CreateDispatchHoldingDictionary()
{
CFDictionaryValueCallBacks valueCallBacks = {
0,
dispatchObjectRetainCallBack,
dispatchObjectReleaseCallBack,
NULL,
NULL
};
return CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &valueCallBacks);
}
The slightly tricky part is getting the dispatch_object_t
s in and out of the collections. You cannot simply cast a variable of type dispatch_object_t
to a void *
, because dispatch_object_t
is a typedef of a union. The compiler gives an error:
Operand of type 'dispatch_object_t' where arithmetic or pointer type is required
You have to go through one of the union types inside the dispatch_object_t
, like so:
void AddDispatchObjectToArray(CFMutableArrayRef array, dispatch_object_t obj)
{
void* voidPtrObj = obj._do;
CFArrayAppendValue(array, voidPtrObj);
}
dispatch_object_t GetDispatchObjectAtIndex(CFMutableArrayRef array, CFIndex index)
{
dispatch_object_t result;
result._do = (struct dispatch_object_s *)CFArrayGetValueAtIndex(array, index);
return result;
}
Upvotes: 2