Home | History | Annotate | Download | only in base
      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 
     20 class FilePath;
     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   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.
    192 class 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