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