]> git.saurik.com Git - apple/objc4.git/blame - runtime/objc-weak.h
objc4-818.2.tar.gz
[apple/objc4.git] / runtime / objc-weak.h
CommitLineData
8972963c
A
1/*
2 * Copyright (c) 2010-2011 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
7257e56c
A
24#ifndef _OBJC_WEAK_H_
25#define _OBJC_WEAK_H_
26
8972963c 27#include <objc/objc.h>
cd5f04f5 28#include "objc-config.h"
8972963c
A
29
30__BEGIN_DECLS
31
32/*
33The weak table is a hash table governed by a single spin lock.
8070259c
A
34An allocated blob of memory, most often an object, but under GC any such
35allocation, may have its address stored in a __weak marked storage location
36through use of compiler generated write-barriers or hand coded uses of the
37register weak primitive. Associated with the registration can be a callback
38block for the case when one of the allocated chunks of memory is reclaimed.
39The table is hashed on the address of the allocated memory. When __weak
40marked memory changes its reference, we count on the fact that we can still
41see its previous reference.
42
43So, in the hash table, indexed by the weakly referenced item, is a list of
44all locations where this address is currently being stored.
8972963c 45
c1e772c4 46For ARC, we also keep track of whether an arbitrary object is being
8070259c
A
47deallocated by briefly placing it in the table just prior to invoking
48dealloc, and removing it via objc_clear_deallocating just prior to memory
49reclamation.
50
8972963c
A
51*/
52
c1e772c4
A
53// The address of a __weak variable.
54// These pointers are stored disguised so memory analysis tools
55// don't see lots of interior pointers from the weak table into objects.
56typedef DisguisedPtr<objc_object *> weak_referrer_t;
8972963c 57
7257e56c 58#if __LP64__
c1e772c4 59#define PTR_MINUS_2 62
7257e56c 60#else
c1e772c4 61#define PTR_MINUS_2 30
7257e56c 62#endif
8972963c 63
7257e56c
A
64/**
65 * The internal structure stored in the weak references table.
66 * It maintains and stores
67 * a hash set of weak references pointing to an object.
c1e772c4
A
68 * If out_of_line_ness != REFERRERS_OUT_OF_LINE then the set
69 * is instead a small inline array.
7257e56c
A
70 */
71#define WEAK_INLINE_COUNT 4
c1e772c4
A
72
73// out_of_line_ness field overlaps with the low two bits of inline_referrers[1].
74// inline_referrers[1] is a DisguisedPtr of a pointer-aligned address.
75// The low two bits of a pointer-aligned DisguisedPtr will always be 0b00
76// (disguised nil or 0x80..00) or 0b11 (any other address).
77// Therefore out_of_line_ness == 0b10 is used to mark the out-of-line state.
78#define REFERRERS_OUT_OF_LINE 2
79
8972963c 80struct weak_entry_t {
8070259c 81 DisguisedPtr<objc_object> referent;
7257e56c
A
82 union {
83 struct {
84 weak_referrer_t *referrers;
c1e772c4
A
85 uintptr_t out_of_line_ness : 2;
86 uintptr_t num_refs : PTR_MINUS_2;
7257e56c
A
87 uintptr_t mask;
88 uintptr_t max_hash_displacement;
89 };
90 struct {
c1e772c4 91 // out_of_line_ness field is low bits of inline_referrers[1]
7257e56c
A
92 weak_referrer_t inline_referrers[WEAK_INLINE_COUNT];
93 };
94 };
c1e772c4
A
95
96 bool out_of_line() {
97 return (out_of_line_ness == REFERRERS_OUT_OF_LINE);
98 }
99
100 weak_entry_t& operator=(const weak_entry_t& other) {
101 memcpy(this, &other, sizeof(other));
102 return *this;
103 }
104
105 weak_entry_t(objc_object *newReferent, objc_object **newReferrer)
106 : referent(newReferent)
107 {
108 inline_referrers[0] = newReferrer;
109 for (int i = 1; i < WEAK_INLINE_COUNT; i++) {
110 inline_referrers[i] = nil;
111 }
112 }
8972963c 113};
8972963c 114
7257e56c
A
115/**
116 * The global weak references table. Stores object ids as keys,
117 * and weak_entry_t structs as their values.
118 */
8972963c 119struct weak_table_t {
7257e56c
A
120 weak_entry_t *weak_entries;
121 size_t num_entries;
122 uintptr_t mask;
123 uintptr_t max_hash_displacement;
8972963c 124};
8972963c 125
34d5b5e8
A
126enum WeakRegisterDeallocatingOptions {
127 ReturnNilIfDeallocating,
128 CrashIfDeallocating,
129 DontCheckDeallocating
130};
131
7257e56c 132/// Adds an (object, weak pointer) pair to the weak table.
31875a97 133id weak_register_no_lock(weak_table_t *weak_table, id referent,
34d5b5e8 134 id *referrer, WeakRegisterDeallocatingOptions deallocatingOptions);
7257e56c
A
135
136/// Removes an (object, weak pointer) pair from the weak table.
137void weak_unregister_no_lock(weak_table_t *weak_table, id referent, id *referrer);
8972963c 138
31875a97 139#if DEBUG
8070259c
A
140/// Returns true if an object is weakly referenced somewhere.
141bool weak_is_registered_no_lock(weak_table_t *weak_table, id referent);
142#endif
143
7257e56c
A
144/// Called on object destruction. Sets all remaining weak pointers to nil.
145void weak_clear_no_lock(weak_table_t *weak_table, id referent);
8972963c
A
146
147__END_DECLS
7257e56c
A
148
149#endif /* _OBJC_WEAK_H_ */