]>
Commit | Line | Data |
---|---|---|
68353d5a | 1 | /* |
f70aedc4 | 2 | * Copyright (C) 1996-2021 The Squid Software Foundation and contributors |
bbc27441 AJ |
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. | |
68353d5a DK |
7 | */ |
8 | ||
9 | #ifndef SQUID_IPC_MEM_POINTER_H | |
10 | #define SQUID_IPC_MEM_POINTER_H | |
11 | ||
8bf217bd | 12 | #include "base/RefCount.h" |
68353d5a DK |
13 | #include "base/TextException.h" |
14 | #include "ipc/mem/Segment.h" | |
68353d5a | 15 | |
9199139f AR |
16 | namespace Ipc |
17 | { | |
68353d5a | 18 | |
9199139f AR |
19 | namespace Mem |
20 | { | |
68353d5a DK |
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); | |
f5591061 DK |
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); | |
8ecbe78d EB |
37 | /// attaches to the existing shared memory segment, becoming its owner |
38 | static Owner *Old(const char *const id); | |
68353d5a DK |
39 | |
40 | ~Owner(); | |
41 | ||
6d68a230 | 42 | /// Raw access; handy to finalize initiatization, but avoid if possible. |
93910d5c AR |
43 | Class *object() { return theObject; } |
44 | ||
68353d5a | 45 | private: |
8ecbe78d | 46 | explicit Owner(const char *const id); |
68353d5a DK |
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: | |
f5591061 | 88 | explicit Pointer(Object<Class> *const anObject = NULL): Base(anObject) {} |
68353d5a DK |
89 | |
90 | Class *operator ->() const { return Base::operator ->()->theObject; } | |
91 | Class &operator *() const { return *Base::operator *().theObject; } | |
cd43a242 | 92 | const Class *getRaw() const { return Base::getRaw()->theObject; } |
68353d5a DK |
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): | |
f53969cc | 100 | theSegment(id), theObject(NULL) |
68353d5a DK |
101 | { |
102 | theSegment.create(sharedSize); | |
103 | Must(theSegment.mem()); | |
104 | } | |
105 | ||
8ecbe78d EB |
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 | ||
68353d5a DK |
114 | template <class Class> |
115 | Owner<Class>::~Owner() | |
116 | { | |
117 | if (theObject) | |
118 | theObject->~Class(); | |
119 | } | |
120 | ||
8ecbe78d EB |
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 | ||
68353d5a DK |
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 | ||
f5591061 DK |
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 | ||
68353d5a DK |
181 | // Object implementation |
182 | ||
183 | template <class Class> | |
184 | Object<Class>::Object(const char *const id): theSegment(id) | |
185 | { | |
8ecbe78d | 186 | theSegment.open(false); |
68353d5a DK |
187 | Must(theSegment.mem()); |
188 | theObject = reinterpret_cast<Class*>(theSegment.mem()); | |
5b92ba07 | 189 | Must(static_cast<off_t>(theObject->sharedMemorySize()) <= theSegment.size()); |
68353d5a DK |
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 */ | |
f53969cc | 208 |