Flow-IPC 1.0.2
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
24#include <boost/move/make_unique.hpp>
25
26namespace ipc::shm::classic
27{
28
29template<typename Mode_tag>
30Pool_arena::Pool_arena(Mode_tag mode_tag, flow::log::Logger* logger_ptr,
31 const Shared_name& pool_name_arg, size_t pool_sz,
32 const util::Permissions& perms, Error_code* err_code) :
33 flow::log::Log_context(logger_ptr, Log_component::S_TRANSPORT),
34 m_pool_name(pool_name_arg)
35{
36 using boost::io::ios_all_saver;
37 using boost::movelib::make_unique;
38
39 assert(pool_sz >= sizeof(void*));
40 static_assert(std::is_same_v<Mode_tag, util::Create_only> || std::is_same_v<Mode_tag, util::Open_or_create>,
41 "Can only delegate to this ctor with Mode_tag = Create_only or Open_or_create.");
42 constexpr char const * MODE_STR = std::is_same_v<Mode_tag, util::Create_only>
43 ? "create-only" : "open-or-create";
44
45 if (get_logger()->should_log(flow::log::Sev::S_INFO, get_log_component()))
46 {
47 ios_all_saver saver(*(get_logger()->this_thread_ostream())); // Revert std::oct/etc. soon.
48 FLOW_LOG_INFO_WITHOUT_CHECKING
49 ("SHM-classic pool [" << *this << "]: Constructing heap handle to heap/pool at name [" << m_pool_name << "] in "
50 "[" << MODE_STR << "] mode; pool size [" << flow::util::ceil_div(pool_sz, size_t(1024 * 1024)) << "Mi]; "
51 "perms = [" << std::setfill('0') << std::setw(4) << std::oct << perms.get_permissions() << "].");
52 }
53
54 /* m_pool is null. Try to create/create-or-open it; it may throw exception; this will do the right thing including
55 * leaving m_pool at null, as promised, on any error. Note we might throw exception because of this call. */
57 (get_logger(), err_code, error::Code::S_SHM_BIPC_MISC_LIBRARY_ERROR, "Pool_arena(): Pool()", [&]()
58 {
59 m_pool = make_unique<Pool>(mode_tag, m_pool_name.native_str(), pool_sz, nullptr, perms);
60 });
61} // Pool_arena::Pool_arena()
62
63Pool_arena::Pool_arena(flow::log::Logger* logger_ptr,
64 const Shared_name& pool_name_arg, util::Create_only, size_t pool_sz,
65 const util::Permissions& perms, Error_code* err_code) :
66 Pool_arena(util::CREATE_ONLY, logger_ptr, pool_name_arg, pool_sz, perms, err_code)
67{
68 // Cool.
69}
70
71Pool_arena::Pool_arena(flow::log::Logger* logger_ptr,
72 const Shared_name& pool_name_arg, util::Open_or_create, size_t pool_sz,
73 const util::Permissions& perms, Error_code* err_code) :
74 Pool_arena(util::OPEN_OR_CREATE, logger_ptr, pool_name_arg, pool_sz, perms, err_code)
75{
76 // Cool.
77}
78
79Pool_arena::Pool_arena(flow::log::Logger* logger_ptr,
80 const Shared_name& pool_name_arg, util::Open_only, bool read_only, Error_code* err_code) :
81 flow::log::Log_context(logger_ptr, Log_component::S_TRANSPORT),
82 m_pool_name(pool_name_arg)
83{
84 using boost::movelib::make_unique;
85
86 FLOW_LOG_INFO("SHM-classic pool [" << *this << "]: Constructing heap handle to heap/pool at name "
87 "[" << m_pool_name << "] in open-only mode; paged read-only? = [" << read_only << "].");
88
90 "Pool_arena(OPEN_ONLY): Pool()", [&]()
91 {
92 m_pool = read_only ? make_unique<Pool>(::ipc::bipc::open_read_only, m_pool_name.native_str())
93 : make_unique<Pool>(util::OPEN_ONLY, m_pool_name.native_str());
94 });
95} // Pool_arena::Pool_arena()
96
98{
99 FLOW_LOG_INFO("SHM-classic pool [" << *this << "]: Closing handle.");
100}
101
102void* Pool_arena::allocate(size_t n)
103{
104 assert((n != 0) && "Please do not allocate(0).");
105
106 if (!m_pool)
107 {
108 return nullptr;
109 }
110 // else
111
112 if (get_logger()->should_log(flow::log::Sev::S_DATA, get_log_component()))
113 {
114 const auto total = m_pool->get_size();
115 const auto prev_free = m_pool->get_free_memory();
116 const auto ret = m_pool->allocate(n); // Can throw (hence we can throw as advertised).
117 const auto now_free = m_pool->get_free_memory();
118 assert(total == m_pool->get_size());
119
120 FLOW_LOG_DATA_WITHOUT_CHECKING("SHM-classic pool [" << *this << "]: SHM-alloc-ed user buffer sized [" << n << "]; "
121 "bipc alloc-algo reports free space changed "
122 "[" << prev_free << "] (used [" << (total - prev_free) << "]) => "
123 "[" << now_free << "] (used [" << (total - now_free) << "]); "
124 "raw delta [" << (prev_free - now_free) << "].");
125 return ret;
126 }
127 // else
128
129 return m_pool->allocate(n); // Can throw (hence we can throw as advertised).
130} // Pool_arena::allocate()
131
132bool Pool_arena::deallocate(void* buf_not_null) noexcept
133{
134 assert(buf_not_null && "Please do not deallocate(nullptr).");
135
136 if (!m_pool)
137 {
138 return false;
139 }
140 // else
141
142 if (get_logger()->should_log(flow::log::Sev::S_DATA, get_log_component()))
143 {
144 const auto total = m_pool->get_size();
145 const auto prev_free = m_pool->get_free_memory();
146 m_pool->deallocate(buf_not_null); // Does not throw.
147 const auto now_free = m_pool->get_free_memory();
148 assert(total == m_pool->get_size());
149
150 FLOW_LOG_DATA_WITHOUT_CHECKING("SHM-classic pool [" << *this << "]: SHM-dealloc-ed user buffer (size unknown) "
151 "bipc alloc-algo reports free space changed "
152 "[" << prev_free << "] (used [" << (total - prev_free) << "]) => "
153 "[" << now_free << "] (used [" << (total - now_free) << "]); "
154 "raw delta [" << (now_free - prev_free) << "].");
155 }
156 else
157 {
158 m_pool->deallocate(buf_not_null);
159 }
160
161 return true;
162} // Pool_arena::deallocate()
163
164void Pool_arena::remove_persistent(flow::log::Logger* logger_ptr, // Static.
165 const Shared_name& pool_name, Error_code* err_code)
166{
167 util::remove_persistent_shm_pool(logger_ptr, pool_name, err_code);
168 // (See that guy's doc header for why we didn't just do what's necessary right in here.)
169}
170
171std::ostream& operator<<(std::ostream& os, const Pool_arena& val)
172{
173 return os << '@' << &val << " => sh_name[" << val.m_pool_name << ']';
174}
175
176} // namespace ipc::shm::classic
A SHM-classic interface around a single SHM pool with allocation-algorithm services by boost....
Definition: pool_arena.hpp:151
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=0)
Construct Pool_arena accessor object to non-existing named SHM pool, creating it first.
Definition: pool_arena.cpp:63
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:132
boost::movelib::unique_ptr< Pool > m_pool
Attached SHM pool. If ctor fails in non-throwing fashion then this remains null. Immutable after ctor...
Definition: pool_arena.hpp:603
const Shared_name m_pool_name
SHM pool name as set immutably at construction.
Definition: pool_arena.hpp:489
void * allocate(size_t n)
Allocates buffer of specified size, in bytes, in the accessed pool; returns locally-derefernceable ad...
Definition: pool_arena.cpp:102
~Pool_arena()
Destroys Pool_arena accessor object.
Definition: pool_arena.cpp:97
static void remove_persistent(flow::log::Logger *logger_ptr, const Shared_name &name, Error_code *err_code=0)
Removes the named SHM pool object.
Definition: pool_arena.cpp:164
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:171
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