boost.
, , (, , ). .
The main disadvantage of the following implementation is that theoretically the total memory of the client (and not the manager) can be opened before the server (which processes the shared memory) completes the initialization.
Oh, I just print the run index in base 0, just for demonstration. Here is the code.
#include <cstring>
#include <iostream>
#include <thread>
#include <chrono>
#include <mutex>
#include <condition_variable>
#include <csignal>
#include <boost/process.hpp>
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
static constexpr const char* daemonizer_string = "--daemon";
static constexpr const char* shared_memory_name = "shared_memory";
static std::mutex waiter_mutex;
static std::condition_variable waiter_cv;
struct shared_data_type
{
std::size_t count = 0;
};
extern "C"
void signal_handler(int)
{
waiter_cv.notify_one();
}
int main(int argc, const char* argv[])
{
namespace bp = boost::process;
namespace bi = boost::interprocess;
if(argc == 2 and std::strcmp(argv[1], daemonizer_string) == 0)
{
struct shm_remove
{
shm_remove() { bi::shared_memory_object::remove("shared_memory"); }
~shm_remove() { bi::shared_memory_object::remove("shared_memory"); }
} shm_remover;
bi::shared_memory_object shm(bi::create_only, shared_memory_name, bi::read_write);
shm.truncate(sizeof(shared_data_type));
bi::mapped_region region(shm, bi::read_write);
void* region_address = region.get_address();
shared_data_type* shared_data = new (region_address) shared_data_type;
std::signal(SIGTERM, signal_handler);
{
std::unique_lock<std::mutex> lock(waiter_mutex);
waiter_cv.wait(lock);
}
shared_data->~shared_data_type();
}
else
{
bi::shared_memory_object shm;
try
{
shm = bi::shared_memory_object(bi::open_only, shared_memory_name, bi::read_write);
}
catch(std::exception&)
{
using namespace std::literals::chrono_literals;
bp::spawn(argv[0], daemonizer_string);
std::this_thread::sleep_for(100ms);
shm = bi::shared_memory_object(bi::open_only, shared_memory_name, bi::read_write);
}
bi::mapped_region region(shm, bi::read_write);
shared_data_type& shared_data = *static_cast<shared_data_type*>(region.get_address());
std::cout << shared_data.count++ << '\n';
}
}
source
share