Replace boost::variant with std::variant

This commit is contained in:
Alexey Rybalchenko 2023-09-15 12:37:19 +02:00
parent 8e430c4764
commit fc00f64f20
4 changed files with 59 additions and 102 deletions

View File

@ -21,7 +21,7 @@
#include <boost/interprocess/managed_shared_memory.hpp> #include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/mem_algo/simple_seq_fit.hpp> #include <boost/interprocess/mem_algo/simple_seq_fit.hpp>
#include <boost/unordered_map.hpp> #include <boost/unordered_map.hpp>
#include <boost/variant.hpp> #include <variant>
#include <sys/types.h> #include <sys/types.h>
@ -292,73 +292,7 @@ std::string makeShmIdStr(const std::string& sessionId);
std::string makeShmIdStr(uint64_t val); std::string makeShmIdStr(uint64_t val);
uint64_t makeShmIdUint64(const std::string& sessionId); uint64_t makeShmIdUint64(const std::string& sessionId);
struct SegmentBufferShrink
struct SegmentSize : public boost::static_visitor<size_t>
{
template<typename S>
size_t operator()(S& s) const { return s.get_size(); }
};
struct SegmentAddress : public boost::static_visitor<void*>
{
template<typename S>
void* operator()(S& s) const { return s.get_address(); }
};
struct SegmentMemoryZeroer : public boost::static_visitor<>
{
template<typename S>
void operator()(S& s) const { s.zero_free_memory(); }
};
struct SegmentFreeMemory : public boost::static_visitor<size_t>
{
template<typename S>
size_t operator()(S& s) const { return s.get_free_memory(); }
};
struct SegmentHandleFromAddress : public boost::static_visitor<boost::interprocess::managed_shared_memory::handle_t>
{
SegmentHandleFromAddress(const void* _ptr) : ptr(_ptr) {}
template<typename S>
boost::interprocess::managed_shared_memory::handle_t operator()(S& s) const { return s.get_handle_from_address(ptr); }
const void* ptr;
};
struct SegmentAddressFromHandle : public boost::static_visitor<char*>
{
SegmentAddressFromHandle(const boost::interprocess::managed_shared_memory::handle_t _handle) : handle(_handle) {}
template<typename S>
char* operator()(S& s) const { return reinterpret_cast<char*>(s.get_address_from_handle(handle)); }
const boost::interprocess::managed_shared_memory::handle_t handle;
};
struct SegmentAllocate : public boost::static_visitor<char*>
{
SegmentAllocate(const size_t _size) : size(_size) {}
template<typename S>
char* operator()(S& s) const { return reinterpret_cast<char*>(s.allocate(size)); }
const size_t size;
};
struct SegmentAllocateAligned : public boost::static_visitor<void*>
{
SegmentAllocateAligned(const size_t _size, const size_t _alignment) : size(_size), alignment(_alignment) {}
template<typename S>
void* operator()(S& s) const { return s.allocate_aligned(size, alignment); }
const size_t size;
const size_t alignment;
};
struct SegmentBufferShrink : public boost::static_visitor<char*>
{ {
SegmentBufferShrink(const size_t _new_size, char* _local_ptr) SegmentBufferShrink(const size_t _new_size, char* _local_ptr)
: new_size(_new_size) : new_size(_new_size)
@ -376,15 +310,28 @@ struct SegmentBufferShrink : public boost::static_visitor<char*>
mutable char* local_ptr; mutable char* local_ptr;
}; };
struct SegmentDeallocate : public boost::static_visitor<> // struct SegmentWrapper
{ // {
SegmentDeallocate(char* _ptr) : ptr(_ptr) {} // SegmentWrapper(boost::variant<RBTreeBestFitSegment, SimpleSeqFitSegment>&& _segment)
// : segment(std::move(_segment))
// , refCountPool(nullptr)
// {}
template<typename S> // void InitRefCountPoolSSF()
void operator()(S& s) const { return s.deallocate(ptr); } // {
// refCountPool = std::make_unique<boost::variant<RefCountPoolRBT, RefCountPoolSSF>>(
// RefCountPoolSSF(boost::get<SimpleSeqFitSegment>(segment).get_segment_manager()));
// }
char* ptr; // void InitRefCountPoolRBT()
}; // {
// refCountPool = std::make_unique<boost::variant<RefCountPoolRBT, RefCountPoolSSF>>(
// RefCountPoolRBT(boost::get<RBTreeBestFitSegment>(segment).get_segment_manager()));
// }
// boost::variant<SimpleSeqFitSegment, RBTreeBestFitSegment> segment;
// std::unique_ptr<boost::variant<RefCountPoolRBT, RefCountPoolSSF>> refCountPool;
// };
} // namespace fair::mq::shmem } // namespace fair::mq::shmem

