8 #ifndef FAIR_MQ_SHMEM_COMMON_H_
9 #define FAIR_MQ_SHMEM_COMMON_H_
18 #include <boost/functional/hash.hpp>
19 #include <boost/interprocess/allocators/allocator.hpp>
20 #include <boost/interprocess/containers/map.hpp>
21 #include <boost/interprocess/containers/string.hpp>
22 #include <boost/interprocess/containers/vector.hpp>
23 #include <boost/interprocess/indexes/null_index.hpp>
24 #include <boost/interprocess/managed_shared_memory.hpp>
25 #include <boost/interprocess/mem_algo/simple_seq_fit.hpp>
26 #include <boost/unordered_map.hpp>
27 #include <boost/variant.hpp>
30 #include <sys/types.h>
35 struct SharedMemoryError : std::runtime_error {
using std::runtime_error::runtime_error; };
37 using SimpleSeqFitSegment = boost::interprocess::basic_managed_shared_memory<char,
38 boost::interprocess::simple_seq_fit<boost::interprocess::mutex_family>,
39 boost::interprocess::null_index>;
41 using RBTreeBestFitSegment = boost::interprocess::basic_managed_shared_memory<char,
42 boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>,
43 boost::interprocess::null_index>;
46 using SegmentManager = boost::interprocess::managed_shared_memory::segment_manager;
47 using VoidAlloc = boost::interprocess::allocator<void, SegmentManager>;
48 using CharAlloc = boost::interprocess::allocator<char, SegmentManager>;
49 using Str = boost::interprocess::basic_string<char, std::char_traits<char>, CharAlloc>;
50 using StrAlloc = boost::interprocess::allocator<Str, SegmentManager>;
51 using StrVector = boost::interprocess::vector<Str, StrAlloc>;
53 enum class AllocationAlgorithm : int
68 RegionInfo(
const char* path,
const int flags,
const uint64_t userFlags,
const VoidAlloc& alloc)
71 , fUserFlags(userFlags)
81 using Uint16RegionInfoPairAlloc = boost::interprocess::allocator<std::pair<const uint16_t, RegionInfo>, SegmentManager>;
82 using Uint16RegionInfoMap = boost::interprocess::map<uint16_t, RegionInfo, std::less<uint16_t>, Uint16RegionInfoPairAlloc>;
83 using Uint16RegionInfoHashMap = boost::unordered_map<uint16_t, RegionInfo, boost::hash<uint16_t>, std::equal_to<uint16_t>, Uint16RegionInfoPairAlloc>;
87 SegmentInfo(AllocationAlgorithm aa)
88 : fAllocationAlgorithm(aa)
91 AllocationAlgorithm fAllocationAlgorithm;
94 using Uint16SegmentInfoPairAlloc = boost::interprocess::allocator<std::pair<const uint16_t, SegmentInfo>, SegmentManager>;
95 using Uint16SegmentInfoHashMap = boost::unordered_map<uint16_t, SegmentInfo, boost::hash<uint16_t>, std::equal_to<uint16_t>, Uint16SegmentInfoPairAlloc>;
104 std::atomic<unsigned int> fCount;
113 std::atomic<uint64_t> fCount;
122 std::atomic<uint16_t> fCount;
131 boost::interprocess::managed_shared_memory::handle_t fHandle;
134 #ifdef FAIRMQ_DEBUG_MODE
141 MsgCounter(
unsigned int c)
145 std::atomic<unsigned int> fCount;
148 using Uint16MsgCounterPairAlloc = boost::interprocess::allocator<std::pair<const uint16_t, MsgCounter>, SegmentManager>;
149 using Uint16MsgCounterHashMap = boost::unordered_map<uint16_t, MsgCounter, boost::hash<uint16_t>, std::equal_to<uint16_t>, Uint16MsgCounterPairAlloc>;
159 MsgDebug(pid_t pid,
size_t size,
const uint64_t creationTime)
162 , fCreationTime(creationTime)
167 uint64_t fCreationTime;
170 using SizetMsgDebugPairAlloc = boost::interprocess::allocator<std::pair<const size_t, MsgDebug>, SegmentManager>;
172 using SizetMsgDebugMap = boost::interprocess::map<size_t, MsgDebug, std::less<size_t>, SizetMsgDebugPairAlloc>;
173 using Uint16MsgDebugMapPairAlloc = boost::interprocess::allocator<std::pair<const uint16_t, SizetMsgDebugMap>, SegmentManager>;
174 using Uint16MsgDebugMapHashMap = boost::unordered_map<uint16_t, SizetMsgDebugMap, boost::hash<uint16_t>, std::equal_to<uint16_t>, Uint16MsgDebugMapPairAlloc>;
185 RegionBlock(boost::interprocess::managed_shared_memory::handle_t handle,
size_t size,
size_t hint)
191 boost::interprocess::managed_shared_memory::handle_t fHandle;
198 inline std::string makeShmIdStr(
const std::string& sessionId)
200 std::string seed((std::to_string(geteuid()) + sessionId));
202 std::vector<unsigned char> hash(4);
203 picosha2::hash256(seed.begin(), seed.end(), hash.begin(), hash.end());
205 return picosha2::bytes_to_hex_string(hash.begin(), hash.end());
208 inline uint64_t makeShmIdUint64(
const std::string& sessionId)
210 std::string shmId = makeShmIdStr(sessionId);
212 std::stringstream ss;
213 ss << std::hex << shmId;
219 struct SegmentSize :
public boost::static_visitor<size_t>
222 size_t operator()(S& s)
const {
return s.get_size(); }
228 void* operator()(S& s)
const {
return s.get_address(); }
234 void operator()(S& s)
const { s.zero_free_memory(); }
240 size_t operator()(S& s)
const {
return s.get_free_memory(); }
248 boost::interprocess::managed_shared_memory::handle_t operator()(S& s)
const {
return s.get_handle_from_address(ptr); }
258 void* operator()(S& s)
const {
return s.get_address_from_handle(handle); }
260 const boost::interprocess::managed_shared_memory::handle_t handle;
268 void* operator()(S& s)
const {
return s.allocate(size); }
275 SegmentAllocateAligned(
const size_t _size,
const size_t _alignment) : size(_size), alignment(_alignment) {}
278 void* operator()(S& s)
const {
return s.allocate_aligned(size, alignment); }
281 const size_t alignment;
287 : new_size(_new_size)
288 , local_ptr(_local_ptr)
292 char* operator()(S& s)
const
294 boost::interprocess::managed_shared_memory::size_type shrunk_size = new_size;
295 return s.template allocation_command<char>(boost::interprocess::shrink_in_place, new_size + 128, shrunk_size, local_ptr);
298 const size_t new_size;
299 mutable char* local_ptr;
302 struct SegmentDeallocate :
public boost::static_visitor<>
304 SegmentDeallocate(
void* _ptr) : ptr(_ptr) {}
307 void operator()(S& s)
const {
return s.deallocate(ptr); }