#ifndef _H_STRUCTURE
#define _H_STRUCTURE
#include <security_utilities/refcount.h>
#include <security_utilities/mach++.h>
#include <security_cdsa_utilities/u32handleobject.h>
#include <map>
#include "dtrace.h"
using MachPlusPlus::Port;
template <class Base, class Glob> class Node;
class PerConnection;
class PerProcess;
class PerSession;
class PerGlobal;
class NodeCore : public RefCount, public Mutex {
template <class Base, class Glob> friend class Node;
public:
#if !defined(DEBUGDUMP) // (see below if DEBUGDUMP)
NodeCore() : Mutex(Mutex::recursive) { }
#endif
virtual ~NodeCore();
void addReference(NodeCore &p);
void removeReference(NodeCore &p);
template <class Sub>
void allReferences(void (Sub::*func)());
template <class Sub, class Value>
RefPointer<Sub> findFirst(Value (Sub::*func)() const, Value compare);
void clearReferences();
virtual void kill(); virtual void kill(NodeCore &ref);
bool operator < (const NodeCore &other) const
{ return this < &other; }
protected:
void parent(NodeCore &p); void referent(NodeCore &r); void clearReferent();
bool hasParent() const { return mParent; }
bool hasReferent() const { return mReferent; }
private:
RefPointer<NodeCore> mParent;
RefPointer<NodeCore> mReferent;
typedef set<RefPointer<NodeCore> > ReferenceSet;
ReferenceSet mReferences;
#if defined(DEBUGDUMP)
public: NodeCore();
virtual void dumpNode(); virtual void dump(); static void dumpAll();
static Mutex mCoreLock; static set<NodeCore *> mCoreNodes; #endif //DEBUGDUMP
};
template <class Sub>
void NodeCore::allReferences(void (Sub::*func)())
{
StLock<Mutex> _(*this);
for (ReferenceSet::const_iterator it = mReferences.begin(); it != mReferences.end();)
if (RefPointer<Sub> sub = dynamic_cast<Sub *>((it++)->get()))
(sub->*func)();
}
template <class Sub, class Value>
RefPointer<Sub> NodeCore::findFirst(Value (Sub::*func)() const, Value compare)
{
StLock<Mutex> _(*this);
for (ReferenceSet::const_iterator it = mReferences.begin(); it != mReferences.end(); it++)
if (Sub *sub = dynamic_cast<Sub *>(it->get()))
if ((sub->*func)() == compare)
return sub;
return NULL;
}
template <class Base, class Glob>
class Node : public NodeCore {
protected:
void parent(Glob &p) { NodeCore::parent(p); }
void referent(Base &r) { NodeCore::referent(r); }
public:
template <class T>
T& parent() const
{ assert(mParent); return safer_cast<T &>(*mParent); }
template <class T>
T& referent() const
{ assert(mReferent); return safer_cast<T &>(*mReferent); }
public:
void addReference(Base &p) { NodeCore::addReference(p); }
void removeReference(Base &p) { NodeCore::removeReference(p); }
};
class PerConnection : public Node<PerConnection, PerProcess> {
public:
};
class PerProcess : public U32HandleObject, public Node<PerProcess, PerSession> {
public:
};
class PerSession : public Node<PerSession, PerGlobal> {
public:
};
class PerGlobal : public Node<PerGlobal, PerGlobal> {
public:
};
template <class Node>
class PortMap : public Mutex, public std::map<Port, RefPointer<Node> > {
typedef std::map<Port, RefPointer<Node> > _Map;
public:
bool contains(mach_port_t port) const { return this->find(port) != this->end(); }
Node *getOpt(mach_port_t port) const
{
typename _Map::const_iterator it = this->find(port);
return (it == this->end()) ? NULL : it->second;
}
Node *get(mach_port_t port) const
{
typename _Map::const_iterator it = this->find(port);
assert(it != this->end());
return it->second;
}
Node *get(mach_port_t port, OSStatus error) const
{
typename _Map::const_iterator it = this->find(port);
if (it == this->end())
MacOSError::throwMe(error);
return it->second;
}
void dump();
};
template <class Node>
void PortMap<Node>::dump()
{
for (typename _Map::const_iterator it = this->begin(); it != this->end(); it++)
it->second->dump();
}
#endif //_H_STRUCTURE