2016-02-16 4 views
2

Я читаю код objc от https://github.com/opensource-apple/objc4.Почему weak_table_t является членом SideTable во время выполнения Objective-C?

В коде есть структура SideTable, которая содержит счетчик ссылок соответствующего объекта и weak_table_t.

struct SideTable { 
    spinlock_t slock; 
    RefcountMap refcnts; 
    weak_table_t weak_table; 

    SideTable() { 
     memset(&weak_table, 0, sizeof(weak_table)); 
    } 

    ~SideTable() { 
     _objc_fatal("Do not delete SideTable."); 
    } 

    void lock() { slock.lock(); } 
    void unlock() { slock.unlock(); } 
    bool trylock() { return slock.trylock(); } 

    // Address-ordered lock discipline for a pair of side tables. 

    template<bool HaveOld, bool HaveNew> 
    static void lockTwo(SideTable *lock1, SideTable *lock2); 
    template<bool HaveOld, bool HaveNew> 
    static void unlockTwo(SideTable *lock1, SideTable *lock2); 
}; 

А SideTable объекта может быть получен с помощью SideTables() [OBJ] как SideTable каждого объекта хранится в StripedMap, которая на самом деле массив с использованием хэш-значение адреса объекта в качестве индекса ,

Но в соответствии с кодом weak_entry_for_referent среда выполнения получает weak_entry_t референта, проверяя weak_table-> weak_entries [index] .referent.

static weak_entry_t * 
weak_entry_for_referent(weak_table_t *weak_table, objc_object *referent) 
{ 
    assert(referent); 

    weak_entry_t *weak_entries = weak_table->weak_entries; 

    if (!weak_entries) return nil; 

    size_t index = hash_pointer(referent) & weak_table->mask; 
    size_t hash_displacement = 0; 
    while (weak_table->weak_entries[index].referent != referent) { 
     index = (index+1) & weak_table->mask; 
     hash_displacement++; 
     if (hash_displacement > weak_table->max_hash_displacement) { 
      return nil; 
     } 
    } 

    return &weak_table->weak_entries[index]; 
} 

Это означает, что weak_table содержит больше, чем слабые записи для одного объекта. Тогда почему weak_table_t является членом SideTable вместо глобальных данных?

Поскольку я не могу найти код, который действительно инициализирует SideTable объекта (storeStrong просто использует SideTable, не инициализируя его сначала) и weak_table, я не могу понять, как все работает в фоновом режиме.

Может ли кто-нибудь дать мне подсказку?

+0

Я не понимаю вашего заключения. Слабая таблица содержит список всех других объектов, ссылающихся на один конкретный объект в учетной записи. Функция возвращает запись для конкретного объекта в учетной записи и реферер (референт). Поэтому каждый объект имеет (локальную) таблицу для своих источников. –

+0

По моему мнению, weak_entry_for_referent вернет запись в weak_table-> weak_entries для референта (объект ссылается на слабые ссылки). Если weak_table или weak_table-> weak_entries в SideTable содержит только слабые источники для себя, почему мы должны проверять, является ли референт референтом, которого мы ищем, while (weak_table-> weak_entries [index] .referent! = Referent) " ? –

+0

Потому что он принимает ссылку на объект ('objc_object') и возвращает всю запись (' weak_entry_t'). Таким образом, вы можете получить запись для справки. 'weak_entry_t' содержит больше информации, чем' id' (aka 'objc_object'). –

ответ

0

Единственная разумная причина, которую я могу понять:

SideTableBuf для всех SideTable экземпляров на самом деле массив ведро. В одном ковше могут быть помещены разные объекты. Таким образом, один SideTable может служить для разных указателей в соответствии с алгоритмом хеширования. И тогда, weak_table фактически содержит weak_entry_t для разных референтов. Вот почему нам нужно проверить референт:

while (weak_table->weak_entries[index].referent != referent) 

И weak_table служит только для текущего SideTable, поэтому он не может быть глобальными данными.

Смежные вопросы