shm.h 2.47 KB
/*
 * shm.h
 *
 *  Created on: 15 gru 2018
 *      Author: mariuszo
 */

#ifndef SHM_H_
#define SHM_H_

#include <string>
#include <map>
#include <mutex>
#include <fcntl.h>
/*
#include <typeinfo>
*/
class shm {
protected:
	struct shmInUse {
		shm* obj;
		uint32_t count;
		bool unlink;
		shmInUse():obj(NULL),count(0),unlink(false){}
	};
	static std::map<std::string, shmInUse> inProcessMapping;
	static std::recursive_mutex inProcessMappingLock;
	const std::string m_name;
	int m_flags;
	mode_t m_mode;
	void* m_data;
	size_t m_size;
public:
	shm(const std::string& name, int flags=O_RDWR, mode_t mode=S_IRUSR|S_IWUSR);
	virtual ~shm() {free();}

	virtual bool alloc(const size_t& size);
	virtual bool attach();
	void unlink();
	void* getAddr(const off_t& offset=0) const {return (uint8_t*)m_data+offset;}
	template <typename T> T* getAddr(const off_t& offset=0) const {return (T*)getAddr(offset*sizeof(T));}
	size_t getSize() const {return m_size;}
	const std::string& getName() const {return m_name;}
	virtual bool mlock();
	virtual void munlock();
	virtual void free();
	friend class shmLog;
	friend class shmTimeLog;
};

class shmRing : public shm {
protected:
	void* m_placeholder;
	size_t m_placeholderSize;
	void* m_data2;
public:
	shmRing(const std::string& name, int flags=O_RDWR, mode_t mode=S_IRUSR|S_IWUSR);
	virtual ~shmRing() {}

	virtual bool alloc(const size_t& size);
	virtual bool attach();
	virtual bool mlock();
	virtual void munlock();
	virtual void free();
	friend class shmLog;
	friend class shmTimeLog;
};

template <typename T> class shm_t:private shm {
	size_t elements;
public:
	shm_t(const std::string& name, int flags=O_RDWR, mode_t mode=S_IRUSR|S_IWUSR):shm(name, flags, mode), elements(0){}
	void unlink() { shm::unlink();}
	bool alloc(const size_t& size){
		elements=size;
		if (!shm::alloc(size*sizeof(T)+sizeof(size_t)))
			return false;
		*((size_t*)m_data)=typeid(T).hash_code();
		return true;
	}
	bool attach(){
		if (!shm::attach())
			return false;
		if (*((size_t*)m_data)!=typeid(T).hash_code())
			return false;
		elements=m_size/sizeof(T);
		return true;
	}
	T* getAddr(const off_t& offset=0) const {return (T*)shm::getAddr(offset*sizeof(T)+sizeof(size_t));}
	const size_t& getSize() const {return elements;}
	bool mlock(){return shm::mlock();}
	void munlock(){shm::munlock();}
	void free(){shm::free();}
	T* operator->() const {return getAddr();}
	T& operator[](const off_t& id) const {return *getAddr(id);}
	friend class shmLog;
	friend class shmTimeLog;
};

#endif /* SHM_H_ */