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,69 @@ 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+ if (id == ipc::invalid_value) return nullptr ;
108+ return reinterpret_cast <ipc::byte_t *>(this + 1 ) + (chunks_elem_size (chunk_size) * id);
109+ }
110110};
111111
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;
112+ auto & chunk_storages () {
113+ class chunk_t {
114+ ipc::shm::handle handle_;
115+
116+ public:
117+ chunk_info_t *get_info (std::size_t chunk_size) {
118+ if (!handle_.valid () &&
119+ !handle_.acquire ( (" __CHUNK_INFO__" + ipc::to_string (chunk_size)).c_str (),
120+ sizeof (chunk_info_t ) + chunk_info_t::chunks_mem_size (chunk_size) )) {
121+ ipc::error (" [chunk_storages] chunk_shm.id_info_.acquire failed: chunk_size = %zd\n " , chunk_size);
122+ return nullptr ;
123+ }
124+ auto info = static_cast <chunk_info_t *>(handle_.get ());
125+ if (info == nullptr ) {
126+ ipc::error (" [chunk_storages] chunk_shm.id_info_.get failed: chunk_size = %zd\n " , chunk_size);
127+ return nullptr ;
128+ }
129+ return info;
130+ }
131+ };
132+ static ipc::unordered_map<std::size_t , chunk_t > chunk_s;
133+ return chunk_s;
114134}
115135
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] ;
136+ auto & chunk_lock ( ) {
137+ static ipc::spin_lock chunk_l ;
138+ return chunk_l ;
119139}
120140
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;
141+ constexpr std::size_t calc_chunk_size (std::size_t size) noexcept {
142+ return ( ((size - 1 ) / ipc::large_msg_align) + 1 ) * ipc::large_msg_align;
134143}
135144
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;
145+ auto & chunk_storage (std::size_t chunk_size) {
146+ IPC_UNUSED_ auto guard = ipc::detail::unique_lock (chunk_lock ());
147+ return chunk_storages ()[chunk_size];
155148}
156149
157150std::pair<std::size_t , void *> apply_storage (std::size_t conn_count, std::size_t size) {
158151 if (conn_count == 0 ) return {};
159152
160- std::size_t cls_size = calc_cls_size (size);
161- auto & cls_shm = cls_storage (cls_size );
153+ std::size_t chunk_size = calc_chunk_size (size);
154+ auto & chunk_shm = chunk_storage (chunk_size );
162155
163- auto info = cls_storage_info ( " apply_storage " , cls_shm, cls_size );
156+ auto info = chunk_shm. get_info (chunk_size );
164157 if (info == nullptr ) return {};
165158
166159 info->lock_ .lock ();
@@ -169,20 +162,28 @@ std::pair<std::size_t, void*> apply_storage(std::size_t conn_count, std::size_t
169162 auto id = info->pool_ .acquire ();
170163 info->lock_ .unlock ();
171164
172- auto ptr = cls_storage_mem ( " apply_storage " , cls_shm, cls_size , id);
165+ auto ptr = info-> at (chunk_size , id);
173166 if (ptr == nullptr ) return {};
174- reinterpret_cast <acc_t *>(ptr + cls_size )->store (static_cast <msg_id_t >(conn_count), std::memory_order_release);
167+ reinterpret_cast <acc_t *>(ptr + chunk_size )->store (static_cast <msg_id_t >(conn_count), std::memory_order_release);
175168 return { id, ptr };
176169}
177170
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);
171+ void *find_storage (std::size_t id, std::size_t size) {
172+ if (id == ipc::invalid_value) {
173+ ipc::error (" [find_storage] id is invalid: id = %zd, size = %zd\n " , id, size);
174+ return nullptr ;
175+ }
176+
177+ std::size_t chunk_size = calc_chunk_size (size);
178+ auto & chunk_shm = chunk_storage (chunk_size);
181179
182- auto ptr = cls_storage_mem (" find_storage" , cls_shm, cls_size, id);
180+ auto info = chunk_shm.get_info (chunk_size);
181+ if (info == nullptr ) return nullptr ;
182+
183+ auto ptr = info->at (chunk_size, id);
183184 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 );
185+ if (reinterpret_cast <acc_t *>(ptr + chunk_size )->load (std::memory_order_acquire) == 0 ) {
186+ ipc::error (" [find_storage] cc test failed: id = %zd, chunk_size = %zd\n " , id, chunk_size );
186187 return nullptr ;
187188 }
188189 return ptr;
@@ -194,26 +195,22 @@ void recycle_storage(std::size_t id, std::size_t size) {
194195 return ;
195196 }
196197
197- std::size_t cls_size = calc_cls_size (size);
198- auto & cls_shm = cls_storage (cls_size );
198+ std::size_t chunk_size = calc_chunk_size (size);
199+ auto & chunk_shm = chunk_storage (chunk_size );
199200
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 ());
201+ auto info = chunk_shm.get_info (chunk_size);
202+ if (info == nullptr ) return ;
203+
204+ auto ptr = info->at (chunk_size, id);
205205 if (ptr == nullptr ) {
206- ipc::error (" [recycle_storage] cls_shm.mems_[id].get failed: id = %zd, cls_size = %zd \n " , id, cls_size );
206+ ipc::error (" [recycle_storage] chunk_shm.mems[%zd] failed: chunk_size = %zd\n " , id, chunk_size );
207207 return ;
208208 }
209- if (reinterpret_cast <acc_t *>(ptr + cls_size )->fetch_sub (1 , std::memory_order_acq_rel) > 1 ) {
209+ if (reinterpret_cast <acc_t *>(ptr + chunk_size )->fetch_sub (1 , std::memory_order_acq_rel) > 1 ) {
210210 // not the last receiver, just return
211211 return ;
212212 }
213213
214- auto info = cls_storage_info (" recycle_storage" , cls_shm, cls_size);
215- if (info == nullptr ) return ;
216-
217214 info->lock_ .lock ();
218215 info->pool_ .release (id);
219216 info->lock_ .unlock ();
@@ -225,13 +222,16 @@ void clear_storage(std::size_t id, std::size_t size) {
225222 return ;
226223 }
227224
228- std::size_t cls_size = calc_cls_size (size);
229- auto & cls_shm = cls_storage (cls_size);
225+ std::size_t chunk_size = calc_chunk_size (size);
226+ auto & chunk_shm = chunk_storage (chunk_size);
227+
228+ auto info = chunk_shm.get_info (chunk_size);
229+ if (info == nullptr ) return ;
230230
231- auto ptr = cls_storage_mem ( " clear_storage " , cls_shm, cls_size , id);
231+ auto ptr = info-> at (chunk_size , id);
232232 if (ptr == nullptr ) return ;
233233
234- auto cc_flag = reinterpret_cast <acc_t *>(ptr + cls_size );
234+ auto cc_flag = reinterpret_cast <acc_t *>(ptr + chunk_size );
235235 for (unsigned k = 0 ;;) {
236236 auto cc_curr = cc_flag->load (std::memory_order_acquire);
237237 if (cc_curr == 0 ) return ; // means this id has been cleared
@@ -241,9 +241,6 @@ void clear_storage(std::size_t id, std::size_t size) {
241241 ipc::yield (k);
242242 }
243243
244- auto info = cls_storage_info (" clear_storage" , cls_shm, cls_size);
245- if (info == nullptr ) return ;
246-
247244 info->lock_ .lock ();
248245 info->pool_ .release (id);
249246 info->lock_ .unlock ();
0 commit comments