2121
2222#include " libipc/utility/log.h"
2323#include " libipc/utility/id_pool.h"
24+ #include " libipc/utility/utility.h"
2425
2526#include " libipc/memory/resource.h"
2627
@@ -90,77 +91,68 @@ auto cc_acc() {
9091 return static_cast <acc_t *>(acc_h.get ());
9192}
9293
93- auto & cls_storages () {
94- struct cls_t {
95- ipc::shm::handle id_info_;
96- std::array<ipc::shm::handle, ipc::id_pool<>::max_count> mems_;
97- };
98- static ipc::unordered_map<std::size_t , cls_t > cls_s;
99- return cls_s;
100- }
101-
102- auto & cls_lock () {
103- static ipc::spin_lock cls_l;
104- return cls_l;
105- }
106-
107- struct cls_info_t {
94+ struct chunk_info_t {
10895 ipc::id_pool<> pool_;
10996 ipc::spin_lock lock_;
97+
98+ IPC_CONSTEXPR_ static std::size_t chunks_elem_size (std::size_t chunk_size) noexcept {
99+ return ipc::make_align (alignof (std::max_align_t ), chunk_size + sizeof (acc_t ));
100+ }
101+
102+ IPC_CONSTEXPR_ static std::size_t chunks_mem_size (std::size_t chunk_size) noexcept {
103+ return ipc::id_pool<>::max_count * chunks_elem_size (chunk_size);
104+ }
105+
106+ ipc::byte_t *at (std::size_t chunk_size, std::size_t id) noexcept {
107+ return reinterpret_cast <ipc::byte_t *>(this + 1 ) + (chunks_elem_size (chunk_size) * id);
108+ }
110109};
111110
112- constexpr std::size_t calc_cls_size (std::size_t size) noexcept {
113- return (((size - 1 ) / ipc::large_msg_limit) + 1 ) * ipc::large_msg_limit;
111+ auto & chunk_storages () {
112+ class chunk_t {
113+ ipc::shm::handle handle_;
114+
115+ public:
116+ chunk_info_t *get_info (std::size_t chunk_size) {
117+ if (!handle_.valid () &&
118+ !handle_.acquire ( (" __CHUNK_INFO__" + ipc::to_string (chunk_size)).c_str (),
119+ sizeof (chunk_info_t ) + chunk_info_t::chunks_mem_size (chunk_size) )) {
120+ ipc::error (" [chunk_storages] chunk_shm.id_info_.acquire failed: chunk_size = %zd\n " , chunk_size);
121+ return nullptr ;
122+ }
123+ auto info = static_cast <chunk_info_t *>(handle_.get ());
124+ if (info == nullptr ) {
125+ ipc::error (" [chunk_storages] chunk_shm.id_info_.get failed: chunk_size = %zd\n " , chunk_size);
126+ return nullptr ;
127+ }
128+ return info;
129+ }
130+ };
131+ static ipc::unordered_map<std::size_t , chunk_t > chunk_s;
132+ return chunk_s;
114133}
115134
116- auto & cls_storage (std:: size_t cls_size ) {
117- IPC_UNUSED_ auto guard = ipc::detail::unique_lock ( cls_lock ()) ;
118- return cls_storages ()[cls_size] ;
135+ auto & chunk_lock ( ) {
136+ static ipc::spin_lock chunk_l ;
137+ return chunk_l ;
119138}
120139
121- template <typename T>
122- cls_info_t * cls_storage_info (const char * func, T& cls_shm, std::size_t cls_size) {
123- if (!cls_shm.id_info_ .valid () &&
124- !cls_shm.id_info_ .acquire ((" __CLS_INFO__" + ipc::to_string (cls_size)).c_str (), sizeof (cls_info_t ))) {
125- ipc::error (" [%s] cls_shm.id_info_.acquire failed: cls_size = %zd\n " , func, cls_size);
126- return nullptr ;
127- }
128- auto info = static_cast <cls_info_t *>(cls_shm.id_info_ .get ());
129- if (info == nullptr ) {
130- ipc::error (" [%s] cls_shm.id_info_.get failed: cls_size = %zd\n " , func, cls_size);
131- return nullptr ;
132- }
133- return info;
140+ constexpr std::size_t calc_chunk_size (std::size_t size) noexcept {
141+ return ( ((size - 1 ) / ipc::large_msg_align) + 1 ) * ipc::large_msg_align;
134142}
135143
136- template <typename T>
137- ipc::byte_t * cls_storage_mem (const char * func, T& cls_shm, std::size_t cls_size, std::size_t id) {
138- if (id == ipc::invalid_value) {
139- return nullptr ;
140- }
141- if (!cls_shm.mems_ [id].valid () &&
142- !cls_shm.mems_ [id].acquire ((" __CLS_MEM_BLOCK__" + ipc::to_string (cls_size) +
143- " __" + ipc::to_string (id)).c_str (),
144- cls_size + sizeof (acc_t ))) {
145- ipc::error (" [%s] cls_shm.mems_[id].acquire failed: id = %zd, cls_size = %zd\n " , func, id, cls_size);
146- return nullptr ;
147- }
148-
149- auto ptr = static_cast <ipc::byte_t *>(cls_shm.mems_ [id].get ());
150- if (ptr == nullptr ) {
151- ipc::error (" [%s] cls_shm.mems_[id].get failed: id = %zd, cls_size = %zd\n " , func, id, cls_size);
152- return nullptr ;
153- }
154- return ptr;
144+ auto & chunk_storage (std::size_t chunk_size) {
145+ IPC_UNUSED_ auto guard = ipc::detail::unique_lock (chunk_lock ());
146+ return chunk_storages ()[chunk_size];
155147}
156148
157149std::pair<std::size_t , void *> apply_storage (std::size_t conn_count, std::size_t size) {
158150 if (conn_count == 0 ) return {};
159151
160- std::size_t cls_size = calc_cls_size (size);
161- auto & cls_shm = cls_storage (cls_size );
152+ std::size_t chunk_size = calc_chunk_size (size);
153+ auto & chunk_shm = chunk_storage (chunk_size );
162154
163- auto info = cls_storage_info ( " apply_storage " , cls_shm, cls_size );
155+ auto info = chunk_shm. get_info (chunk_size );
164156 if (info == nullptr ) return {};
165157
166158 info->lock_ .lock ();
@@ -169,20 +161,23 @@ std::pair<std::size_t, void*> apply_storage(std::size_t conn_count, std::size_t
169161 auto id = info->pool_ .acquire ();
170162 info->lock_ .unlock ();
171163
172- auto ptr = cls_storage_mem ( " apply_storage " , cls_shm, cls_size , id);
164+ auto ptr = info-> at (chunk_size , id);
173165 if (ptr == nullptr ) return {};
174- reinterpret_cast <acc_t *>(ptr + cls_size )->store (static_cast <msg_id_t >(conn_count), std::memory_order_release);
166+ reinterpret_cast <acc_t *>(ptr + chunk_size )->store (static_cast <msg_id_t >(conn_count), std::memory_order_release);
175167 return { id, ptr };
176168}
177169
178- void * find_storage (std::size_t id, std::size_t size) {
179- std::size_t cls_size = calc_cls_size (size);
180- auto & cls_shm = cls_storage (cls_size);
170+ void *find_storage (std::size_t id, std::size_t size) {
171+ std::size_t chunk_size = calc_chunk_size (size);
172+ auto & chunk_shm = chunk_storage (chunk_size);
173+
174+ auto info = chunk_shm.get_info (chunk_size);
175+ if (info == nullptr ) return nullptr ;
181176
182- auto ptr = cls_storage_mem ( " find_storage " , cls_shm, cls_size , id);
177+ auto ptr = info-> at (chunk_size , id);
183178 if (ptr == nullptr ) return nullptr ;
184- if (reinterpret_cast <acc_t *>(ptr + cls_size )->load (std::memory_order_acquire) == 0 ) {
185- ipc::error (" [find_storage] cc test failed: id = %zd, cls_size = %zd\n " , id, cls_size );
179+ if (reinterpret_cast <acc_t *>(ptr + chunk_size )->load (std::memory_order_acquire) == 0 ) {
180+ ipc::error (" [find_storage] cc test failed: id = %zd, chunk_size = %zd\n " , id, chunk_size );
186181 return nullptr ;
187182 }
188183 return ptr;
@@ -194,26 +189,22 @@ void recycle_storage(std::size_t id, std::size_t size) {
194189 return ;
195190 }
196191
197- std::size_t cls_size = calc_cls_size (size);
198- auto & cls_shm = cls_storage (cls_size );
192+ std::size_t chunk_size = calc_chunk_size (size);
193+ auto & chunk_shm = chunk_storage (chunk_size );
199194
200- if (!cls_shm.mems_ [id].valid ()) {
201- ipc::error (" [recycle_storage] should find storage first: id = %zd, cls_size = %zd\n " , id, cls_size);
202- return ;
203- }
204- auto ptr = static_cast <ipc::byte_t *>(cls_shm.mems_ [id].get ());
195+ auto info = chunk_shm.get_info (chunk_size);
196+ if (info == nullptr ) return ;
197+
198+ auto ptr = info->at (chunk_size, id);
205199 if (ptr == nullptr ) {
206- ipc::error (" [recycle_storage] cls_shm.mems_[id].get failed: id = %zd, cls_size = %zd \n " , id, cls_size );
200+ ipc::error (" [recycle_storage] chunk_shm.mems[%zd] failed: chunk_size = %zd\n " , id, chunk_size );
207201 return ;
208202 }
209- if (reinterpret_cast <acc_t *>(ptr + cls_size )->fetch_sub (1 , std::memory_order_acq_rel) > 1 ) {
203+ if (reinterpret_cast <acc_t *>(ptr + chunk_size )->fetch_sub (1 , std::memory_order_acq_rel) > 1 ) {
210204 // not the last receiver, just return
211205 return ;
212206 }
213207
214- auto info = cls_storage_info (" recycle_storage" , cls_shm, cls_size);
215- if (info == nullptr ) return ;
216-
217208 info->lock_ .lock ();
218209 info->pool_ .release (id);
219210 info->lock_ .unlock ();
@@ -225,13 +216,16 @@ void clear_storage(std::size_t id, std::size_t size) {
225216 return ;
226217 }
227218
228- std::size_t cls_size = calc_cls_size (size);
229- auto & cls_shm = cls_storage (cls_size);
219+ std::size_t chunk_size = calc_chunk_size (size);
220+ auto & chunk_shm = chunk_storage (chunk_size);
221+
222+ auto info = chunk_shm.get_info (chunk_size);
223+ if (info == nullptr ) return ;
230224
231- auto ptr = cls_storage_mem ( " clear_storage " , cls_shm, cls_size , id);
225+ auto ptr = info-> at (chunk_size , id);
232226 if (ptr == nullptr ) return ;
233227
234- auto cc_flag = reinterpret_cast <acc_t *>(ptr + cls_size );
228+ auto cc_flag = reinterpret_cast <acc_t *>(ptr + chunk_size );
235229 for (unsigned k = 0 ;;) {
236230 auto cc_curr = cc_flag->load (std::memory_order_acquire);
237231 if (cc_curr == 0 ) return ; // means this id has been cleared
@@ -241,9 +235,6 @@ void clear_storage(std::size_t id, std::size_t size) {
241235 ipc::yield (k);
242236 }
243237
244- auto info = cls_storage_info (" clear_storage" , cls_shm, cls_size);
245- if (info == nullptr ) return ;
246-
247238 info->lock_ .lock ();
248239 info->pool_ .release (id);
249240 info->lock_ .unlock ();
0 commit comments