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