/* * Copyright (C) 1996-2015 The Squid Software Foundation and contributors * * Squid software is distributed under GPLv2+ license and includes * contributions from numerous individuals and organizations. * Please see the COPYING and CONTRIBUTORS files for details. */ #ifndef SQUID_IPC_MEM_POINTER_H #define SQUID_IPC_MEM_POINTER_H #include "base/RefCount.h" #include "base/TextException.h" #include "ipc/mem/Segment.h" namespace Ipc { namespace Mem { /// allocates/deallocates shared memory; creates and later destroys a /// Class object using that memory template class Owner { public: static Owner *New(const char *const id); template static Owner *New(const char *const id, const P1 &p1); template static Owner *New(const char *const id, const P1 &p1, const P2 &p2); template static Owner *New(const char *const id, const P1 &p1, const P2 &p2, const P3 &p3); template static Owner *New(const char *const id, const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4); ~Owner(); /// Raw access; handy to finalize initiatization, but avoid if possible. Class *object() { return theObject; } private: Owner(const char *const id, const off_t sharedSize); // not implemented Owner(const Owner &); Owner &operator =(const Owner &); Segment theSegment; ///< shared memory segment that holds the object Class *theObject; ///< shared object }; template class Pointer; /// attaches to a shared memory segment with Class object owned by Owner template class Object: public RefCountable { public: static Pointer Old(const char *const id); private: explicit Object(const char *const id); // not implemented Object(const Object &); Object &operator =(const Object &); Segment theSegment; ///< shared memory segment that holds the object Class *theObject; ///< shared object friend class Pointer; }; /// uses a refcounted pointer to Object as a parent, but /// translates its API to return raw Class pointers template class Pointer: public RefCount< Object > { private: typedef RefCount< Object > Base; public: explicit Pointer(Object *const anObject = NULL): Base(anObject) {} Class *operator ->() const { return Base::operator ->()->theObject; } Class &operator *() const { return *Base::operator *().theObject; } const Class *getRaw() const { return Base::getRaw()->theObject; } Class *getRaw() { return Base::getRaw()->theObject; } }; // Owner implementation template Owner::Owner(const char *const id, const off_t sharedSize): theSegment(id), theObject(NULL) { theSegment.create(sharedSize); Must(theSegment.mem()); } template Owner::~Owner() { if (theObject) theObject->~Class(); } template Owner * Owner::New(const char *const id) { const off_t sharedSize = Class::SharedMemorySize(); Owner *const owner = new Owner(id, sharedSize); owner->theObject = new (owner->theSegment.reserve(sharedSize)) Class; return owner; } template template Owner * Owner::New(const char *const id, const P1 &p1) { const off_t sharedSize = Class::SharedMemorySize(p1); Owner *const owner = new Owner(id, sharedSize); owner->theObject = new (owner->theSegment.reserve(sharedSize)) Class(p1); return owner; } template template Owner * Owner::New(const char *const id, const P1 &p1, const P2 &p2) { const off_t sharedSize = Class::SharedMemorySize(p1, p2); Owner *const owner = new Owner(id, sharedSize); owner->theObject = new (owner->theSegment.reserve(sharedSize)) Class(p1, p2); return owner; } template template Owner * Owner::New(const char *const id, const P1 &p1, const P2 &p2, const P3 &p3) { const off_t sharedSize = Class::SharedMemorySize(p1, p2, p3); Owner *const owner = new Owner(id, sharedSize); owner->theObject = new (owner->theSegment.reserve(sharedSize)) Class(p1, p2, p3); return owner; } template template Owner * Owner::New(const char *const id, const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4) { const off_t sharedSize = Class::SharedMemorySize(p1, p2, p3, p4); Owner *const owner = new Owner(id, sharedSize); owner->theObject = new (owner->theSegment.reserve(sharedSize)) Class(p1, p2, p3, p4); return owner; } // Object implementation template Object::Object(const char *const id): theSegment(id) { theSegment.open(); Must(theSegment.mem()); theObject = reinterpret_cast(theSegment.mem()); Must(static_cast(theObject->sharedMemorySize()) == theSegment.size()); } template Pointer Object::Old(const char *const id) { return Pointer(new Object(id)); } // convenience macros for creating shared objects #define shm_new(Class) Ipc::Mem::Owner::New #define shm_old(Class) Ipc::Mem::Object::Old } // namespace Mem } // namespace Ipc #endif /* SQUID_IPC_MEM_POINTER_H */