Skip to content

Instantly share code, notes, and snippets.

@eruffaldi
Created March 6, 2017 12:54
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eruffaldi/710a70aa169b9c2a2d687be805f6d01e to your computer and use it in GitHub Desktop.
Save eruffaldi/710a70aa169b9c2a2d687be805f6d01e to your computer and use it in GitHub Desktop.
Cross Platform Shared Memory and Mutex (alternative to using boost/interprocess
/**
* 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