[전재] 대상을 회수할 때 Weak 포인터가 자동으로 nil로 설정되는 실현 원리

1775 단어

전언


문장과 전재
Weak 포인터는 인용 대상의 계수를 증가시키지 않으며, 인용 대상이 회수될 때 자동으로 nil로 설정됩니다.일반적으로 순환 인용 문제를 해결하는 데 쓰인다.그렇다면 자동적으로nil 내부로 설정되는 것은 어떻게 이루어질까?

내부 구현 - Weak 표


4
  • 런타임은 어떤 대상을 가리키는 모든 위크 포인터를 저장하는 데 사용되는 위크 테이블을 유지했다.Weak표는 사실 해시표입니다. Key는 대상을 가리키는 주소이고,Value는 Weak포인터의 주소(이 주소의 값은 대상을 가리키는 주소)의 수조입니다

  • 4
  • 대상이 회수될 때 층층이 호출되면 다음 방법으로 모든 Weak 바늘의 값을 nil로 설정합니다.(구체적으로 objc-weak.m에 정의됨)
  • PRIVATE_EXTERN void 
    arr_clear_deallocating(weak_table_t *weak_table, id referent) {
        {
            weak_entry_t *entry = weak_entry_for_referent(weak_table, referent);
            if (entry == NULL) {
                /// XXX shouldn't happen, but does with mismatched CF/objc
                //printf("XXX no entry for clear deallocating %p
    ", referent); return; } // zero out references for (int i = 0; i < entry->referrers.num_allocated; ++i) { id *referrer = entry->referrers.refs[i].referrer; if (referrer) { if (*referrer == referent) { *referrer = nil; } else if (*referrer) { _objc_inform("__weak variable @ %p holds %p instead of %p
    ", referrer, *referrer, referent); } } } weak_entry_remove_no_lock(weak_table, entry); weak_table->num_weak_refs--; } }

    4
  • 간단하게 말하자면 이 방법은 먼저 대상 주소에 따라 위크 바늘 주소의 그룹을 얻은 다음에 이 그룹을 옮겨다니며 그 중의 데이터를 nil로 설정하고 마지막으로 이entry를 위크 테이블에서 삭제한다

  • 4
  • 여기서 대상 회수 시 Weak 지침을 어떻게 nil로 설정하는지, Weak 지침을 어떻게 Weak 표에 등록하는지, 어떻게 유지하는지에 대해objc-weak를 참고할 수 있습니다.m의 다른 원본 코드입니다.이를 통해 알 수 있듯이 Weak 포인터의 사용은Hash표의 추가 삭제와 수정과 관련되어 어느 정도의 성능 비용이 든다
  • 좋은 웹페이지 즐겨찾기