24#include <flow/error/error.hpp>
25#include <flow/util/stat/stat_set.hpp>
26#include <boost/interprocess/exceptions.hpp>
32template<
typename Mode_tag>
37 m_pool_name(pool_name_arg),
38 m_own_process_id(util::Process_credentials::own_process_id()),
39 m_arena_metadata(nullptr)
41 using boost::io::ios_all_saver;
43 assert(pool_sz >=
sizeof(
void*));
44 static_assert(std::is_same_v<Mode_tag, util::Create_only> || std::is_same_v<Mode_tag, util::Open_or_create>,
45 "Can only delegate to this ctor with Mode_tag = Create_only or Open_or_create.");
46 constexpr char const * MODE_STR = std::is_same_v<Mode_tag, util::Create_only>
47 ?
"create-only" :
"open-or-create";
49 if (logger_ptr && logger_ptr->should_log(flow::log::Sev::S_INFO, get_log_component()))
51 ios_all_saver saver{*(logger_ptr->this_thread_ostream())};
52 FLOW_LOG_INFO_WITHOUT_CHECKING
53 (
"SHM-classic pool [" << *
this <<
"]: Constructing heap handle to heap/pool at name [" <<
m_pool_name <<
"] in "
54 "[" << MODE_STR <<
"] mode; pool size [" << flow::util::ceil_div(pool_sz,
size_t(1024 * 1024)) <<
"Mi]; "
55 "perms = [" << std::setfill(
'0') << std::setw(4) << std::oct << perms.get_permissions() <<
"].");
87 m_pool_name(pool_name_arg),
88 m_own_process_id(util::Process_credentials::own_process_id()),
89 m_arena_metadata(nullptr)
91 using flow::error::Runtime_error;
93 FLOW_LOG_INFO(
"SHM-classic pool [" << *
this <<
"]: Constructing heap handle to heap/pool at name "
94 "[" <<
m_pool_name <<
"] in open-only mode; paged read-only? = [" << read_only <<
"].");
97 "Pool_arena(OPEN_ONLY): Pool()", [&]()
106 if (err_code && *err_code)
113 assert((!
m_pool) &&
"init_arena_metadata() is supposed to nullify m_pool in this error case too.");
116 FLOW_LOG_WARNING(
"SHM-classic pool [" << *
this <<
"]: Improper use of read-only-mode ctor detected; emitting "
117 "error [" << our_err_code <<
"] "
118 "[" << our_err_code.message() <<
"].");
121 throw Runtime_error{our_err_code,
"Pool_arena::Pool_arena(OPEN_ONLY/read_only)"};
124 *err_code = our_err_code;
131 using ::ipc::bipc::unique_instance;
132 using flow::util::stat::print;
156 assert(
m_arena_metadata &&
"That find_or_construct() form is supposed to either return non-null or throw.");
184 FLOW_LOG_INFO(
"SHM-classic pool [" << *
this <<
"]: Stats at ctor (arena[] can change concurrently if pool "
185 "just-opened; ~zeroed if pool just-created): "
195 FLOW_LOG_INFO(
"SHM-classic pool [" << *
this <<
"]: Closing handle.");
201 FLOW_LOG_INFO(
"SHM-classic pool [" << *
this <<
"]: ~Final state:\n" << (
info_dump(&dump), dump) <<
'.');
208 FLOW_ERROR_EXEC_AND_THROW_ON_ERROR(
bool,
commit, _1);
218 bool committed =
false;
220 "Pool_arena::commit()", [&]()
222 committed =
m_pool->commit();
227 FLOW_LOG_WARNING(
"SHM-classic pool [" << *
this <<
"]: Commit (take RAM for) entire pool: failed (details "
228 "above); pool remains as it was (sparse) and usable.");
236 FLOW_LOG_TRACE(
"SHM-classic pool [" << *
this <<
"]: Commit (take RAM for) entire pool: done.");
240 FLOW_LOG_TRACE(
"SHM-classic pool [" << *
this <<
"]: Commit (take RAM for) entire pool: no-op, as "
241 "close_shm_object_handle() was called earlier.");
254 FLOW_LOG_INFO(
"SHM-classic pool [" << *
this <<
"]: Closing SHM-pool OS handle (commit() no longer possible).");
255 m_pool->close_shm_object_handle();
261 using Bipc_bad_alloc = ::ipc::bipc::bad_alloc;
262 using Std_bad_alloc = std::bad_alloc;
264 assert((n != 0) &&
"Please do not allocate(0).");
276 const auto logger_ptr = get_logger();
277 if (logger_ptr && logger_ptr->should_log(flow::log::Sev::S_DATA, get_log_component()))
281 ret =
m_pool->core()->allocate(n);
285 FLOW_LOG_DATA_WITHOUT_CHECKING(
"SHM-classic pool [" << *
this <<
"]: SHM-alloc-ed user buffer sized [" << n <<
"]; "
286 "bipc alloc-algo reports free space changed "
287 "[" << prev_free <<
"] (used [" << (total - prev_free) <<
"]) => "
288 "[" << now_free <<
"] (used [" << (total - now_free) <<
"]); "
289 "raw delta [" << (prev_free - now_free) <<
"].");
293 ret =
m_pool->core()->allocate(n);
296 catch (
const Bipc_bad_alloc&)
301 FLOW_LOG_TRACE(
"SHM-classic pool [" << *
this <<
"]: SHM-alloc-ed user buffer sized [" << n <<
"]; but "
302 "bipc alloc-algo threw bipc::bad_alloc (no space left in SHM-pool); throwing as "
305 throw Std_bad_alloc{};
313 assert(buf_not_null &&
"Please do not deallocate(nullptr).");
321 const auto logger_ptr = get_logger();
322 if (logger_ptr && logger_ptr->should_log(flow::log::Sev::S_DATA, get_log_component()))
324 const auto total = arena_size();
325 const auto prev_free = arena_stat_free_size();
326 m_pool->core()->deallocate(buf_not_null);
327 const auto now_free = arena_stat_free_size();
328 assert(total == arena_size());
330 FLOW_LOG_DATA_WITHOUT_CHECKING(
"SHM-classic pool [" << *
this <<
"]: SHM-dealloc-ed user buffer (size unknown) "
331 "bipc alloc-algo reports free space changed "
332 "[" << prev_free <<
"] (used [" << (total - prev_free) <<
"]) => "
333 "[" << now_free <<
"] (used [" << (total - now_free) <<
"]); "
334 "raw delta [" << (now_free - prev_free) <<
"].");
338 m_pool->core()->deallocate(buf_not_null);
348 const auto addr =
reinterpret_cast<uintptr_t
>(p);
349 const auto pool_base =
reinterpret_cast<uintptr_t
>(
m_pool->address());
351 return (addr >= pool_base) && ((addr - pool_base) <
arena_size());
394 using flow::util::stat::stats_assign;
396 assert(target_info_dump);
404 stats_assign(&target_info_dump->
m_arena_stats, *arena_stats_ptr);
420 return os <<
'@' << &val <<
" => sh_name[" << val.
m_pool_name <<
']';
A SHM-classic interface around a single SHM pool with allocation-algorithm services by boost....
bool commit(Error_code *err_code=nullptr)
Commits (takes RAM for) every page of the pool not yet committed, so that subsequent use of the pool ...
const stat::Arena_stats * arena_stats() const
Cumulative stats relevant to one SHM-classic arena – in this case single SHM-pool in shared memory,...
Pool_arena(flow::log::Logger *logger_ptr, const Shared_name &pool_name, util::Create_only mode_tag, size_t pool_sz, const util::Permissions &perms={}, Error_code *err_code=nullptr)
Construct Pool_arena accessor object to non-existing named SHM pool, creating it first.
std::optional< Pool > m_pool
Attached SHM pool. If ctor fails in non-throwing fashion then this remains null. Immutable after ctor...
Arena_metadata * m_arena_metadata
Created or acquired in ctor, pointer to in-m_pool (in-SHM) metadata singleton; see Arena_metadata doc...
stat::Local_stats m_local_stats
Per-*this (not per-arena-in-SHM) stats being accumulated, from multiple threads sans sharding.
bool deallocate(void *buf_not_null) noexcept
Undoes effects of local allocate() that returned buf_not_null; or another-process's allocate() that r...
size_t arena_stat_free_size() const
How much of arena_size() is currently available for allocations; that is, not currently used by curre...
void init_arena_metadata(bool read_only)
Helper of ctors: with the assumption that m_pool is ready, sets up m_arena_metadata if possible.
const Shared_name m_pool_name
SHM pool name as set immutably at construction.
size_t arena_size() const
Arena (in this case, arena=pool) size in bytes as configured at arena/pool creation; never changes.
bool is_addr_in_arena(const void *p) const
Returns true if and only if the byte at p is within the bounds of the pool accessed by *this.
static void remove_persistent(flow::log::Logger *logger_ptr, const Shared_name &name, Error_code *err_code=nullptr)
Removes the named SHM pool object.
void arena_stats_reset()
Resets arena_stats().
const stat::Local_stats & local_stats() const
Cumulative stats relevant to *this Pool_arena object – a Pool_arena – and excluding those in arena_st...
void * allocate(size_t n)
Allocates buffer of specified size, in bytes, in the accessed pool; returns locally-dereferenceable a...
~Pool_arena()
Destroys Pool_arena accessor object.
bool close_shm_object_handle()
Closes the pool's OS handle (FD) that *this keeps open only to enable commit(), returning that resour...
void local_stats_reset()
Resets local_stats().
void info_dump(Info_dump *target_info_dump) const
Fills-out the stats/info contents of the given stat::Arena_info_dump: a printable bundling of all sta...
String-wrapping abstraction representing a name uniquely distinguishing a kernel-persistent entity fr...
@ S_SHM_POOL_OPEN_READ_ONLY_FOUND_BUT_UNINIT
SHM-classic pool/arena, requested to be opened in native read-only mode, was found by name,...
@ S_SHM_BIPC_MISC_LIBRARY_ERROR
Low-level boost.ipc.shm: boost.interprocess emitted miscellaneous library exception sans a system cod...
ipc::shm sub-module with the SHM-classic SHM-provider. See ipc::shm doc header for introduction.
std::ostream & operator<<(std::ostream &os, const Pool_arena &val)
Prints string representation of the given Pool_arena to the given ostream.
bipc::permissions Permissions
Short-hand for Unix (POSIX) permissions class.
void remove_persistent_shm_pool(flow::log::Logger *logger_ptr, const Shared_name &pool_name, Error_code *err_code)
Equivalent to shm::classic::Pool_arena::remove_persistent().
bipc::open_only_t Open_only
Tag type indicating an ideally-atomic open-if-exists-else-fail operation.
const Open_or_create OPEN_OR_CREATE
Tag value indicating an open-if-exists-else-create operation.
const Open_only OPEN_ONLY
Tag value indicating an atomic open-if-exists-else-fail operation.
bipc::open_or_create_t Open_or_create
Tag type indicating an atomic open-if-exists-else-create operation.
bipc::create_only_t Create_only
Tag type indicating a create-unless-exists-else-fail operation.
void op_with_possible_bipc_exception(flow::log::Logger *logger_ptr, Error_code *err_code, const Error_code &misc_bipc_lib_error, String_view context, const Func &func)
Internal (to ipc) utility that invokes the given function that invokes a boost.interprocess operation...
const Create_only CREATE_ONLY
Tag value indicating an atomic create-unless-exists-else-fail operation.
Log_component
The flow::log::Component payload enumeration containing various log components used by Flow-IPC inter...
flow::Error_code Error_code
Short-hand for flow::Error_code which is very common.
Printable (with knobs in contained util::stat::Info_dump_format) bundling of stats/info pertaining to...
Arena_stats m_arena_stats
The source Pool_arena's (shared, in-SHM) arena stats from: Pool_arena::arena_stats(); meaningless/ign...
size_t m_arena_sz_or_0
The source Pool_arena's Pool_arena::arena_size(); 0 if and only if that Pool_arena was invalid (its c...
Local_stats m_local_stats
The source Pool_arena object's stats from: Pool_arena::local_stats(); meaningless/ignorable if m_aren...
size_t m_arena_stat_free_sz
The source Pool_arena's Pool_arena::arena_stat_free_size(); meaningless/ignorable if m_arena_sz_or_0 ...
Cumulative stats relevant to one SHM-classic arena – in this case single SHM-pool in shared memory,...
Cumulative stats relevant to a given SHM-classic arena object – a Pool_arena – and excluding those in...