| // |
| // Copyright 2005 The Android Open Source Project |
| // |
| // Inter-process shared memory. |
| // |
| #ifndef __LIBS_SHMEM_H |
| #define __LIBS_SHMEM_H |
| |
| #ifdef HAVE_ANDROID_OS |
| #error DO NOT USE THIS FILE IN THE DEVICE BUILD |
| #endif |
| |
| #include "Semaphore.h" |
| |
| namespace android { |
| |
| /* |
| * Platform-independent shared memory. Each object can be used to |
| * create a chunk of memory that is shared between processes. |
| * |
| * For convenience, a semaphore is associated with each segment. |
| * (Whether this should have been done in a subclass is debatable.) |
| * |
| * The "key" is usually the process ID of the process that created the |
| * segment. The goal is to avoid clashing with other processes that are |
| * trying to do the same thing. It's a little awkward to use when you |
| * want to have multiple shared segments created in one process. In |
| * SysV you can work around this by using a "private" key and sharing |
| * the shmid with your friends, in Win32 you can use a string, but we're |
| * in lowest-common-denominator mode here. Assuming we have 16-bit PIDs, |
| * the upper 16 bits can be used to serialize keys. |
| * |
| * When the object goes out of scope, the shared memory segment is |
| * detached from the process. If the object was responsible for creating |
| * the segment, it is also marked for destruction on SysV systems. This |
| * will make it impossible for others to attach to. |
| * |
| * On some systems, the length returned by getLength() may be different |
| * for parent and child due to page size rounding. |
| */ |
| class Shmem { |
| public: |
| Shmem(void); |
| virtual ~Shmem(void); |
| |
| /* |
| * Create a new shared memory segment, with the specified size. If |
| * "deleteExisting" is set, any existing segment will be deleted first |
| * (useful for SysV IPC). |
| * |
| * Returns "true" on success, "false" on failure. |
| */ |
| bool create(int key, long size, bool deleteExisting); |
| |
| /* |
| * Attach to a shared memory segment. Use this from the process that |
| * didn't create the segment. |
| * |
| * Returns "true" on success, "false" on failure. |
| */ |
| bool attach(int key); |
| |
| /* |
| * Get the memory segment address and length. These will not change |
| * for the lifetime of the object, so it's okay to cache the results. |
| * |
| * On failure, getAddr() returns NULL and getLength() returns -1. |
| */ |
| void* getAddr(void); |
| long getLength(void); |
| |
| /* |
| * Lock or unlock the shared memory segment. This is useful if you |
| * are updating pieces of shared data. The segment is initially |
| * "unlocked". |
| * |
| * This does *not* lock down the segment in the virtual paging system. |
| * It's just a mutex. |
| */ |
| void lock(void); |
| void unlock(void); |
| bool tryLock(void); |
| |
| private: |
| Semaphore mSem; // uses the same value for "key" |
| unsigned long mHandle; // shmid(int) or HANDLE |
| void* mAddr; // address |
| long mLength; // length of segment (cached) |
| bool mCreator; // true if we created the segment |
| int mKey; // key passed in as arg |
| }; |
| |
| }; // namespace android |
| |
| #endif // __LIBS_SHMEM_H |