]>
Commit | Line | Data |
---|---|---|
68353d5a | 1 | /* |
bbc27441 AJ |
2 | * Copyright (C) 1996-2014 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. | |
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); | |
68353d5a DK |
37 | |
38 | ~Owner(); | |
39 | ||
6d68a230 | 40 | /// Raw access; handy to finalize initiatization, but avoid if possible. |
93910d5c AR |
41 | Class *object() { return theObject; } |
42 | ||
68353d5a DK |
43 | private: |
44 | Owner(const char *const id, const off_t sharedSize); | |
45 | ||
46 | // not implemented | |
47 | Owner(const Owner &); | |
48 | Owner &operator =(const Owner &); | |
49 | ||
50 | Segment theSegment; ///< shared memory segment that holds the object | |
51 | Class *theObject; ///< shared object | |
52 | }; | |
53 | ||
54 | template <class Class> class Pointer; | |
55 | ||
56 | /// attaches to a shared memory segment with Class object owned by Owner | |
57 | template <class Class> | |
58 | class Object: public RefCountable | |
59 | { | |
60 | public: | |
61 | static Pointer<Class> Old(const char *const id); | |
62 | ||
63 | private: | |
64 | explicit Object(const char *const id); | |
65 | ||
66 | // not implemented | |
67 | Object(const Object &); | |
68 | Object &operator =(const Object &); | |
69 | ||
70 | Segment theSegment; ///< shared memory segment that holds the object | |
71 | Class *theObject; ///< shared object | |
72 | ||
73 | friend class Pointer<Class>; | |
74 | }; | |
75 | ||
76 | /// uses a refcounted pointer to Object<Class> as a parent, but | |
77 | /// translates its API to return raw Class pointers | |
78 | template <class Class> | |
79 | class Pointer: public RefCount< Object<Class> > | |
80 | { | |
81 | private: | |
82 | typedef RefCount< Object<Class> > Base; | |
83 | ||
84 | public: | |
f5591061 | 85 | explicit Pointer(Object<Class> *const anObject = NULL): Base(anObject) {} |
68353d5a DK |
86 | |
87 | Class *operator ->() const { return Base::operator ->()->theObject; } | |
88 | Class &operator *() const { return *Base::operator *().theObject; } | |
cd43a242 | 89 | const Class *getRaw() const { return Base::getRaw()->theObject; } |
68353d5a DK |
90 | Class *getRaw() { return Base::getRaw()->theObject; } |
91 | }; | |
92 | ||
93 | // Owner implementation | |
94 | ||
95 | template <class Class> | |
96 | Owner<Class>::Owner(const char *const id, const off_t sharedSize): | |
9199139f | 97 | theSegment(id), theObject(NULL) |
68353d5a DK |
98 | { |
99 | theSegment.create(sharedSize); | |
100 | Must(theSegment.mem()); | |
101 | } | |
102 | ||
103 | template <class Class> | |
104 | Owner<Class>::~Owner() | |
105 | { | |
106 | if (theObject) | |
107 | theObject->~Class(); | |
108 | } | |
109 | ||
110 | template <class Class> | |
111 | Owner<Class> * | |
112 | Owner<Class>::New(const char *const id) | |
113 | { | |
114 | const off_t sharedSize = Class::SharedMemorySize(); | |
115 | Owner *const owner = new Owner(id, sharedSize); | |
116 | owner->theObject = new (owner->theSegment.reserve(sharedSize)) Class; | |
117 | return owner; | |
118 | } | |
119 | ||
120 | template <class Class> template <class P1> | |
121 | Owner<Class> * | |
122 | Owner<Class>::New(const char *const id, const P1 &p1) | |
123 | { | |
124 | const off_t sharedSize = Class::SharedMemorySize(p1); | |
125 | Owner *const owner = new Owner(id, sharedSize); | |
126 | owner->theObject = new (owner->theSegment.reserve(sharedSize)) Class(p1); | |
127 | return owner; | |
128 | } | |
129 | ||
130 | template <class Class> template <class P1, class P2> | |
131 | Owner<Class> * | |
132 | Owner<Class>::New(const char *const id, const P1 &p1, const P2 &p2) | |
133 | { | |
134 | const off_t sharedSize = Class::SharedMemorySize(p1, p2); | |
135 | Owner *const owner = new Owner(id, sharedSize); | |
136 | owner->theObject = new (owner->theSegment.reserve(sharedSize)) Class(p1, p2); | |
137 | return owner; | |
138 | } | |
139 | ||
140 | template <class Class> template <class P1, class P2, class P3> | |
141 | Owner<Class> * | |
142 | Owner<Class>::New(const char *const id, const P1 &p1, const P2 &p2, const P3 &p3) | |
143 | { | |
144 | const off_t sharedSize = Class::SharedMemorySize(p1, p2, p3); | |
145 | Owner *const owner = new Owner(id, sharedSize); | |
146 | owner->theObject = new (owner->theSegment.reserve(sharedSize)) Class(p1, p2, p3); | |
147 | return owner; | |
148 | } | |
149 | ||
f5591061 DK |
150 | template <class Class> template <class P1, class P2, class P3, class P4> |
151 | Owner<Class> * | |
152 | Owner<Class>::New(const char *const id, const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4) | |
153 | { | |
154 | const off_t sharedSize = Class::SharedMemorySize(p1, p2, p3, p4); | |
155 | Owner *const owner = new Owner(id, sharedSize); | |
156 | owner->theObject = new (owner->theSegment.reserve(sharedSize)) Class(p1, p2, p3, p4); | |
157 | return owner; | |
158 | } | |
159 | ||
68353d5a DK |
160 | // Object implementation |
161 | ||
162 | template <class Class> | |
163 | Object<Class>::Object(const char *const id): theSegment(id) | |
164 | { | |
165 | theSegment.open(); | |
166 | Must(theSegment.mem()); | |
167 | theObject = reinterpret_cast<Class*>(theSegment.mem()); | |
168 | Must(static_cast<off_t>(theObject->sharedMemorySize()) == theSegment.size()); | |
169 | } | |
170 | ||
171 | template <class Class> | |
172 | Pointer<Class> | |
173 | Object<Class>::Old(const char *const id) | |
174 | { | |
175 | return Pointer<Class>(new Object(id)); | |
176 | } | |
177 | ||
178 | // convenience macros for creating shared objects | |
179 | #define shm_new(Class) Ipc::Mem::Owner<Class>::New | |
180 | #define shm_old(Class) Ipc::Mem::Object<Class>::Old | |
181 | ||
182 | } // namespace Mem | |
183 | ||
184 | } // namespace Ipc | |
185 | ||
186 | #endif /* SQUID_IPC_MEM_POINTER_H */ |