]> git.saurik.com Git - apple/security.git/blobdiff - securityd/src/structure.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / securityd / src / structure.cpp
diff --git a/securityd/src/structure.cpp b/securityd/src/structure.cpp
new file mode 100644 (file)
index 0000000..b148a68
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2000-2001,2004,2009 Apple Inc. All Rights Reserved.
+ * 
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+
+//
+// structure - structural framework for securityd objects
+//
+#include "structure.h"
+
+
+//
+// NodeCore always has a destructor (because it's virtual),
+// but its dump support is conditionally included.
+//
+NodeCore::~NodeCore()
+{
+#if defined(DEBUGDUMP)
+       StLock<Mutex> _(mCoreLock);
+       mCoreNodes.erase(this);
+#endif //DEBUGDUMP
+}
+
+
+//
+// Basic object mesh maintainance
+//
+void NodeCore::parent(NodeCore &p)
+{
+       StLock<Mutex> _(*this);
+       mParent = &p;
+}
+
+void NodeCore::referent(NodeCore &r)
+{
+       StLock<Mutex> _(*this);
+       assert(!mReferent);
+       mReferent = &r;
+}
+       
+void NodeCore::clearReferent()
+{
+       StLock<Mutex> _(*this);
+       if (mReferent)
+               assert(!mReferent->hasReference(*this));
+       mReferent = NULL;
+}
+
+
+void NodeCore::addReference(NodeCore &p)
+{
+       StLock<Mutex> _(*this);
+       assert(p.mReferent == this);
+       mReferences.insert(&p);
+}
+
+void NodeCore::removeReference(NodeCore &p)
+{
+       StLock<Mutex> _(*this);
+       assert(hasReference(p));
+       mReferences.erase(&p);
+}
+
+#if !defined(NDEBUG)
+
+bool NodeCore::hasReference(NodeCore &p)
+{
+       assert(p.refCountForDebuggingOnly() > 0);
+       return mReferences.find(&p) != mReferences.end();
+}
+
+#endif //NDEBUG
+
+
+//
+// ClearReferences clears the reference set but does not propagate
+// anything; it is NOT recursive.
+//
+void NodeCore::clearReferences()
+{
+       StLock<Mutex> _(*this);
+       secdebug("ssnode", "%p clearing all %d references",
+               this, int(mReferences.size()));
+       mReferences.erase(mReferences.begin(), mReferences.end());
+}
+
+
+//
+// Kill should be overloaded by Nodes to implement any cleanup and release
+// operations that should happen at LOGICAL death of the represented object.
+// This is where you should release ports, close files, etc.
+// This default behavior, which you MUST include in your override,
+// propagates kills to all active references, recursively.
+//
+void NodeCore::kill()
+{
+       StLock<Mutex> _(*this);
+       for (ReferenceSet::const_iterator it = mReferences.begin(); it != mReferences.end(); it++)
+               (*it)->kill();
+       clearReferences();
+}
+
+
+void NodeCore::kill(NodeCore &ref)
+{
+       StLock<Mutex> _(*this);
+       assert(hasReference(ref));
+       ref.kill();
+       removeReference(ref);
+}
+
+
+//
+// NodeCore-level support for state dumping.
+// Call NodeCore::dumpAll() to debug-dump all nodes.
+// Note that enabling DEBUGDUMP serializes all node creation/destruction
+// operations, and thus may cause significant shifts in thread interactions.
+//
+#if defined(DEBUGDUMP)
+
+// The (uncounted) set of all known NodeCores in existence, with protective lock
+set<NodeCore *> NodeCore::mCoreNodes;
+Mutex NodeCore::mCoreLock;
+
+// add a new NodeCore to the known set
+NodeCore::NodeCore()
+       : Mutex(Mutex::recursive)
+{
+       StLock<Mutex> _(mCoreLock);
+       mCoreNodes.insert(this);
+}
+
+// partial-line common dump text for any NodeCore
+// override this to add text to your Node type's state dump output
+void NodeCore::dumpNode()
+{
+ Debug::dump("%s@%p rc=%u", Debug::typeName(*this).c_str(), this, unsigned(refCountForDebuggingOnly()));
+       if (mParent)
+               Debug::dump(" parent=%p", mParent.get());
+       if (mReferent)
+               Debug::dump(" referent=%p", mReferent.get());
+}
+
+// full-line dump of a NodeCore
+// override this to completely re-implement the dump format for your Node type
+void NodeCore::dump()
+{
+ dumpNode();
+       if (!mReferences.empty()) {
+               Debug::dump(" {");
+               for (ReferenceSet::const_iterator it = mReferences.begin(); it != mReferences.end(); it++) {
+                       Debug::dump(" %p", it->get());
+                       if ((*it)->mReferent != this)
+                               Debug::dump("!*INVALID*");
+               }
+               Debug::dump(" }");
+       }
+       Debug::dump("\n");
+}
+
+// dump all known nodes
+void NodeCore::dumpAll()
+{
+ StLock<Mutex> _(mCoreLock);
+       time_t now; time(&now);
+       Debug::dump("\nNODE DUMP (%24.24s)\n", ctime(&now));
+       for (set<NodeCore *>::const_iterator it = mCoreNodes.begin(); it != mCoreNodes.end(); it++)
+               (*it)->dump();
+       Debug::dump("END NODE DUMP\n\n");
+}
+
+#endif //DEBUGDUMP