Library of Assembled Shared Sources
shared_memory.cpp
Go to the documentation of this file.
1 /** @file
2 * @author Bram de Greve (bram@cocamware.com)
3 * @author Tom De Muer (tom@cocamware.com)
4 *
5 * *** BEGIN LICENSE INFORMATION ***
6 *
7 * The contents of this file are subject to the Common Public Attribution License
8 * Version 1.0 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://lass.sourceforge.net/cpal-license. The License is based on the
11 * Mozilla Public License Version 1.1 but Sections 14 and 15 have been added to cover
12 * use of software over a computer network and provide for limited attribution for
13 * the Original Developer. In addition, Exhibit A has been modified to be consistent
14 * with Exhibit B.
15 *
16 * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
17 * WARRANTY OF ANY KIND, either express or implied. See the License for the specific
18 * language governing rights and limitations under the License.
19 *
20 * The Original Code is LASS - Library of Assembled Shared Sources.
21 *
22 * The Initial Developer of the Original Code is Bram de Greve and Tom De Muer.
23 * The Original Developer is the Initial Developer.
24 *
25 * All portions of the code written by the Initial Developer are:
26 * Copyright (C) 2004-2011 the Initial Developer.
27 * All Rights Reserved.
28 *
29 * Contributor(s):
30 *
31 * Alternatively, the contents of this file may be used under the terms of the
32 * GNU General Public License Version 2 or later (the GPL), in which case the
33 * provisions of GPL are applicable instead of those above. If you wish to allow use
34 * of your version of this file only under the terms of the GPL and not to allow
35 * others to use your version of this file under the CPAL, indicate your decision by
36 * deleting the provisions above and replace them with the notice and other
37 * provisions required by the GPL License. If you do not delete the provisions above,
38 * a recipient may use your version of this file under either the CPAL or the GPL.
39 *
40 * *** END LICENSE INFORMATION ***
41 */
42
43#include "lass_common.h"
44#include "shared_memory.h"
46#include "../num/num_cast.h"
47
48#ifdef _WIN32
49# define NOMINMAX
50# define WIN32_LEAN_AND_MEAN
51# include <Windows.h>
52#else
54# include <sys/mman.h>
55# include <sys/stat.h>
56# include <fcntl.h>
57# include <unistd.h>
58# include <errno.h>
59#endif
60
61namespace lass
62{
63namespace io
64{
65namespace impl
66{
67
68#ifdef _WIN32
69
70class SharedMemoryImpl
71{
72public:
73 SharedMemoryImpl():
74 map_(0),
75 view_(0),
76 size_(0)
77 {
78 }
79
80 ~SharedMemoryImpl()
81 {
82 close();
83 }
84
85 bool create(size_t size)
86 {
87 close();
88
89 const unsigned long pid = GetCurrentProcessId();
90 name_ = stde::safe_format("Local\\LassIOSharedMemory_%lx_%i", pid, id_++);
91
92 LARGE_INTEGER s;
93 s.QuadPart = size;
94 map_ = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, s.HighPart, s.LowPart, name_.c_str());
95 if (!mapView())
96 {
97 return false;
98 }
99
100 size_ = size;
101 return true;
102 }
103
104 bool open(const char* name)
105 {
106 close();
107
108 name_ = name;
109 map_ = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, name);
110 if (!mapView())
111 {
112 return false;
113 }
114
115 // OK, we can't really know the size. The following is our best guess.
116 MEMORY_BASIC_INFORMATION buffer;
117 if ( VirtualQuery( view_, &buffer, sizeof(buffer) ) )
118 {
119 size_ = buffer.RegionSize;
120 }
121
122 return true;
123 }
124
125 void close()
126 {
127 if (view_)
128 {
129 UnmapViewOfFile(view_);
130 view_ = 0;
131 }
132 if (map_)
133 {
134 CloseHandle(map_);
135 map_ = 0;
136 }
137 size_ = 0;
138 }
139
140 const char* name() const
141 {
142 return name_.c_str();
143 }
144
145 void* get() const
146 {
147 return view_;
148 }
149
150 size_t size() const
151 {
152 return size_;
153 }
154
155private:
156
157 bool mapView()
158 {
159 if (!map_)
160 {
161 return false;
162 }
163 LASS_ASSERT(!view_);
164 view_ = MapViewOfFile(map_, FILE_MAP_ALL_ACCESS, 0, 0, 0);
165 if (!view_)
166 {
167 close();
168 return false;
169 }
170 return true;
171 }
172
173 HANDLE map_;
174 void* view_;
175 size_t size_;
176 std::string name_;
177 static unsigned id_;
178};
179
180unsigned SharedMemoryImpl::id_ = 0;
181
182#else
183
184class SharedMemoryImpl
185{
186public:
187 SharedMemoryImpl():
188 view_(0),
189 size_(0),
190 fd_(-1)
191 {
192 }
193
194 ~SharedMemoryImpl()
195 {
196 close();
197 }
198
199 bool create(size_t size)
200 {
201 close();
202
203 off_t ssize = num::numCast<off_t>(size);
204
205 char shmname[] = "/dev/shm/lass-shm.XXXXXX";
206 if (tryCreate(shmname, ssize))
207 {
208 return mapView(ssize);
209 }
210
211 char tmpname[] = "/tmp/lass-shm.XXXXXX";
212 if (tryCreate(tmpname, ssize))
213 {
214 return mapView(ssize);
215 }
216
217 if (const char* tmpdir = getenv("TMPDIR"))
218 {
219 const size_t n = ::strlen(tmpdir) + 16;
220 std::vector<char> buf(n + 1);
221 const int written = ::snprintf(buf.data(), buf.size(), "%s/lass-shm.XXXXXX", tmpdir);
222 LASS_ENFORCE(written > 0 && static_cast<size_t>(written) == n);
223 buf[n] = 0;
224 if (tryCreate(buf.data(), ssize))
225 {
226 return mapView(ssize);
227 }
228 }
229
230 return false; // give up
231 }
232
233 bool open(const char* name)
234 {
235 close();
236
237 fd_ = ::open(name, O_RDWR, 0);
238 if (fd_ == -1)
239 {
240 return false;
241 }
242
243 struct stat st;
244 if (fstat(fd_, &st) == -1)
245 {
246 close();
247 return false;
248 }
249
250 return mapView(st.st_size);
251 }
252
253 void close()
254 {
255 if (view_ && view_ != MAP_FAILED)
256 {
257 munmap(view_, this->size());
258 }
259 view_ = 0;
260
261 if (fd_ != -1)
262 {
263 ::close(fd_);
264 fd_ = -1;
265 }
266
267 size_ = 0;
268 name_.clear();
269 }
270
271 const char* name() const
272 {
273 return name_.c_str();
274 }
275
276 void* get() const
277 {
278 return view_;
279 }
280
281 size_t size() const
282 {
283 LASS_ASSERT(size_ >= 0);
284 return static_cast<size_t>(size_);
285 }
286
287private:
288
289 bool tryCreate(char* namebuf, off_t size)
290 {
291 fd_ = mkstemp(namebuf);
292 if (fd_ == -1)
293 {
294 return false;
295 }
296 unlink(namebuf);
297 return ftruncate(fd_, size) == 0;
298 }
299
300 bool mapView(off_t size)
301 {
302 const int pid = getpid();
303 name_ = lass::stde::safe_format("/proc/%i/fd/%i", pid, fd_);
304
305 LASS_ASSERT(size_ >= 0);
306 view_ = mmap(0, static_cast<size_t>(size), PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, fd_, 0);
307 if (view_ == MAP_FAILED)
308 {
309 close();
310 return false;
311 }
312 size_ = size;
313 return true;
314 }
315
316 void* view_;
317 off_t size_;
318 std::string name_;
319 int fd_;
320};
321
322#endif
323
324}
325
326
327// --- SharedMemory ---------------------------------------------------------------------------------
328
329SharedMemory::SharedMemory():
330 pimpl_(new impl::SharedMemoryImpl())
331{
332}
333
334
335SharedMemory::~SharedMemory()
336{
337 delete pimpl_;
338}
339
340
341bool SharedMemory::create(size_t size)
342{
343 return pimpl_->create(size);
344}
345
346
347bool SharedMemory::open(const char* pipeName)
348{
349 return pimpl_->open(pipeName);
350}
351
352
353void SharedMemory::close()
354{
355 pimpl_->close();
356}
357
358
359const char* SharedMemory::name() const
360{
361 return pimpl_->name();
362}
363
364
365size_t SharedMemory::size() const
366{
367 return pimpl_->size();
368}
369
370
371void* SharedMemory::get() const
372{
373 return pimpl_->get();
374}
375
376
377bool SharedMemory::operator!() const
378{
379 return !pimpl_->get();
380}
381
382
383}
384}
385
386// EOF
streams, binary streams, vrmlstreams, ...
Library for Assembled Shared Sources.
Definition config.h:53