Skip to content

Commit 2179ce2

Browse files
committed
fix some bugs, adjust the test cases
1 parent bbd2419 commit 2179ce2

File tree

6 files changed

+148
-106
lines changed

6 files changed

+148
-106
lines changed

include/libipc/def.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ enum : std::size_t {
2929
invalid_value = (std::numeric_limits<std::size_t>::max)(),
3030
data_length = 64,
3131
large_msg_limit = data_length,
32-
large_msg_align = 512,
32+
large_msg_align = 1024,
3333
large_msg_cache = 32,
3434
default_timeout = 100 // ms
3535
};

src/ipc.cpp

Lines changed: 52 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -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>
195183
bool 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);

src/libipc/memory/resource.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <utility>
66
#include <functional>
77
#include <unordered_map>
8+
#include <map>
89
#include <string>
910
#include <cstdio>
1011

@@ -49,6 +50,11 @@ using unordered_map = std::unordered_map<
4950
Key, T, std::hash<Key>, std::equal_to<Key>, ipc::mem::allocator<std::pair<const Key, T>>
5051
>;
5152

53+
template <typename Key, typename T>
54+
using map = std::map<
55+
Key, T, std::less<Key>, ipc::mem::allocator<std::pair<const Key, T>>
56+
>;
57+
5258
template <typename Char>
5359
using basic_string = std::basic_string<
5460
Char, std::char_traits<Char>, ipc::mem::allocator<Char>

src/libipc/utility/id_pool.h

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,23 @@
22

33
#include <type_traits> // std::aligned_storage_t
44
#include <cstring> // std::memcmp
5+
#include <cstdint>
56

67
#include "libipc/def.h"
7-
88
#include "libipc/platform/detail.h"
99

1010
namespace ipc {
1111

12+
using storage_id_t = std::int32_t;
13+
1214
template <std::size_t DataSize, std::size_t AlignSize>
1315
struct id_type;
1416

1517
template <std::size_t AlignSize>
1618
struct id_type<0, AlignSize> {
1719
uint_t<8> id_;
1820

19-
id_type& operator=(std::size_t val) {
21+
id_type& operator=(storage_id_t val) {
2022
id_ = static_cast<uint_t<8>>(val);
2123
return (*this);
2224
}
@@ -57,7 +59,7 @@ class id_pool {
5759
}
5860

5961
void init() {
60-
for (std::size_t i = 0; i < max_count;) {
62+
for (storage_id_t i = 0; i < max_count;) {
6163
i = next_[i] = (i + 1);
6264
}
6365
}
@@ -71,31 +73,31 @@ class id_pool {
7173
return cursor_ == max_count;
7274
}
7375

74-
std::size_t acquire() {
75-
if (empty()) return invalid_value;
76-
std::size_t id = cursor_;
76+
storage_id_t acquire() {
77+
if (empty()) return -1;
78+
storage_id_t id = cursor_;
7779
cursor_ = next_[id]; // point to next
7880
return id;
7981
}
8082

81-
bool release(std::size_t id) {
82-
if (id == invalid_value) return false;
83+
bool release(storage_id_t id) {
84+
if (id < 0) return false;
8385
next_[id] = cursor_;
8486
cursor_ = static_cast<uint_t<8>>(id); // put it back
8587
return true;
8688
}
8789

88-
void * at(std::size_t id) { return &(next_[id].data_); }
89-
void const * at(std::size_t id) const { return &(next_[id].data_); }
90+
void * at(storage_id_t id) { return &(next_[id].data_); }
91+
void const * at(storage_id_t id) const { return &(next_[id].data_); }
9092
};
9193

9294
template <typename T>
9395
class obj_pool : public id_pool<sizeof(T), alignof(T)> {
9496
using base_t = id_pool<sizeof(T), alignof(T)>;
9597

9698
public:
97-
T * at(std::size_t id) { return reinterpret_cast<T *>(base_t::at(id)); }
98-
T const * at(std::size_t id) const { return reinterpret_cast<T const *>(base_t::at(id)); }
99+
T * at(storage_id_t id) { return reinterpret_cast<T *>(base_t::at(id)); }
100+
T const * at(storage_id_t id) const { return reinterpret_cast<T const *>(base_t::at(id)); }
99101
};
100102

101103
} // namespace ipc

0 commit comments

Comments
 (0)