1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| static inline void reallySetProperty(id self, SEL _cmd, id newValue, ptrdiff_t offset, bool atomic, bool copy, bool mutableCopy) { if (offset == 0) { object_setClass(self, newValue); return; }
id oldValue; id *slot = (id*) ((char*)self + offset);
if (copy) { newValue = [newValue copyWithZone:nil]; } else if (mutableCopy) { newValue = [newValue mutableCopyWithZone:nil]; } else { if (*slot == newValue) return; newValue = objc_retain(newValue); }
if (!atomic) { oldValue = *slot; *slot = newValue; } else { spinlock_t& slotlock = PropertyLocks[slot]; slotlock.lock(); oldValue = *slot; *slot = newValue; slotlock.unlock(); }
objc_release(oldValue); }
void objc_setProperty_atomic(id self, SEL _cmd, id newValue, ptrdiff_t offset) { reallySetProperty(self, _cmd, newValue, offset, true, false, false); }
void objc_setProperty_nonatomic(id self, SEL _cmd, id newValue, ptrdiff_t offset) { reallySetProperty(self, _cmd, newValue, offset, false, false, false); }
void objc_setProperty_atomic_copy(id self, SEL _cmd, id newValue, ptrdiff_t offset) { reallySetProperty(self, _cmd, newValue, offset, true, true, false); }
void objc_setProperty_nonatomic_copy(id self, SEL _cmd, id newValue, ptrdiff_t offset) { reallySetProperty(self, _cmd, newValue, offset, false, true, false); }
|