대상이 회수될 때 Weak 포인터가 자동으로 nil로 설정되는 실현 원리

1795 단어

1. 앞말


우리는 Weak 포인터가 인용 대상의 계수를 증가시키지 않고 인용 대상이 회수될 때 자동으로 nil로 설정되는 것을 알고 있다.일반적으로 순환 인용 문제를 해결하는 데 쓰인다.그렇다면 자동nil 내부는 어떻게 이루어졌을까?

2. 내부 구현 - Weak 표


런타임은 대상을 가리키는 모든 위크 포인터를 저장하는 데 사용되는 위크 테이블을 유지합니다.Weak표는 사실 해시표입니다. Key는 대상의 주소를 가리키고,Value는 Weak포인터의 주소 (이 주소의 값은 대상의 주소를 가리킨다) 의 그룹입니다.
대상이 회수될 때 층층이 호출되면 다음 방법으로 모든 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--; } }

간단하게 말하자면, 이 방법은 우선 대상 주소에 따라 위크 포인터 주소의 그룹을 얻은 다음에 이 그룹을 옮겨다니며 그 중의 데이터를 nil로 설정하고, 마지막으로 이entry를 위크 테이블에서 삭제한다.
대상 회수 시 위크 바늘을 어떻게 설정하는지nil만 간단히 말하고, 위크 바늘을 위크 테이블에 어떻게 등록하는지, 어떻게 유지하는지는objc-위크를 참고할 수 있다.m의 다른 원본 코드입니다.이를 통해 알 수 있듯이 Weak 포인터의 사용은Hash표의 추가 삭제와 수정과 관련되어 일정한 성능 비용이 든다.

좋은 웹페이지 즐겨찾기