structure.cpp
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() 36 try { 37 #if defined(DEBUGDUMP) 38 StLock<Mutex> _(mCoreLock); 39 mCoreNodes.erase(this); 40 #endif //DEBUGDUMP 41 } catch(...) { 42 return; 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 mReferent = NULL; 66 } 67 68 69 void NodeCore::addReference(NodeCore &p) 70 { 71 StLock<Mutex> _(*this); 72 assert(p.mReferent == this); 73 mReferences.insert(&p); 74 } 75 76 void NodeCore::removeReference(NodeCore &p) 77 { 78 StLock<Mutex> _(*this); 79 mReferences.erase(&p); 80 } 81 82 // 83 // ClearReferences clears the reference set but does not propagate 84 // anything; it is NOT recursive. 85 // 86 void NodeCore::clearReferences() 87 { 88 StLock<Mutex> _(*this); 89 secinfo("ssnode", "%p clearing all %d references", this, int(mReferences.size())); 90 mReferences.erase(mReferences.begin(), mReferences.end()); 91 } 92 93 94 // 95 // Kill should be overloaded by Nodes to implement any cleanup and release 96 // operations that should happen at LOGICAL death of the represented object. 97 // This is where you should release ports, close files, etc. 98 // This default behavior, which you MUST include in your override, 99 // propagates kills to all active references, recursively. 100 // 101 void NodeCore::kill() 102 { 103 StLock<Mutex> _(*this); 104 for (ReferenceSet::const_iterator it = mReferences.begin(); it != mReferences.end(); it++) 105 (*it)->kill(); 106 clearReferences(); 107 } 108 109 110 void NodeCore::kill(NodeCore &ref) 111 { 112 StLock<Mutex> _(*this); 113 ref.kill(); 114 removeReference(ref); 115 } 116 117 118 // 119 // NodeCore-level support for state dumping. 120 // Call NodeCore::dumpAll() to debug-dump all nodes. 121 // Note that enabling DEBUGDUMP serializes all node creation/destruction 122 // operations, and thus may cause significant shifts in thread interactions. 123 // 124 #if defined(DEBUGDUMP) 125 126 // The (uncounted) set of all known NodeCores in existence, with protective lock 127 set<NodeCore *> NodeCore::mCoreNodes; 128 Mutex NodeCore::mCoreLock; 129 130 // add a new NodeCore to the known set 131 NodeCore::NodeCore() 132 : Mutex(Mutex::recursive) 133 { 134 StLock<Mutex> _(mCoreLock); 135 mCoreNodes.insert(this); 136 } 137 138 // partial-line common dump text for any NodeCore 139 // override this to add text to your Node type's state dump output 140 void NodeCore::dumpNode() 141 { 142 Debug::dump("%s@%p rc=%u", Debug::typeName(*this).c_str(), this, unsigned(refCountForDebuggingOnly())); 143 if (mParent) 144 Debug::dump(" parent=%p", mParent.get()); 145 if (mReferent) 146 Debug::dump(" referent=%p", mReferent.get()); 147 } 148 149 // full-line dump of a NodeCore 150 // override this to completely re-implement the dump format for your Node type 151 void NodeCore::dump() 152 { 153 dumpNode(); 154 if (!mReferences.empty()) { 155 Debug::dump(" {"); 156 for (ReferenceSet::const_iterator it = mReferences.begin(); it != mReferences.end(); it++) { 157 Debug::dump(" %p", it->get()); 158 if ((*it)->mReferent != this) 159 Debug::dump("!*INVALID*"); 160 } 161 Debug::dump(" }"); 162 } 163 Debug::dump("\n"); 164 } 165 166 // dump all known nodes 167 void NodeCore::dumpAll() 168 { 169 StLock<Mutex> _(mCoreLock); 170 time_t now; time(&now); 171 Debug::dump("\nNODE DUMP (%24.24s)\n", ctime(&now)); 172 for (set<NodeCore *>::const_iterator it = mCoreNodes.begin(); it != mCoreNodes.end(); it++) 173 (*it)->dump(); 174 Debug::dump("END NODE DUMP\n\n"); 175 } 176 177 #endif //DEBUGDUMP