View File

@ -24,7 +24,6 @@
#include <boost/interprocess/sync/interprocess_condition.hpp> #include <boost/interprocess/sync/interprocess_condition.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp> #include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/interprocess/sync/named_mutex.hpp> #include <boost/interprocess/sync/named_mutex.hpp>
#include <boost/variant.hpp>
#include <algorithm> // max #include <algorithm> // max
#include <chrono> #include <chrono>
@ -42,6 +41,7 @@
#include <tuple> #include <tuple>
#include <unordered_map> #include <unordered_map>
#include <utility> // pair #include <utility> // pair
#include <variant>
#include <vector> #include <vector>
#include <unistd.h> // getuid #include <unistd.h> // getuid
@ -193,8 +193,8 @@ class Manager
} }
} }
LOG(debug) << (createdSegment ? "Created" : "Opened") << " managed shared memory segment " << "fmq_" << fShmId << "_m_" << fSegmentId LOG(debug) << (createdSegment ? "Created" : "Opened") << " managed shared memory segment " << "fmq_" << fShmId << "_m_" << fSegmentId
<< ". Size: " << boost::apply_visitor(SegmentSize(), fSegments.at(fSegmentId)) << " bytes." << ". Size: " << std::visit([](auto& s) { return s.get_size(); }, fSegments.at(fSegmentId)) << " bytes."
<< " Available: " << boost::apply_visitor(SegmentFreeMemory(), fSegments.at(fSegmentId)) << " bytes." << " Available: " << std::visit([](auto& s) { return s.get_free_memory(); }, fSegments.at(fSegmentId)) << " bytes."
<< " Allocation algorithm: " << allocationAlgorithm; << " Allocation algorithm: " << allocationAlgorithm;
} catch (interprocess_exception& bie) { } catch (interprocess_exception& bie) {
LOG(error) << "Failed to create/open shared memory segment '" << "fmq_" << fShmId << "_m_" << fSegmentId << "': " << bie.what(); LOG(error) << "Failed to create/open shared memory segment '" << "fmq_" << fShmId << "_m_" << fSegmentId << "': " << bie.what();
@ -232,14 +232,16 @@ class Manager
void ZeroSegment(uint16_t id) void ZeroSegment(uint16_t id)
{ {
LOG(debug) << "Zeroing the managed segment free memory..."; LOG(debug) << "Zeroing the managed segment free memory...";
boost::apply_visitor(SegmentMemoryZeroer(), fSegments.at(id)); std::visit([](auto& s) { return s.zero_free_memory(); }, fSegments.at(id));
LOG(debug) << "Successfully zeroed the managed segment free memory."; LOG(debug) << "Successfully zeroed the managed segment free memory.";
} }
void MlockSegment(uint16_t id) void MlockSegment(uint16_t id)
{ {
LOG(debug) << "Locking the managed segment memory pages..."; LOG(debug) << "Locking the managed segment memory pages...";
if (mlock(boost::apply_visitor(SegmentAddress(), fSegments.at(id)), boost::apply_visitor(SegmentSize(), fSegments.at(id))) == -1) { if (mlock(
std::visit([](auto& s) { return s.get_address(); }, fSegments.at(id)),
std::visit([](auto& s) { return s.get_size(); }, fSegments.at(id))) == -1) {
LOG(error) << "Could not lock the managed segment memory. Code: " << errno << ", reason: " << strerror(errno); LOG(error) << "Could not lock the managed segment memory. Code: " << errno << ", reason: " << strerror(errno);
throw TransportError(tools::ToString("Could not lock the managed segment memory: ", strerror(errno))); throw TransportError(tools::ToString("Could not lock the managed segment memory: ", strerror(errno)));
} }
@ -456,8 +458,8 @@ class Manager
info.managed = true; info.managed = true;
info.id = segmentId; info.id = segmentId;
info.event = RegionEvent::created; info.event = RegionEvent::created;
info.ptr = boost::apply_visitor(SegmentAddress(), fSegments.at(segmentId)); info.ptr = std::visit([](auto& s) { return s.get_address(); }, fSegments.at(segmentId));
info.size = boost::apply_visitor(SegmentSize(), fSegments.at(segmentId)); info.size = std::visit([](auto& s) { return s.get_size(); }, fSegments.at(segmentId));
result.push_back(info); result.push_back(info);
} catch (const std::out_of_range& oor) { } catch (const std::out_of_range& oor) {
LOG(error) << "could not find segment with id " << segmentId; LOG(error) << "could not find segment with id " << segmentId;
@ -651,11 +653,11 @@ class Manager
boost::interprocess::managed_shared_memory::handle_t GetHandleFromAddress(const void* ptr, uint16_t segmentId) const boost::interprocess::managed_shared_memory::handle_t GetHandleFromAddress(const void* ptr, uint16_t segmentId) const
{ {
return boost::apply_visitor(SegmentHandleFromAddress(ptr), fSegments.at(segmentId)); return std::visit([ptr](auto& s) { return s.get_handle_from_address(ptr); }, fSegments.at(segmentId));
} }
char* GetAddressFromHandle(const boost::interprocess::managed_shared_memory::handle_t handle, uint16_t segmentId) const char* GetAddressFromHandle(const boost::interprocess::managed_shared_memory::handle_t handle, uint16_t segmentId) const
{ {
return boost::apply_visitor(SegmentAddressFromHandle(handle), fSegments.at(segmentId)); return std::visit([handle](auto& s) { return reinterpret_cast<char*>(s.get_address_from_handle(handle)); }, fSegments.at(segmentId));
} }
char* Allocate(size_t size, size_t alignment = 0) char* Allocate(size_t size, size_t alignment = 0)
@ -668,24 +670,32 @@ class Manager
while (!ptr) { while (!ptr) {
try { try {
size_t segmentSize = boost::apply_visitor(SegmentSize(), fSegments.at(fSegmentId)); size_t segmentSize = std::visit([](auto& s) { return s.get_size(); }, fSegments.at(fSegmentId));
if (fullSize > segmentSize) { if (fullSize > segmentSize) {
throw MessageBadAlloc(tools::ToString("Requested message size (", fullSize, ") exceeds segment size (", segmentSize, ")")); throw MessageBadAlloc(tools::ToString("Requested message size (", fullSize, ") exceeds segment size (", segmentSize, ")"));
} }
ptr = boost::apply_visitor(SegmentAllocate{fullSize}, fSegments.at(fSegmentId)); ptr = std::visit([fullSize](auto& s) { return reinterpret_cast<char*>(s.allocate(fullSize)); }, fSegments.at(fSegmentId));
ShmHeader::Construct(ptr, alignment); ShmHeader::Construct(ptr, alignment);
} catch (boost::interprocess::bad_alloc& ba) { } catch (boost::interprocess::bad_alloc& ba) {
// LOG(warn) << "Shared memory full..."; // LOG(warn) << "Shared memory full...";
if (fBadAllocMaxAttempts >= 0 && ++numAttempts >= fBadAllocMaxAttempts) { if (fBadAllocMaxAttempts >= 0 && ++numAttempts >= fBadAllocMaxAttempts) {
throw MessageBadAlloc(tools::ToString("shmem: could not create a message of size ", size, ", alignment: ", (alignment != 0) ? std::to_string(alignment) : "default", ", free memory: ", boost::apply_visitor(SegmentFreeMemory(), fSegments.at(fSegmentId)))); throw MessageBadAlloc(tools::ToString("shmem: could not create a message of size ", size,
", alignment: ", (alignment != 0) ? std::to_string(alignment) : "default",
", free memory: ", std::visit([](auto& s) { return s.get_free_memory(); }, fSegments.at(fSegmentId))));
} }
if (numAttempts == 1 && fBadAllocMaxAttempts > 1) { if (numAttempts == 1 && fBadAllocMaxAttempts > 1) {
LOG(warn) << tools::ToString("shmem: could not create a message of size ", size, ", alignment: ", (alignment != 0) ? std::to_string(alignment) : "default", ", free memory: ", boost::apply_visitor(SegmentFreeMemory(), fSegments.at(fSegmentId)), ". Will try ", (fBadAllocMaxAttempts > 1 ? (std::to_string(fBadAllocMaxAttempts - 1)) + " more times" : " until success"), ", in ", fBadAllocAttemptIntervalInMs, "ms intervals"); LOG(warn) << tools::ToString("shmem: could not create a message of size ", size,
", alignment: ", (alignment != 0) ? std::to_string(alignment) : "default",
", free memory: ", std::visit([](auto& s) { return s.get_free_memory(); }, fSegments.at(fSegmentId)),
". Will try ", (fBadAllocMaxAttempts > 1 ? (std::to_string(fBadAllocMaxAttempts - 1)) + " more times" : " until success"),
", in ", fBadAllocAttemptIntervalInMs, "ms intervals");
} }
std::this_thread::sleep_for(std::chrono::milliseconds(fBadAllocAttemptIntervalInMs)); std::this_thread::sleep_for(std::chrono::milliseconds(fBadAllocAttemptIntervalInMs));
if (Interrupted()) { if (Interrupted()) {
throw MessageBadAlloc(tools::ToString("shmem: could not create a message of size ", size, ", alignment: ", (alignment != 0) ? std::to_string(alignment) : "default", ", free memory: ", boost::apply_visitor(SegmentFreeMemory(), fSegments.at(fSegmentId)))); throw MessageBadAlloc(tools::ToString("shmem: could not create a message of size ", size,
", alignment: ", (alignment != 0) ? std::to_string(alignment) : "default",
", free memory: ", std::visit([](auto& s) { return s.get_free_memory(); }, fSegments.at(fSegmentId))));
} else { } else {
continue; continue;
} }
@ -719,12 +729,12 @@ class Manager
} }
#endif #endif
ShmHeader::Destruct(ptr); ShmHeader::Destruct(ptr);
boost::apply_visitor(SegmentDeallocate(ptr), fSegments.at(segmentId)); std::visit([ptr](auto& s) { s.deallocate(ptr); }, fSegments.at(segmentId));
} }
char* ShrinkInPlace(size_t newSize, char* localPtr, uint16_t segmentId) char* ShrinkInPlace(size_t newSize, char* localPtr, uint16_t segmentId)
{ {
return boost::apply_visitor(SegmentBufferShrink(newSize, localPtr), fSegments.at(segmentId)); return std::visit(SegmentBufferShrink(newSize, localPtr), fSegments.at(segmentId));
} }
uint16_t GetSegmentId() const { return fSegmentId; } uint16_t GetSegmentId() const { return fSegmentId; }
@ -772,7 +782,7 @@ class Manager
uint64_t fShmId64; uint64_t fShmId64;
std::string fShmId; std::string fShmId;
uint16_t fSegmentId; uint16_t fSegmentId;
std::unordered_map<uint16_t, boost::variant<RBTreeBestFitSegment, SimpleSeqFitSegment>> fSegments; // TODO: refactor to use Segment class std::unordered_map<uint16_t, std::variant<RBTreeBestFitSegment, SimpleSeqFitSegment>> fSegments; // TODO: refactor to use Segment class
boost::interprocess::managed_shared_memory fManagementSegment; // TODO: refactor to use ManagementSegment class boost::interprocess::managed_shared_memory fManagementSegment; // TODO: refactor to use ManagementSegment class
VoidAlloc fShmVoidAlloc; VoidAlloc fShmVoidAlloc;
boost::interprocess::interprocess_mutex* fShmMtx; boost::interprocess::interprocess_mutex* fShmMtx;

View File

@ -30,6 +30,7 @@
#include <ctime> #include <ctime>
#include <iomanip> #include <iomanip>
#include <sstream> #include <sstream>
#include <variant>
#include <poll.h> #include <poll.h>
@ -184,7 +185,7 @@ bool Monitor::PrintShm(const ShmId& shmId)
VoidAlloc allocInstance(managementSegment.get_segment_manager()); VoidAlloc allocInstance(managementSegment.get_segment_manager());
Uint16SegmentInfoHashMap* shmSegments = managementSegment.find<Uint16SegmentInfoHashMap>(unique_instance).first; Uint16SegmentInfoHashMap* shmSegments = managementSegment.find<Uint16SegmentInfoHashMap>(unique_instance).first;
std::unordered_map<uint16_t, boost::variant<RBTreeBestFitSegment, SimpleSeqFitSegment>> segments; std::unordered_map<uint16_t, std::variant<RBTreeBestFitSegment, SimpleSeqFitSegment>> segments;
Uint16RegionInfoHashMap* shmRegions = managementSegment.find<Uint16RegionInfoHashMap>(unique_instance).first; Uint16RegionInfoHashMap* shmRegions = managementSegment.find<Uint16RegionInfoHashMap>(unique_instance).first;
@ -234,8 +235,8 @@ bool Monitor::PrintShm(const ShmId& shmId)
<< ", managed segments:\n"; << ", managed segments:\n";
for (const auto& s : segments) { for (const auto& s : segments) {
size_t free = boost::apply_visitor(SegmentFreeMemory(), s.second); size_t free = std::visit([](auto& s){ return s.get_free_memory(); }, s.second);
size_t total = boost::apply_visitor(SegmentSize(), s.second); size_t total = std::visit([](auto& s){ return s.get_size(); }, s.second);
size_t used = total - free; size_t used = total - free;
std::string msgCount; std::string msgCount;

View File

@ -11,10 +11,9 @@
#include <fairmq/shmem/Common.h> #include <fairmq/shmem/Common.h>
#include <fairmq/shmem/Monitor.h> #include <fairmq/shmem/Monitor.h>
#include <boost/variant.hpp>
#include <cstdint> #include <cstdint>
#include <string> #include <string>
#include <variant>
namespace fair::mq::shmem namespace fair::mq::shmem
{ {
@ -44,12 +43,12 @@ struct Segment
Register(shmId, id, AllocationAlgorithm::rbtree_best_fit); Register(shmId, id, AllocationAlgorithm::rbtree_best_fit);
} }
size_t GetSize() const { return boost::apply_visitor(SegmentSize(), fSegment); } size_t GetSize() const { return std::visit([](auto& s){ return s.get_size(); }, fSegment); }
void* GetData() { return boost::apply_visitor(SegmentAddress(), fSegment); } void* GetData() { return std::visit([](auto& s){ return s.get_address(); }, fSegment); }
size_t GetFreeMemory() const { return boost::apply_visitor(SegmentFreeMemory(), fSegment); } size_t GetFreeMemory() const { return std::visit([](auto& s){ return s.get_free_memory(); }, fSegment); }
void Zero() { boost::apply_visitor(SegmentMemoryZeroer(), fSegment); } void Zero() { std::visit([](auto& s){ return s.zero_free_memory(); }, fSegment); }
void Lock() void Lock()
{ {
if (mlock(GetData(), GetSize()) == -1) { if (mlock(GetData(), GetSize()) == -1) {
@ -63,7 +62,7 @@ struct Segment
} }
private: private:
boost::variant<RBTreeBestFitSegment, SimpleSeqFitSegment> fSegment; std::variant<RBTreeBestFitSegment, SimpleSeqFitSegment> fSegment;
static void Register(const std::string& shmId, uint16_t id, AllocationAlgorithm allocAlgo) static void Register(const std::string& shmId, uint16_t id, AllocationAlgorithm allocAlgo)
{ {