2

I want to know how the getter and setter for an Objective-C property are implemented as part of learning the concept of memory management.

I have not been able to find an actual representation other than "nonatomic" and "atomic".

What does the actual code look like for getters and setters with the different property attributes, such as strong/weak, copy/assign, and __unsafe_unretained?

jscs
  • 63,694
  • 13
  • 151
  • 195
NSUser
  • 1,233
  • 9
  • 15
  • 1
    Non-ARC in title and strong/weak in question is mutually-exclusive. – Droppy Oct 12 '16 at 09:44
  • https://github.com/opensource-apple/objc4/blob/cd5e62a5597ea7a31dccef089317abb3a661c154/runtime/objc-accessors.mm – Bryan Chen Oct 12 '16 at 09:46
  • @Droppy I am just curious about their inner implementation. regardless of ARC or MRC . – NSUser Oct 12 '16 at 09:48
  • Well you need to understand that with ARC the compiler does the heavy lifting behind the scenes and no body really cares to look at it closely (apart from the devs and the seriously curious). There are many examples of non-ARC versions however, including many on this site. – Droppy Oct 12 '16 at 09:50
  • @Droppy yes you are right. I have just saw the setter of strong - `-(void)setName:(NSString *)name{ [name retain]; [_name release]; _name = name; }` their are so many concepts in this like why `[name retain]` is the first line. So I just wanted to see actual Implementation. I never worked on MRC. that's why some time i feel some issues while understanding this. that's why I now understanding each thing throughly. – NSUser Oct 12 '16 at 09:52
  • Do you want the actual synthesized definitions, or what they _would_ look like if you implemented them by hand? – jscs Oct 12 '16 at 18:33

1 Answers1

0

You can check the source code at the objc4 github repo

getter: https://github.com/opensource-apple/objc4/blob/cd5e62a5597ea7a31dccef089317abb3a661c154/runtime/objc-accessors.mm#L48

id objc_getProperty_non_gc(id self, SEL _cmd, ptrdiff_t offset, BOOL atomic) {
    if (offset == 0) {
        return object_getClass(self);
    }

    // Retain release world
    id *slot = (id*) ((char*)self + offset);
    if (!atomic) return *slot;

    // Atomic retain release world
    spinlock_t& slotlock = PropertyLocks[slot];
    slotlock.lock();
    id value = objc_retain(*slot);
    slotlock.unlock();

    // for performance, we (safely) issue the autorelease OUTSIDE of the spinlock.
    return objc_autoreleaseReturnValue(value);
}

setter: https://github.com/opensource-apple/objc4/blob/cd5e62a5597ea7a31dccef089317abb3a661c154/runtime/objc-accessors.mm#L70

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);
}

load weak variable: https://github.com/opensource-apple/objc4/blob/cd5e62a5597ea7a31dccef089317abb3a661c154/runtime/NSObject.mm#L444

id
objc_loadWeakRetained(id *location)
{
    id result;

    SideTable *table;

 retry:
    result = *location;
    if (!result) return nil;

    table = &SideTables()[result];

    table->lock();
    if (*location != result) {
        table->unlock();
        goto retry;
    }

    result = weak_read_no_lock(&table->weak_table, location);

    table->unlock();
    return result;
}

I don't think there is any code for unsafe_retained. Compiler can just simply assign the pointer without anything else.

Bryan Chen
  • 45,816
  • 18
  • 112
  • 143