Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
4 : // Use of this source code is governed by a BSD-style license that can be
5 : // found in the LICENSE file.
6 :
7 : #ifndef BASE_SHARED_MEMORY_H_
8 : #define BASE_SHARED_MEMORY_H_
9 :
10 : #include "build/build_config.h"
11 :
12 : #if defined(OS_POSIX)
13 : #include <sys/types.h>
14 : #include <semaphore.h>
15 : #include "base/file_descriptor_posix.h"
16 : #endif
17 : #include <string>
18 :
19 : #include "base/basictypes.h"
20 : #include "base/process.h"
21 :
22 : namespace base {
23 :
24 : // SharedMemoryHandle is a platform specific type which represents
25 : // the underlying OS handle to a shared memory segment.
26 : #if defined(OS_WIN)
27 : typedef HANDLE SharedMemoryHandle;
28 : typedef HANDLE SharedMemoryLock;
29 : #elif defined(OS_POSIX)
30 : // A SharedMemoryId is sufficient to identify a given shared memory segment on a
31 : // system, but insufficient to map it.
32 : typedef FileDescriptor SharedMemoryHandle;
33 : typedef ino_t SharedMemoryId;
34 : // On POSIX, the lock is implemented as a lockf() on the mapped file,
35 : // so no additional member (or definition of SharedMemoryLock) is
36 : // needed.
37 : #endif
38 :
39 : // Platform abstraction for shared memory. Provides a C++ wrapper
40 : // around the OS primitive for a memory mapped file.
41 : class SharedMemory {
42 : public:
43 : // Create a new SharedMemory object.
44 : SharedMemory();
45 :
46 : // Create a new SharedMemory object from an existing, open
47 : // shared memory file.
48 0 : SharedMemory(SharedMemoryHandle init_handle, bool read_only)
49 0 : : SharedMemory() {
50 0 : SetHandle(init_handle, read_only);
51 0 : }
52 :
53 : // Destructor. Will close any open files.
54 : ~SharedMemory();
55 :
56 : // Initialize a new SharedMemory object from an existing, open
57 : // shared memory file.
58 : bool SetHandle(SharedMemoryHandle handle, bool read_only);
59 :
60 : // Return true iff the given handle is valid (i.e. not the distingished
61 : // invalid value; NULL for a HANDLE and -1 for a file descriptor)
62 : static bool IsHandleValid(const SharedMemoryHandle& handle);
63 :
64 : // Return invalid handle (see comment above for exact definition).
65 : static SharedMemoryHandle NULLHandle();
66 :
67 : // Creates or opens a shared memory segment based on a name.
68 : // If read_only is true, opens the memory as read-only.
69 : // If open_existing is true, and the shared memory already exists,
70 : // opens the existing shared memory and ignores the size parameter.
71 : // If name is the empty string, use a unique name.
72 : // Returns true on success, false on failure.
73 : bool Create(const std::string& name, bool read_only, bool open_existing,
74 : size_t size);
75 :
76 : // Deletes resources associated with a shared memory segment based on name.
77 : // Not all platforms require this call.
78 : bool Delete(const std::wstring& name);
79 :
80 : // Opens a shared memory segment based on a name.
81 : // If read_only is true, opens for read-only access.
82 : // If name is the empty string, use a unique name.
83 : // Returns true on success, false on failure.
84 : bool Open(const std::wstring& name, bool read_only);
85 :
86 : // Maps the shared memory into the caller's address space.
87 : // Returns true on success, false otherwise. The memory address
88 : // is accessed via the memory() accessor.
89 : bool Map(size_t bytes);
90 :
91 : // Unmaps the shared memory from the caller's address space.
92 : // Returns true if successful; returns false on error or if the
93 : // memory is not mapped.
94 : bool Unmap();
95 :
96 : // Get the size of the opened shared memory backing file.
97 : // Note: This size is only available to the creator of the
98 : // shared memory, and not to those that opened shared memory
99 : // created externally.
100 : // Returns 0 if not opened or unknown.
101 : size_t max_size() const { return max_size_; }
102 :
103 : // Gets a pointer to the opened memory space if it has been
104 : // Mapped via Map(). Returns NULL if it is not mapped.
105 99 : void *memory() const { return memory_; }
106 :
107 : // Get access to the underlying OS handle for this segment.
108 : // Use of this handle for anything other than an opaque
109 : // identifier is not portable.
110 : SharedMemoryHandle handle() const;
111 :
112 : #if defined(OS_POSIX)
113 : // Return a unique identifier for this shared memory segment. Inode numbers
114 : // are technically only unique to a single filesystem. However, we always
115 : // allocate shared memory backing files from the same directory, so will end
116 : // up on the same filesystem.
117 : SharedMemoryId id() const { return inode_; }
118 : #endif
119 :
120 : // Closes the open shared memory segment.
121 : // It is safe to call Close repeatedly.
122 : void Close(bool unmap_view = true);
123 :
124 : // Share the shared memory to another process. Attempts
125 : // to create a platform-specific new_handle which can be
126 : // used in a remote process to access the shared memory
127 : // file. new_handle is an ouput parameter to receive
128 : // the handle for use in the remote process.
129 : // Returns true on success, false otherwise.
130 38 : bool ShareToProcess(base::ProcessId target_pid,
131 : SharedMemoryHandle* new_handle) {
132 38 : return ShareToProcessCommon(target_pid, new_handle, false);
133 : }
134 :
135 : // Logically equivalent to:
136 : // bool ok = ShareToProcess(process, new_handle);
137 : // Close();
138 : // return ok;
139 : // Note that the memory is unmapped by calling this method, regardless of the
140 : // return value.
141 : bool GiveToProcess(ProcessId target_pid,
142 : SharedMemoryHandle* new_handle) {
143 : return ShareToProcessCommon(target_pid, new_handle, true);
144 : }
145 :
146 : // Lock the shared memory.
147 : // This is a cross-process lock which may be recursively
148 : // locked by the same thread.
149 : // TODO(port):
150 : // WARNING: on POSIX the lock only works across processes, not
151 : // across threads. 2 threads in the same process can both grab the
152 : // lock at the same time. There are several solutions for this
153 : // (futex, lockf+anon_semaphore) but none are both clean and common
154 : // across Mac and Linux.
155 : void Lock();
156 :
157 : // Release the shared memory lock.
158 : void Unlock();
159 :
160 : private:
161 : #if defined(OS_POSIX)
162 : bool CreateOrOpen(const std::wstring &name, int posix_flags, size_t size);
163 : bool FilenameForMemoryName(const std::wstring &memname,
164 : std::wstring *filename);
165 : void LockOrUnlockCommon(int function);
166 :
167 : #endif
168 : bool ShareToProcessCommon(ProcessId target_pid,
169 : SharedMemoryHandle* new_handle,
170 : bool close_self);
171 :
172 : #if defined(OS_WIN)
173 : std::wstring name_;
174 : HANDLE mapped_file_;
175 : #elif defined(OS_POSIX)
176 : int mapped_file_;
177 : ino_t inode_;
178 : #endif
179 : void* memory_;
180 : bool read_only_;
181 : size_t max_size_;
182 : #if !defined(OS_POSIX)
183 : SharedMemoryLock lock_;
184 : #endif
185 :
186 : DISALLOW_EVIL_CONSTRUCTORS(SharedMemory);
187 : };
188 :
189 : // A helper class that acquires the shared memory lock while
190 : // the SharedMemoryAutoLock is in scope.
191 : class SharedMemoryAutoLock {
192 : public:
193 : explicit SharedMemoryAutoLock(SharedMemory* shared_memory)
194 : : shared_memory_(shared_memory) {
195 : shared_memory_->Lock();
196 : }
197 :
198 : ~SharedMemoryAutoLock() {
199 : shared_memory_->Unlock();
200 : }
201 :
202 : private:
203 : SharedMemory* shared_memory_;
204 : DISALLOW_EVIL_CONSTRUCTORS(SharedMemoryAutoLock);
205 : };
206 :
207 : } // namespace base
208 :
209 : #endif // BASE_SHARED_MEMORY_H_
|