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