]> git.ipfire.org Git - thirdparty/squid.git/blob - src/ipc/mem/Pointer.h
Merged from trunk
[thirdparty/squid.git] / src / ipc / mem / Pointer.h
1 /*
2 * $Id$
3 *
4 */
5
6 #ifndef SQUID_IPC_MEM_POINTER_H
7 #define SQUID_IPC_MEM_POINTER_H
8
9 #include "base/TextException.h"
10 #include "ipc/mem/Segment.h"
11 #include "RefCount.h"
12
13 namespace Ipc
14 {
15
16 namespace Mem
17 {
18
19 /// allocates/deallocates shared memory; creates and later destroys a
20 /// Class object using that memory
21 template <class Class>
22 class Owner
23 {
24 public:
25 static Owner *New(const char *const id);
26 template <class P1>
27 static Owner *New(const char *const id, const P1 &p1);
28 template <class P1, class P2>
29 static Owner *New(const char *const id, const P1 &p1, const P2 &p2);
30 template <class P1, class P2, class P3>
31 static Owner *New(const char *const id, const P1 &p1, const P2 &p2, const P3 &p3);
32 template <class P1, class P2, class P3, class P4>
33 static Owner *New(const char *const id, const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4);
34
35 ~Owner();
36
37 private:
38 Owner(const char *const id, const off_t sharedSize);
39
40 // not implemented
41 Owner(const Owner &);
42 Owner &operator =(const Owner &);
43
44 Segment theSegment; ///< shared memory segment that holds the object
45 Class *theObject; ///< shared object
46 };
47
48 template <class Class> class Pointer;
49
50 /// attaches to a shared memory segment with Class object owned by Owner
51 template <class Class>
52 class Object: public RefCountable
53 {
54 public:
55 static Pointer<Class> Old(const char *const id);
56
57 private:
58 explicit Object(const char *const id);
59
60 // not implemented
61 Object(const Object &);
62 Object &operator =(const Object &);
63
64 Segment theSegment; ///< shared memory segment that holds the object
65 Class *theObject; ///< shared object
66
67 friend class Pointer<Class>;
68 };
69
70 /// uses a refcounted pointer to Object<Class> as a parent, but
71 /// translates its API to return raw Class pointers
72 template <class Class>
73 class Pointer: public RefCount< Object<Class> >
74 {
75 private:
76 typedef RefCount< Object<Class> > Base;
77
78 public:
79 explicit Pointer(Object<Class> *const anObject = NULL): Base(anObject) {}
80
81 Class *operator ->() const { return Base::operator ->()->theObject; }
82 Class &operator *() const { return *Base::operator *().theObject; }
83 const Class *getRaw() const { return Base::getRaw()->theObject; }
84 Class *getRaw() { return Base::getRaw()->theObject; }
85 };
86
87 // Owner implementation
88
89 template <class Class>
90 Owner<Class>::Owner(const char *const id, const off_t sharedSize):
91 theSegment(id), theObject(NULL)
92 {
93 theSegment.create(sharedSize);
94 Must(theSegment.mem());
95 }
96
97 template <class Class>
98 Owner<Class>::~Owner()
99 {
100 if (theObject)
101 theObject->~Class();
102 }
103
104 template <class Class>
105 Owner<Class> *
106 Owner<Class>::New(const char *const id)
107 {
108 const off_t sharedSize = Class::SharedMemorySize();
109 Owner *const owner = new Owner(id, sharedSize);
110 owner->theObject = new (owner->theSegment.reserve(sharedSize)) Class;
111 return owner;
112 }
113
114 template <class Class> template <class P1>
115 Owner<Class> *
116 Owner<Class>::New(const char *const id, const P1 &p1)
117 {
118 const off_t sharedSize = Class::SharedMemorySize(p1);
119 Owner *const owner = new Owner(id, sharedSize);
120 owner->theObject = new (owner->theSegment.reserve(sharedSize)) Class(p1);
121 return owner;
122 }
123
124 template <class Class> template <class P1, class P2>
125 Owner<Class> *
126 Owner<Class>::New(const char *const id, const P1 &p1, const P2 &p2)
127 {
128 const off_t sharedSize = Class::SharedMemorySize(p1, p2);
129 Owner *const owner = new Owner(id, sharedSize);
130 owner->theObject = new (owner->theSegment.reserve(sharedSize)) Class(p1, p2);
131 return owner;
132 }
133
134 template <class Class> template <class P1, class P2, class P3>
135 Owner<Class> *
136 Owner<Class>::New(const char *const id, const P1 &p1, const P2 &p2, const P3 &p3)
137 {
138 const off_t sharedSize = Class::SharedMemorySize(p1, p2, p3);
139 Owner *const owner = new Owner(id, sharedSize);
140 owner->theObject = new (owner->theSegment.reserve(sharedSize)) Class(p1, p2, p3);
141 return owner;
142 }
143
144 template <class Class> template <class P1, class P2, class P3, class P4>
145 Owner<Class> *
146 Owner<Class>::New(const char *const id, const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4)
147 {
148 const off_t sharedSize = Class::SharedMemorySize(p1, p2, p3, p4);
149 Owner *const owner = new Owner(id, sharedSize);
150 owner->theObject = new (owner->theSegment.reserve(sharedSize)) Class(p1, p2, p3, p4);
151 return owner;
152 }
153
154 // Object implementation
155
156 template <class Class>
157 Object<Class>::Object(const char *const id): theSegment(id)
158 {
159 theSegment.open();
160 Must(theSegment.mem());
161 theObject = reinterpret_cast<Class*>(theSegment.mem());
162 Must(static_cast<off_t>(theObject->sharedMemorySize()) == theSegment.size());
163 }
164
165 template <class Class>
166 Pointer<Class>
167 Object<Class>::Old(const char *const id)
168 {
169 return Pointer<Class>(new Object(id));
170 }
171
172 // convenience macros for creating shared objects
173 #define shm_new(Class) Ipc::Mem::Owner<Class>::New
174 #define shm_old(Class) Ipc::Mem::Object<Class>::Old
175
176 } // namespace Mem
177
178 } // namespace Ipc
179
180 #endif /* SQUID_IPC_MEM_POINTER_H */