Skip to content

Commit 1a0f5ac

Browse files
authored
Retain and autorelease associated objects properly (#331)
Apple's objc4 runtime expands the policy bits into the following subcategories: ``` enum { OBJC_ASSOCIATION_SETTER_ASSIGN = 0, OBJC_ASSOCIATION_SETTER_RETAIN = 1, OBJC_ASSOCIATION_SETTER_COPY = 3, OBJC_ASSOCIATION_GETTER_READ = (0 << 8), OBJC_ASSOCIATION_GETTER_RETAIN = (1 << 8), OBJC_ASSOCIATION_GETTER_AUTORELEASE = (2 << 8) }; ``` where OBJC_ASSOCIATION_ASSIGN = 0 OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1 OBJC_ASSOCIATION_COPY_NONATOMIC = 3 OBJC_ASSOCIATION_RETAIN = 01401 OBJC_ASSOCIATION_COPY = 01403 This means that on OBJC_ASSOCIATION_{RETAIN, COPY} and the NONATOMIC counterpart, we need to retain and autorelease the associated object before returning it in objc_getAssociatedObject. * Cirrus: Bump freebsd image versions
1 parent bcbeacd commit 1a0f5ac

File tree

3 files changed

+16
-3
lines changed

3 files changed

+16
-3
lines changed

.cirrus.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
libcxxrt_freebsd_task:
22
matrix:
33
- freebsd_instance:
4-
image_family: freebsd-13-3
4+
image_family: freebsd-13-5
55
- freebsd_instance:
66
image_family: freebsd-15-0-snap
77
- freebsd_instance:
8-
image_family: freebsd-14-0
8+
image_family: freebsd-14-2
99

1010
install_script: pkg install -y cmake ninja git
1111

@@ -31,7 +31,7 @@ libcxxrt_freebsd_task:
3131

3232
libcxxrt_master_task:
3333
freebsd_instance:
34-
image_family: freebsd-14-0
34+
image_family: freebsd-14-2
3535
install_script: pkg install -y cmake ninja git
3636

3737
clone_script: |

Test/AssociatedObject.m

+3
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,11 @@ int main(void)
4141

4242
object = [Associated new];
4343
holder = [Test new];
44+
size_t rc = object_getRetainCount_np(object);
4445
for (uintptr_t i = 1; i <= 20; ++i)
4546
{
4647
objc_setAssociatedObject(holder, (void*)i, object, OBJC_ASSOCIATION_RETAIN);
48+
assert(rc + i == object_getRetainCount_np(object));
4749
}
4850
int lost = 0;
4951
for (uintptr_t i = 1; i <= 20; ++i)
@@ -53,6 +55,7 @@ int main(void)
5355
fprintf(stderr, "lost object %" PRIuPTR "\n", i);
5456
++lost;
5557
}
58+
assert(rc + 20 + i == object_getRetainCount_np(object));
5659
}
5760
[holder release];
5861
[object release];

associate.m

+10
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,12 @@ id objc_getAssociatedObject(id object, const void *key)
341341
struct reference *r = findReference(list, key);
342342
if (NULL != r)
343343
{
344+
// Check if the policy is OBJC_ASSOCIATION_{RETAIN, COPY} or OBJC_ASSOCIATION_{RETAIN, COPY}_NONATOMIC (LSB set)
345+
// Apple's objc4 retains and autoreleases the object under these policies
346+
if (r->policy & OBJC_ASSOCIATION_RETAIN_NONATOMIC)
347+
{
348+
objc_retainAutorelease(r->object);
349+
}
344350
return r->object;
345351
}
346352
if (class_isMetaClass(object->isa))
@@ -364,6 +370,10 @@ id objc_getAssociatedObject(id object, const void *key)
364370
struct reference *r = findReference(list, key);
365371
if (NULL != r)
366372
{
373+
if (r->policy & OBJC_ASSOCIATION_RETAIN_NONATOMIC)
374+
{
375+
objc_retainAutorelease(r->object);
376+
}
367377
return r->object;
368378
}
369379
}

0 commit comments

Comments
 (0)