@@ -51,15 +51,16 @@ struct msg_t : msg_t<0, AlignSize> {
5151 std::aligned_storage_t <DataSize, AlignSize> data_ {};
5252
5353 msg_t () = default ;
54- msg_t (msg_id_t c , msg_id_t i , std::int32_t r , void const * d , std::size_t s )
55- : msg_t <0 , AlignSize> { c, i, r , (d == nullptr ) || (s == 0 ) } {
54+ msg_t (msg_id_t conn , msg_id_t id , std::int32_t remain , void const * data , std::size_t size )
55+ : msg_t <0 , AlignSize> {conn, id, remain , (data == nullptr ) || (size == 0 )} {
5656 if (this ->storage_ ) {
57- if (d != nullptr ) {
57+ if (data != nullptr ) {
5858 // copy storage-id
59- *reinterpret_cast <std::size_t *>(&data_) = *static_cast <std::size_t const *>(d);
59+ *reinterpret_cast <ipc::storage_id_t *>(&data_) =
60+ *static_cast <ipc::storage_id_t const *>(data);
6061 }
6162 }
62- else std::memcpy (&data_, d, s );
63+ else std::memcpy (&data_, data, size );
6364 }
6465};
6566
@@ -95,17 +96,13 @@ struct chunk_info_t {
9596 ipc::id_pool<> pool_;
9697 ipc::spin_lock lock_;
9798
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);
100- }
101-
10299 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) ;
100+ return ipc::id_pool<>::max_count * chunk_size;
104101 }
105102
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);
103+ ipc::byte_t *at (std::size_t chunk_size, ipc:: storage_id_t id) noexcept {
104+ if (id < 0 ) return nullptr ;
105+ return reinterpret_cast <ipc::byte_t *>(this + 1 ) + (chunk_size * id);
109106 }
110107};
111108
@@ -129,29 +126,22 @@ auto& chunk_storages() {
129126 return info;
130127 }
131128 };
132- static ipc::unordered_map<std::size_t , chunk_t > chunk_s;
129+ thread_local ipc::unordered_map<std::size_t , chunk_t > chunk_s;
133130 return chunk_s;
134131}
135132
136- auto & chunk_lock () {
137- static ipc::spin_lock chunk_l;
138- return chunk_l ;
133+ IPC_CONSTEXPR_ std:: size_t calc_chunk_size (std:: size_t size) noexcept {
134+ return ipc::make_align ( alignof (std:: max_align_t ),
135+ (((size - 1 ) / ipc::large_msg_align) + 1 ) * ipc::large_msg_align) ;
139136}
140137
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 ;
138+ chunk_info_t * chunk_storage_info (std::size_t chunk_size) {
139+ return chunk_storages ()[chunk_size]. get_info (chunk_size) ;
143140}
144141
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];
148- }
149-
150- std::pair<std::size_t , void *> apply_storage (std::size_t size) {
142+ std::pair<ipc::storage_id_t , void *> apply_storage (std::size_t size) {
151143 std::size_t chunk_size = calc_chunk_size (size);
152- auto & chunk_shm = chunk_storage (chunk_size);
153-
154- auto info = chunk_shm.get_info (chunk_size);
144+ auto info = chunk_storage_info (chunk_size);
155145 if (info == nullptr ) return {};
156146
157147 info->lock_ .lock ();
@@ -163,27 +153,25 @@ std::pair<std::size_t, void*> apply_storage(std::size_t size) {
163153 return { id, info->at (chunk_size, id) };
164154}
165155
166- void *find_storage (std:: size_t id, std::size_t size) {
167- if (id == ipc::invalid_value ) {
156+ void *find_storage (ipc:: storage_id_t id, std::size_t size) {
157+ if (id < 0 ) {
168158 ipc::error (" [find_storage] id is invalid: id = %ld, size = %zd\n " , (long )id, size);
169159 return nullptr ;
170160 }
171161 std::size_t chunk_size = calc_chunk_size (size);
172- auto & chunk_shm = chunk_storage (chunk_size);
173- auto info = chunk_shm.get_info (chunk_size);
162+ auto info = chunk_storage_info (chunk_size);
174163 if (info == nullptr ) return nullptr ;
175164 return info->at (chunk_size, id);
176165}
177166
178- void clear_storage (std:: size_t id, std::size_t size) {
179- if (id == ipc::invalid_value ) {
167+ void release_storage (ipc:: storage_id_t id, std::size_t size) {
168+ if (id < 0 ) {
180169 ipc::error (" [clear_storage] id is invalid: id = %ld, size = %zd\n " , (long )id, size);
181170 return ;
182171 }
183172
184173 std::size_t chunk_size = calc_chunk_size (size);
185- auto & chunk_shm = chunk_storage (chunk_size);
186- auto info = chunk_shm.get_info (chunk_size);
174+ auto info = chunk_storage_info (chunk_size);
187175 if (info == nullptr ) return ;
188176
189177 info->lock_ .lock ();
@@ -195,9 +183,14 @@ template <typename MsgT>
195183bool recycle_message (void * p) {
196184 auto msg = static_cast <MsgT*>(p);
197185 if (msg->storage_ ) {
198- clear_storage (
199- *reinterpret_cast <std::size_t *>(&msg->data_ ),
200- static_cast <std::int32_t >(ipc::data_length) + msg->remain_ );
186+ std::int32_t r_size = static_cast <std::int32_t >(ipc::data_length) + msg->remain_ ;
187+ if (r_size <= 0 ) {
188+ ipc::error (" [recycle_message] invalid msg size: %d\n " , (int )r_size);
189+ return true ;
190+ }
191+ release_storage (
192+ *reinterpret_cast <ipc::storage_id_t *>(&msg->data_ ),
193+ static_cast <std::size_t >(r_size));
201194 }
202195 return true ;
203196}
@@ -220,7 +213,7 @@ struct conn_info_head {
220213 * - https://developercommunity.visualstudio.com/content/problem/124121/thread-local-variables-fail-to-be-initialized-when.html
221214 * - https://software.intel.com/en-us/forums/intel-c-compiler/topic/684827
222215 */
223- ipc::tls::pointer<ipc::unordered_map <msg_id_t , cache_t >> recv_cache_;
216+ ipc::tls::pointer<ipc::map <msg_id_t , cache_t >> recv_cache_;
224217
225218 conn_info_head (char const * name)
226219 : name_ {name}
@@ -409,11 +402,11 @@ static bool send(F&& gen_push, ipc::handle_t h, void const * data, std::size_t s
409402 static_cast <std::int32_t >(ipc::data_length), &(dat.first ), 0 );
410403 }
411404 // try using message fragment
412- // ipc::log("fail: shm::handle for big message. msg_id: %zd, size: %zd\n", msg_id, size);
405+ // ipc::log("fail: shm::handle for big message. msg_id: %zd, size: %zd\n", msg_id, size);
413406 }
414407 // push message fragment
415408 std::int32_t offset = 0 ;
416- for (int i = 0 ; i < static_cast <int >(size / ipc::data_length); ++i, offset += ipc::data_length) {
409+ for (std:: int32_t i = 0 ; i < static_cast <std:: int32_t >(size / ipc::data_length); ++i, offset += ipc::data_length) {
417410 if (!try_push (static_cast <std::int32_t >(size) - offset - static_cast <std::int32_t >(ipc::data_length),
418411 static_cast <ipc::byte_t const *>(data) + offset, ipc::data_length)) {
419412 return false ;
@@ -479,7 +472,7 @@ static ipc::buff_t recv(ipc::handle_t h, std::size_t tm) {
479472 return {};
480473 }
481474 auto & rc = info_of (h)->recv_cache ();
482- while ( 1 ) {
475+ for (;; ) {
483476 // pop a new message
484477 typename queue_t ::value_t msg;
485478 if (!wait_for (info_of (h)->rd_waiter_ , [que, &msg] { return !que->pop (msg); }, tm)) {
@@ -491,20 +484,28 @@ static ipc::buff_t recv(ipc::handle_t h, std::size_t tm) {
491484 continue ; // ignore message to self
492485 }
493486 // msg.remain_ may minus & abs(msg.remain_) < data_length
494- std::size_t remain = static_cast <std::int32_t >(ipc::data_length) + msg.remain_ ;
487+ std::int32_t r_size = static_cast <std::int32_t >(ipc::data_length) + msg.remain_ ;
488+ if (r_size <= 0 ) {
489+ ipc::error (" fail: recv, r_size = %d\n " , (int )r_size);
490+ return {};
491+ }
492+ std::size_t msg_size = static_cast <std::size_t >(r_size);
495493 // find cache with msg.id_
496494 auto cac_it = rc.find (msg.id_ );
497495 if (cac_it == rc.end ()) {
498- if (remain <= ipc::data_length) {
499- return make_cache (msg.data_ , remain );
496+ if (msg_size <= ipc::data_length) {
497+ return make_cache (msg.data_ , msg_size );
500498 }
501499 if (msg.storage_ ) {
502500 std::size_t buf_id = *reinterpret_cast <std::size_t *>(&msg.data_ );
503- void * buf = find_storage (buf_id, remain );
501+ void * buf = find_storage (buf_id, msg_size );
504502 if (buf != nullptr ) {
505- return ipc::buff_t {buf, remain};
503+ return ipc::buff_t {buf, msg_size};
504+ }
505+ else {
506+ ipc::log (" fail: shm::handle for big message. msg_id: %zd, buf_id: %zd, size: %zd\n " , msg.id_ , buf_id, msg_size);
507+ continue ;
506508 }
507- else ipc::log (" fail: shm::handle for big message. msg_id: %zd, buf_id: %zd, size: %zd\n " , msg.id_ , buf_id, remain);
508509 }
509510 // gc
510511 if (rc.size () > 1024 ) {
@@ -518,14 +519,14 @@ static ipc::buff_t recv(ipc::handle_t h, std::size_t tm) {
518519 for (auto id : need_del) rc.erase (id);
519520 }
520521 // cache the first message fragment
521- rc.emplace (msg.id_ , cache_t { ipc::data_length, make_cache (msg.data_ , remain ) });
522+ rc.emplace (msg.id_ , cache_t { ipc::data_length, make_cache (msg.data_ , msg_size ) });
522523 }
523524 // has cached before this message
524525 else {
525526 auto & cac = cac_it->second ;
526527 // this is the last message fragment
527528 if (msg.remain_ <= 0 ) {
528- cac.append (&(msg.data_ ), remain );
529+ cac.append (&(msg.data_ ), msg_size );
529530 // finish this message, erase it from cache
530531 auto buff = std::move (cac.buff_ );
531532 rc.erase (cac_it);
0 commit comments