2013-02-15 10 views
5

La mia domanda è come implementano le versioni correnti di Foundation (o della libreria di runtime Objective-C, poiché ciò sembra essere lì) conteggio trattenuto per oggetti derivati ​​NSObject? Come ho potuto vedere a NSObject.mm, non esiste alcun ivar chiamato retain count nel corpo dell'interfaccia di NSObject. Invece, sembra esserci un tipo di tabella o mappa che contiene contatori di riferimenti per ciascun oggetto. Ma se il conteggio dei ritardi è fatto con una mappa, non sono le operazioni retain e release troppo costose con questo tipo di implementazione (poiché, in questo caso, è necessario bloccare e sbloccare i mutex, cercare la mappa per trovare l'oggetto giusto, oltre il fatto che, in un ambiente multithread, solo un oggetto può essere mantenuto/rilasciato alla volta)?Come viene implementato il conto di mantenimento in NSObject?

Non ho trovato tutto ciò che riguarda l'impostazione del contatore mantenere a 1 quando l'assegnazione di un nuovo oggetto, né in _objc_rootAllocWithZone a NSObject.mm (che sembra essere la funzione che viene chiamata da [NSObject alloc]), né in _class_createInstanceFromZone a objc-runtime-new.mm (che ottiene chiamato in seguito da _objc_rootAllocWithZone).

+2

- (NSUInteger) retainCount {return rand()}; – CodaFi

+0

Oh buon dio, ho smarrito il termine: ... Non dormirò stanotte. – CodaFi

risposta

10

Il numero di ritenzione per NSObject viene effettivamente mantenuto in una mappa globale. IIRC utilizza effettivamente una serie di mappe partizionate, presumibilmente basate sull'indirizzo dell'oggetto, per ridurre la contesa del blocco, ma i dettagli reali dell'implementazione sono proprio questo, i dettagli dell'implementazione.

In ogni caso, non è possibile trovare il codice che imposta il conteggio di ritenzione su 1 perché non ce n'è. Gli oggetti con un numero di ritenzione pari a 1 non vengono inseriti nella mappa. Gli oggetti immettono solo la mappa del conteggio dei ritardi quando sono retain oltre l'iniziale 1. Si tratta di un'ottimizzazione che accelera il caso comune di oggetti che non hanno mai il conteggio dei ritardi oltre 1.

+1

... con il caso speciale di puntatori contrassegnati che non dispongono di un conteggio di mantenimento. I dati stessi sono codificati all'interno del puntatore in modo da passarli tecnicamente per valore piuttosto che per riferimento (perché il riferimento è il valore e non c'è nulla di reale dietro il riferimento). – Tommy

+0

Vero. E naturalmente ogni classe che sovrascrive '-retain' e' -release' è libera di avere una propria implementazione del conteggio dei ritiri. Ci sono un certo numero di classi che incorporano il conteggio dei ritiri come un ivar, perché preferiscono velocizzare 'retain' e' release' a scapito di avere un oggetto più grande. –

+0

Ok. Ma perché non usano un ivar come contatore, il che ridurrebbe il costo del mantenimento/rilascio? Sai se c'è qualche motivo particolare per usare le mappe? – LuisABOL