/* Copyright (C) 2004-2008 Grame This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __JackShmMem__ #define __JackShmMem__ #include "shm.h" #include "JackError.h" #include "JackCompilerDeps.h" #include // GCC 4.0 #include #include #include "JackShmMem_os.h" namespace Jack { void LockMemoryImp(void* ptr, size_t size); void InitLockMemoryImp(void* ptr, size_t size); void UnlockMemoryImp(void* ptr, size_t size); void LockAllMemory(); void UnlockAllMemory(); /*! \brief A class which objects possibly want to be allocated in shared memory derives from this class. */ class JackShmMemAble { protected: jack_shm_info_t fInfo; public: void Init(); int GetShmIndex() { return fInfo.index; } char* GetShmAddress() { return (char*)fInfo.ptr.attached_at; } void LockMemory() { LockMemoryImp(this, fInfo.size); } void UnlockMemory() { UnlockMemoryImp(this, fInfo.size); } }; /*! \brief The base class for shared memory management. A class which objects need to be allocated in shared memory derives from this class. */ class SERVER_EXPORT JackShmMem : public JackShmMemAble { protected: JackShmMem(); ~JackShmMem(); public: void* operator new(size_t size); void* operator new(size_t size, void* memory); void operator delete(void* p, size_t size); void operator delete(void* p); }; /*! \brief Pointer on shared memory segment in the client side. */ template class JackShmReadWritePtr { private: jack_shm_info_t fInfo; bool fInitDone; void Init(int index, const char* server_name = JACK_DEFAULT_SERVER_NAME) { if (fInfo.index < 0 && index >= 0) { jack_log("JackShmReadWritePtr::Init %ld %d", index, fInfo.index); if (jack_initialize_shm(server_name) < 0) { throw std::bad_alloc(); } fInfo.index = index; if (jack_attach_lib_shm(&fInfo)) { throw std::bad_alloc(); } GetShmAddress()->LockMemory(); fInitDone = true; } } public: JackShmReadWritePtr() { fInfo.index = -1; fInitDone = false; fInfo.ptr.attached_at = (char*)NULL; } JackShmReadWritePtr(int index, const char* server_name) { Init(index, server_name); } ~JackShmReadWritePtr() { if (!fInitDone) { jack_error("JackShmReadWritePtr::~JackShmReadWritePtr - Init not done for %d, skipping unlock", fInfo.index); return; } if (fInfo.index >= 0) { jack_log("JackShmReadWritePtr::~JackShmReadWritePtr %d", fInfo.index); GetShmAddress()->UnlockMemory(); jack_release_lib_shm(&fInfo); fInfo.index = -1; } } T* operator->() const { return (T*)fInfo.ptr.attached_at; } operator T*() const { return (T*)fInfo.ptr.attached_at; } JackShmReadWritePtr& operator=(int index) { Init(index); return *this; } void SetShmIndex(int index, const char* server_name) { Init(index, server_name); } int GetShmIndex() { return fInfo.index; } T* GetShmAddress() { return (T*)fInfo.ptr.attached_at; } }; /*! \brief Pointer on shared memory segment in the client side: destroy the segment (used client control) */ template class JackShmReadWritePtr1 { private: jack_shm_info_t fInfo; bool fInitDone; void Init(int index, const char* server_name = JACK_DEFAULT_SERVER_NAME) { if (fInfo.index < 0 && index >= 0) { jack_log("JackShmReadWritePtr1::Init %ld %d", index, fInfo.index); if (jack_initialize_shm(server_name) < 0) { throw std::bad_alloc(); } fInfo.index = index; if (jack_attach_lib_shm(&fInfo)) { throw std::bad_alloc(); } GetShmAddress()->LockMemory(); fInitDone = true; /* nobody else needs to access this shared memory any more, so destroy it. because we have our own attachment to it, it won't vanish till we exit (and release it). */ jack_destroy_shm(&fInfo); } } public: JackShmReadWritePtr1() { fInfo.index = -1; fInitDone = false; fInfo.ptr.attached_at = NULL; } JackShmReadWritePtr1(int index, const char* server_name) { Init(index, server_name); } ~JackShmReadWritePtr1() { if (!fInitDone) { jack_error("JackShmReadWritePtr1::~JackShmReadWritePtr1 - Init not done for %d, skipping unlock", fInfo.index); return; } if (fInfo.index >= 0) { jack_log("JackShmReadWritePtr1::~JackShmReadWritePtr1 %d", fInfo.index); GetShmAddress()->UnlockMemory(); jack_release_lib_shm(&fInfo); fInfo.index = -1; } } T* operator->() const { return (T*)fInfo.ptr.attached_at; } operator T*() const { return (T*)fInfo.ptr.attached_at; } JackShmReadWritePtr1& operator=(int index) { Init(index); return *this; } void SetShmIndex(int index, const char* server_name) { Init(index, server_name); } int GetShmIndex() { return fInfo.index; } T* GetShmAddress() { return (T*)fInfo.ptr.attached_at; } }; /*! \brief Pointer on shared memory segment in the client side. */ template class JackShmReadPtr { private: jack_shm_info_t fInfo; bool fInitDone; void Init(int index, const char* server_name = JACK_DEFAULT_SERVER_NAME) { if (fInfo.index < 0 && index >= 0) { jack_log("JackShmPtrRead::Init %ld %d", index, fInfo.index); if (jack_initialize_shm(server_name) < 0) { throw std::bad_alloc(); } fInfo.index = index; if (jack_attach_lib_shm_read(&fInfo)) { throw std::bad_alloc(); } GetShmAddress()->LockMemory(); fInitDone = true; } } public: JackShmReadPtr() { fInfo.index = -1; fInitDone = false; fInfo.ptr.attached_at = NULL; } JackShmReadPtr(int index, const char* server_name) { Init(index, server_name); } ~JackShmReadPtr() { if (!fInitDone) { jack_error("JackShmReadPtr::~JackShmReadPtr - Init not done for %ld, skipping unlock", fInfo.index); return; } if (fInfo.index >= 0) { jack_log("JackShmPtrRead::~JackShmPtrRead %ld", fInfo.index); GetShmAddress()->UnlockMemory(); jack_release_lib_shm(&fInfo); fInfo.index = -1; } } T* operator->() const { return (T*)fInfo.ptr.attached_at; } operator T*() const { return (T*)fInfo.ptr.attached_at; } JackShmReadPtr& operator=(int index) { Init(index); return *this; } void SetShmIndex(int index, const char* server_name) { Init(index, server_name); } int GetShmIndex() { return fInfo.index; } T* GetShmAddress() { return (T*)fInfo.ptr.attached_at; } }; } // end of namespace #endif