]>
Commit | Line | Data |
---|---|---|
d8f41ccd A |
1 | /* |
2 | * Copyright (c) 2000-2001,2004,2009 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 | ||
24 | ||
25 | // | |
26 | // structure - structural framework for securityd objects | |
27 | // | |
28 | #include "structure.h" | |
29 | ||
30 | ||
31 | // | |
32 | // NodeCore always has a destructor (because it's virtual), | |
33 | // but its dump support is conditionally included. | |
34 | // | |
35 | NodeCore::~NodeCore() | |
866f8763 | 36 | try { |
d8f41ccd A |
37 | #if defined(DEBUGDUMP) |
38 | StLock<Mutex> _(mCoreLock); | |
39 | mCoreNodes.erase(this); | |
40 | #endif //DEBUGDUMP | |
866f8763 A |
41 | } catch(...) { |
42 | return; | |
d8f41ccd A |
43 | } |
44 | ||
45 | ||
46 | // | |
47 | // Basic object mesh maintainance | |
48 | // | |
49 | void NodeCore::parent(NodeCore &p) | |
50 | { | |
51 | StLock<Mutex> _(*this); | |
52 | mParent = &p; | |
53 | } | |
54 | ||
55 | void NodeCore::referent(NodeCore &r) | |
56 | { | |
57 | StLock<Mutex> _(*this); | |
58 | assert(!mReferent); | |
59 | mReferent = &r; | |
60 | } | |
61 | ||
62 | void NodeCore::clearReferent() | |
63 | { | |
64 | StLock<Mutex> _(*this); | |
65 | if (mReferent) | |
66 | assert(!mReferent->hasReference(*this)); | |
67 | mReferent = NULL; | |
68 | } | |
69 | ||
70 | ||
71 | void NodeCore::addReference(NodeCore &p) | |
72 | { | |
73 | StLock<Mutex> _(*this); | |
74 | assert(p.mReferent == this); | |
75 | mReferences.insert(&p); | |
76 | } | |
77 | ||
78 | void NodeCore::removeReference(NodeCore &p) | |
79 | { | |
80 | StLock<Mutex> _(*this); | |
81 | assert(hasReference(p)); | |
82 | mReferences.erase(&p); | |
83 | } | |
84 | ||
85 | #if !defined(NDEBUG) | |
86 | ||
87 | bool NodeCore::hasReference(NodeCore &p) | |
88 | { | |
89 | assert(p.refCountForDebuggingOnly() > 0); | |
90 | return mReferences.find(&p) != mReferences.end(); | |
91 | } | |
92 | ||
93 | #endif //NDEBUG | |
94 | ||
95 | ||
96 | // | |
97 | // ClearReferences clears the reference set but does not propagate | |
98 | // anything; it is NOT recursive. | |
99 | // | |
100 | void NodeCore::clearReferences() | |
101 | { | |
102 | StLock<Mutex> _(*this); | |
fa7225c8 | 103 | secinfo("ssnode", "%p clearing all %d references", |
d8f41ccd A |
104 | this, int(mReferences.size())); |
105 | mReferences.erase(mReferences.begin(), mReferences.end()); | |
106 | } | |
107 | ||
108 | ||
109 | // | |
110 | // Kill should be overloaded by Nodes to implement any cleanup and release | |
111 | // operations that should happen at LOGICAL death of the represented object. | |
112 | // This is where you should release ports, close files, etc. | |
113 | // This default behavior, which you MUST include in your override, | |
114 | // propagates kills to all active references, recursively. | |
115 | // | |
116 | void NodeCore::kill() | |
117 | { | |
118 | StLock<Mutex> _(*this); | |
119 | for (ReferenceSet::const_iterator it = mReferences.begin(); it != mReferences.end(); it++) | |
120 | (*it)->kill(); | |
121 | clearReferences(); | |
122 | } | |
123 | ||
124 | ||
125 | void NodeCore::kill(NodeCore &ref) | |
126 | { | |
127 | StLock<Mutex> _(*this); | |
128 | assert(hasReference(ref)); | |
129 | ref.kill(); | |
130 | removeReference(ref); | |
131 | } | |
132 | ||
133 | ||
134 | // | |
135 | // NodeCore-level support for state dumping. | |
136 | // Call NodeCore::dumpAll() to debug-dump all nodes. | |
137 | // Note that enabling DEBUGDUMP serializes all node creation/destruction | |
138 | // operations, and thus may cause significant shifts in thread interactions. | |
139 | // | |
140 | #if defined(DEBUGDUMP) | |
141 | ||
142 | // The (uncounted) set of all known NodeCores in existence, with protective lock | |
143 | set<NodeCore *> NodeCore::mCoreNodes; | |
144 | Mutex NodeCore::mCoreLock; | |
145 | ||
146 | // add a new NodeCore to the known set | |
147 | NodeCore::NodeCore() | |
148 | : Mutex(Mutex::recursive) | |
149 | { | |
150 | StLock<Mutex> _(mCoreLock); | |
151 | mCoreNodes.insert(this); | |
152 | } | |
153 | ||
154 | // partial-line common dump text for any NodeCore | |
155 | // override this to add text to your Node type's state dump output | |
156 | void NodeCore::dumpNode() | |
157 | { | |
158 | Debug::dump("%s@%p rc=%u", Debug::typeName(*this).c_str(), this, unsigned(refCountForDebuggingOnly())); | |
159 | if (mParent) | |
160 | Debug::dump(" parent=%p", mParent.get()); | |
161 | if (mReferent) | |
162 | Debug::dump(" referent=%p", mReferent.get()); | |
163 | } | |
164 | ||
165 | // full-line dump of a NodeCore | |
166 | // override this to completely re-implement the dump format for your Node type | |
167 | void NodeCore::dump() | |
168 | { | |
169 | dumpNode(); | |
170 | if (!mReferences.empty()) { | |
171 | Debug::dump(" {"); | |
172 | for (ReferenceSet::const_iterator it = mReferences.begin(); it != mReferences.end(); it++) { | |
173 | Debug::dump(" %p", it->get()); | |
174 | if ((*it)->mReferent != this) | |
175 | Debug::dump("!*INVALID*"); | |
176 | } | |
177 | Debug::dump(" }"); | |
178 | } | |
179 | Debug::dump("\n"); | |
180 | } | |
181 | ||
182 | // dump all known nodes | |
183 | void NodeCore::dumpAll() | |
184 | { | |
185 | StLock<Mutex> _(mCoreLock); | |
186 | time_t now; time(&now); | |
187 | Debug::dump("\nNODE DUMP (%24.24s)\n", ctime(&now)); | |
188 | for (set<NodeCore *>::const_iterator it = mCoreNodes.begin(); it != mCoreNodes.end(); it++) | |
189 | (*it)->dump(); | |
190 | Debug::dump("END NODE DUMP\n\n"); | |
191 | } | |
192 | ||
193 | #endif //DEBUGDUMP |