Flow-IPC 2.0.0
Flow-IPC project: Full implementation reference.
pool_arena.cpp
Go to the documentation of this file.
1/* Flow-IPC: Shared Memory
2 * Copyright 2023 Akamai Technologies, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the
5 * "License"); you may not use this file except in
6 * compliance with the License. You may obtain a copy
7 * of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in
12 * writing, software distributed under the License is
13 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
14 * CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing
16 * permissions and limitations under the License. */
17
18/// @file
19
23
24namespace ipc::shm::classic
25{
26
27template<typename Mode_tag>
28Pool_arena::Pool_arena(Mode_tag mode_tag, flow::log::Logger* logger_ptr,
29 const Shared_name& pool_name_arg, size_t pool_sz,
30 const util::Permissions& perms, Error_code* err_code) :
31 flow::log::Log_context(logger_ptr, Log_component::S_SHM),
32 m_pool_name(pool_name_arg)
33{
34 using boost::io::ios_all_saver;
35
36 assert(pool_sz >= sizeof(void*));
37 static_assert(std::is_same_v<Mode_tag, util::Create_only> || std::is_same_v<Mode_tag, util::Open_or_create>,
38 "Can only delegate to this ctor with Mode_tag = Create_only or Open_or_create.");
39 constexpr char const * MODE_STR = std::is_same_v<Mode_tag, util::Create_only>
40 ? "create-only" : "open-or-create";
41
42 if (get_logger()->should_log(flow::log::Sev::S_INFO, get_log_component()))
43 {
44 ios_all_saver saver{*(get_logger()->this_thread_ostream())}; // Revert std::oct/etc. soon.
45 FLOW_LOG_INFO_WITHOUT_CHECKING
46 ("SHM-classic pool [" << *this << "]: Constructing heap handle to heap/pool at name [" << m_pool_name << "] in "
47 "[" << MODE_STR << "] mode; pool size [" << flow::util::ceil_div(pool_sz, size_t(1024 * 1024)) << "Mi]; "
48 "perms = [" << std::setfill('0') << std::setw(4) << std::oct << perms.get_permissions() << "].");
49 }
50
51 /* m_pool is null. Try to create/create-or-open it; it may throw exception; this will do the right thing including
52 * leaving m_pool at null, as promised, on any error. Note we might throw exception because of this call. */
54 (get_logger(), err_code, error::Code::S_SHM_BIPC_MISC_LIBRARY_ERROR, "Pool_arena(): Pool()", [&]()
55 {
56 m_pool.emplace(mode_tag, m_pool_name.native_str(), pool_sz, nullptr, perms);
57 });
58} // Pool_arena::Pool_arena()
59
60Pool_arena::Pool_arena(flow::log::Logger* logger_ptr,
61 const Shared_name& pool_name_arg, util::Create_only, size_t pool_sz,
62 const util::Permissions& perms, Error_code* err_code) :
63 Pool_arena(util::CREATE_ONLY, logger_ptr, pool_name_arg, pool_sz, perms, err_code)
64{
65 // Cool.
66}
67
68Pool_arena::Pool_arena(flow::log::Logger* logger_ptr,
69 const Shared_name& pool_name_arg, util::Open_or_create, size_t pool_sz,
70 const util::Permissions& perms, Error_code* err_code) :
71 Pool_arena(util::OPEN_OR_CREATE, logger_ptr, pool_name_arg, pool_sz, perms, err_code)
72{
73 // Cool.
74}
75
76Pool_arena::Pool_arena(flow::log::Logger* logger_ptr,
77 const Shared_name& pool_name_arg, util::Open_only, bool read_only, Error_code* err_code) :
78 flow::log::Log_context(logger_ptr, Log_component::S_TRANSPORT),
79 m_pool_name(pool_name_arg)
80{
81 FLOW_LOG_INFO("SHM-classic pool [" << *this << "]: Constructing heap handle to heap/pool at name "
82 "[" << m_pool_name << "] in open-only mode; paged read-only? = [" << read_only << "].");
83
85 "Pool_arena(OPEN_ONLY): Pool()", [&]()
86 {
87 if (read_only)
88 {
89 m_pool.emplace(::ipc::bipc::open_read_only, m_pool_name.native_str());
90 }
91 else
92 {
94 }
95 });
96} // Pool_arena::Pool_arena()
97
99{
100 FLOW_LOG_INFO("SHM-classic pool [" << *this << "]: Closing handle.");
101}
102
103void* Pool_arena::allocate(size_t n)
104{
105 assert((n != 0) && "Please do not allocate(0).");
106
107 if (!m_pool)
108 {
109 return nullptr;
110 }
111 // else
112
113 if (get_logger()->should_log(flow::log::Sev::S_DATA, get_log_component()))
114 {
115 const auto total = m_pool->get_size();
116 const auto prev_free = m_pool->get_free_memory();
117 const auto ret = m_pool->allocate(n); // Can throw (hence we can throw as advertised).
118 const auto now_free = m_pool->get_free_memory();
119 assert(total == m_pool->get_size());
120
121 FLOW_LOG_DATA_WITHOUT_CHECKING("SHM-classic pool [" << *this << "]: SHM-alloc-ed user buffer sized [" << n << "]; "
122 "bipc alloc-algo reports free space changed "
123 "[" << prev_free << "] (used [" << (total - prev_free) << "]) => "
124 "[" << now_free << "] (used [" << (total - now_free) << "]); "
125 "raw delta [" << (prev_free - now_free) << "].");
126 return ret;
127 }
128 // else
129
130 return m_pool->allocate(n); // Can throw (hence we can throw as advertised).
131} // Pool_arena::allocate()
132
133bool Pool_arena::deallocate(void* buf_not_null) noexcept
134{
135 assert(buf_not_null && "Please do not deallocate(nullptr).");
136
137 if (!m_pool)
138 {
139 return false;
140 }
141 // else
142
143 if (get_logger()->should_log(flow::log::Sev::S_DATA, get_log_component()))
144 {
145 const auto total = m_pool->get_size();
146 const auto prev_free = m_pool->get_free_memory();
147 m_pool->deallocate(buf_not_null); // Does not throw.
148 const auto now_free = m_pool->get_free_memory();
149 assert(total == m_pool->get_size());
150
151 FLOW_LOG_DATA_WITHOUT_CHECKING("SHM-classic pool [" << *this << "]: SHM-dealloc-ed user buffer (size unknown) "
152 "bipc alloc-algo reports free space changed "
153 "[" << prev_free << "] (used [" << (total - prev_free) << "]) => "
154 "[" << now_free << "] (used [" << (total - now_free) << "]); "
155 "raw delta [" << (now_free - prev_free) << "].");
156 }
157 else
158 {
159 m_pool->deallocate(buf_not_null);
160 }
161
162 return true;
163} // Pool_arena::deallocate()
164
165void Pool_arena::remove_persistent(flow::log::Logger* logger_ptr, // Static.
166 const Shared_name& pool_name, Error_code* err_code)
167{
168 util::remove_persistent_shm_pool(logger_ptr, pool_name, err_code);
169 // (See that guy's doc header for why we didn't just do what's necessary right in here.)
170}
171
172std::ostream& operator<<(std::ostream& os, const Pool_arena& val)
173{
174 return os << '@' << &val << " => sh_name[" << val.m_pool_name << ']';
175}
176
177} // namespace ipc::shm::classic
A SHM-classic interface around a single SHM pool with allocation-algorithm services by boost....
Definition: pool_arena.hpp:153
std::optional< Pool > m_pool
Attached SHM pool. If ctor fails in non-throwing fashion then this remains null. Immutable after ctor...
Definition: pool_arena.hpp:614
bool deallocate(void *buf_not_null) noexcept
Undoes effects of local allocate() that returned buf_not_null; or another-process's allocate() that r...
Definition: pool_arena.cpp:133
const Shared_name m_pool_name
SHM pool name as set immutably at construction.
Definition: pool_arena.hpp:493
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=util::Permissions{}, Error_code *err_code=nullptr)
Construct Pool_arena accessor object to non-existing named SHM pool, creating it first.
Definition: pool_arena.cpp:60
static void remove_persistent(flow::log::Logger *logger_ptr, const Shared_name &name, Error_code *err_code=nullptr)
Removes the named SHM pool object.
Definition: pool_arena.cpp:165
void * allocate(size_t n)
Allocates buffer of specified size, in bytes, in the accessed pool; returns locally-derefernceable ad...
Definition: pool_arena.cpp:103
~Pool_arena()
Destroys Pool_arena accessor object.
Definition: pool_arena.cpp:98
String-wrapping abstraction representing a name uniquely distinguishing a kernel-persistent entity fr...
const char * native_str() const
Returns (sans copying) pointer to NUL-terminated wrapped name string, suitable to pass into sys calls...
@ 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.
Definition: classic_fwd.hpp:26
std::ostream & operator<<(std::ostream &os, const Pool_arena &val)
Prints string representation of the given Pool_arena to the given ostream.
Definition: pool_arena.cpp:172
bipc::permissions Permissions
Short-hand for Unix (POSIX) permissions class.
Definition: util_fwd.hpp:161
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().
Definition: util.cpp:119
bipc::open_only_t Open_only
Tag type indicating an ideally-atomic open-if-exists-else-fail operation.
Definition: util_fwd.hpp:155
const Open_or_create OPEN_OR_CREATE
Tag value indicating an open-if-exists-else-create operation.
Definition: util.cpp:30
const Open_only OPEN_ONLY
Tag value indicating an atomic open-if-exists-else-fail operation.
Definition: util.cpp:31
bipc::open_or_create_t Open_or_create
Tag type indicating an atomic open-if-exists-else-create operation.
Definition: util_fwd.hpp:152
bipc::create_only_t Create_only
Tag type indicating a create-unless-exists-else-fail operation.
Definition: util_fwd.hpp:158
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...
Definition: util.hpp:34
const Create_only CREATE_ONLY
Tag value indicating an atomic create-unless-exists-else-fail operation.
Definition: util.cpp:32
Log_component
The flow::log::Component payload enumeration containing various log components used by Flow-IPC inter...
Definition: common.hpp:323
flow::Error_code Error_code
Short-hand for flow::Error_code which is very common.
Definition: common.hpp:298