Instantly share code, notes, and snippets.
Created
March 6, 2017 12:54
-
Save eruffaldi/710a70aa169b9c2a2d687be805f6d01e to your computer and use it in GitHub Desktop.
Cross Platform Shared Memory and Mutex (alternative to using boost/interprocess
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Emanuele Ruffaldi 2009-2015 | |
* | |
* C++ Shared Memory Class Cross Platform | |
* | |
* Windows: files and named shared memories + named mutex | |
* Linux: N/A | |
* OSX: N/A | |
* | |
*/ | |
#ifndef SHAREDMEMORY_H | |
#define SHAREDMEMORY_H | |
#include <iostream> | |
#ifdef WIN32 | |
#include <windows.h> | |
#else | |
# include <string> | |
# include <fcntl.h> //O_CREAT, O_*... | |
# include <sys/mman.h> //shm_xxx | |
# include <unistd.h> //ftruncate, close | |
# include <sys/stat.h> //mode_t, S_IRWXG, S_IRWXO, S_IRWXU, | |
#endif | |
namespace Tesla | |
{ | |
class SharedMutex | |
{ | |
public: | |
struct ScopedLock | |
{ | |
SharedMutex & m_; | |
ScopedLock(SharedMutex & m) : m_(m) { m.lock(); } | |
~ScopedLock() { m_.unlock(); } | |
}; | |
SharedMutex(const char * name) { | |
#ifdef WIN32 | |
h_ = CreateMutex(0,FALSE,name); | |
if(h_ == 0 || h_ == INVALID_HANDLE_VALUE) | |
h_ = OpenMutex(SYNCHRONIZE,FALSE,name); | |
#endif | |
} | |
~SharedMutex() { | |
#ifdef WIN32 | |
CloseHandle(h_); | |
#endif | |
} | |
void lock() | |
{ | |
#ifdef WIN32 | |
WaitForSingleObject(h_,INFINITE); | |
#endif | |
} | |
void unlock() | |
{ | |
#ifdef WIN32 | |
ReleaseMutex(h_); | |
#endif | |
} | |
HANDLE h_; | |
}; | |
/** simplified class for shared memory | |
- file mapped | |
- bulk memory | |
*/ | |
class SharedMemory | |
{ | |
public: | |
// just empty | |
SharedMemory(); | |
// release resources | |
~SharedMemory(); | |
int size() const { return _size; } | |
/// release resources | |
void close(); | |
/// try to open an existing mapping or create a new one. Use name = NULL for unnamed | |
void * mapMemory(const char * name, int size); | |
/// try to map a file as mapname | |
void * mapFile(const char * name,const char*mapname=NULL,bool readOnly = false); | |
#ifdef WIN32 | |
HANDLE _hmap; | |
HANDLE _hfile; | |
#else | |
int _hfile; | |
std::string _name; | |
#endif | |
void * _data; | |
int _size; | |
}; | |
inline SharedMemory::SharedMemory() | |
{ | |
_size = 0; | |
_data = 0; | |
#ifdef WIN32 | |
_hmap = 0; | |
_hfile = 0; | |
#else | |
_hfile = 0; | |
#endif | |
} | |
SharedMemory::~SharedMemory() | |
{ | |
close(); | |
} | |
/// release resources | |
void SharedMemory::close() | |
{ | |
#ifdef WIN32 | |
if(_hmap != 0) | |
{ | |
CloseHandle(_hmap); | |
_hmap = 0; | |
} | |
if(_hfile != 0) | |
{ | |
CloseHandle(_hfile); | |
_hfile = 0; | |
} | |
if(_data != 0) | |
{ | |
UnmapViewOfFile(_data); | |
_data = 0; | |
} | |
#else | |
if(!_name.empty()) | |
{ | |
shm_unlink(_name.c_str()); | |
_name = ""; | |
_data = 0; | |
} | |
else | |
::close(_hfile); | |
#endif | |
} | |
/// create a shared memory file or open existing | |
void * SharedMemory::mapMemory(const char * name, int size) | |
{ | |
close(); | |
#ifdef WIN32 | |
HANDLE h = OpenFileMapping(FILE_MAP_ALL_ACCESS, TRUE, name); | |
if(h == 0) | |
{ | |
h = CreateFileMapping(INVALID_HANDLE_VALUE,0,PAGE_READWRITE,0,size,name); | |
if(h == 0) | |
{ | |
printf("Cannot Create/Open SharedMemory %s of size %d",name,size); | |
exit(-1); | |
} | |
} | |
_hmap = h; | |
_size = size; | |
if(h != 0) | |
{ | |
_data = MapViewOfFile(_hmap,FILE_MAP_ALL_ACCESS,0,0,size); | |
if(_data == 0) | |
{ | |
printf("Cannot Map %s of size %d",name,size); | |
exit(-1); | |
} | |
} | |
printf("crated map %s of size %d with handle %p pointer %p\n",name,size,h,_data); | |
#else | |
/* | |
if((_hfile = shm_open(name,O_RDWR|O_CREA)) >= 0) | |
{ | |
_data = mmap(NULL, _size, PROT_READ | (readOnly ? 0:PROT_WRITE), MAP_SHARED, _hfile, 0); | |
_name = name; | |
} | |
else | |
{ | |
std::cout << "failed shm_open " << name << " " << _hfile << " " << errno << std::endl; | |
_data = 0; | |
} | |
*/ | |
#endif | |
return _data; | |
} | |
/// open a file | |
void * SharedMemory::mapFile(const char * name,const char*mapname, bool readOnly) | |
{ | |
close(); | |
#ifdef WIN32 | |
// stat | |
WIN32_FILE_ATTRIBUTE_DATA fileInfo; | |
if(!GetFileAttributesEx(name, GetFileExInfoStandard, (void*)&fileInfo)) | |
return 0; | |
_size = (long)fileInfo.nFileSizeLow; | |
// shm_open(name, readOnly ? O_RDONLY:O_RDWR, S_IRWXO | S_IRWXG | S_IRWXU); | |
_hfile = CreateFile(name,readOnly ? GENERIC_READ:GENERIC_READ|GENERIC_WRITE,readOnly? FILE_SHARE_READ:FILE_SHARE_READ|FILE_SHARE_WRITE,0,OPEN_EXISTING,0,0); | |
if(_hfile == INVALID_HANDLE_VALUE) | |
{ | |
_hfile = 0; | |
return 0; | |
} | |
_hmap = CreateFileMapping(_hfile,0,readOnly ? PAGE_READONLY: PAGE_READWRITE,0,0,mapname); | |
if(_hmap != 0) | |
_data = MapViewOfFile(_hmap,readOnly? FILE_MAP_READ:FILE_MAP_WRITE,0,0,0); | |
#else | |
struct stat st; | |
if (stat(name, &st) == 0) | |
_size = st.st_size; | |
else | |
return 0; | |
if((_hfile = open(name,readOnly ? O_RDONLY: O_RDWR)) >= 0) | |
{ | |
_data = mmap(NULL, _size, PROT_READ | (readOnly ? 0:PROT_WRITE), MAP_SHARED, _hfile, 0); | |
_name = ""; | |
} | |
else | |
{ | |
std::cout << "failed shm_open " << name << " " << _hfile << " " << std::endl; // << errno << std::endl; | |
} | |
#endif | |
return _data; | |
} | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment