Skip to content

Commit 1a39118

Browse files
authored
Merge pull request #38 from mutouyun/issue-17
Issue 17
2 parents 9667d50 + a85199d commit 1a39118

File tree

4 files changed

+92
-88
lines changed

4 files changed

+92
-88
lines changed

include/libipc/def.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +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,
3233
large_msg_cache = 32,
3334
default_timeout = 100 // ms
3435
};

src/ipc.cpp

Lines changed: 79 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
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

157150
std::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();

src/libipc/memory/resource.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,13 @@
1717
namespace ipc {
1818
namespace mem {
1919

20-
using async_pool_alloc = static_wrapper<variable_wrapper<async_wrapper<
21-
detail::fixed_alloc<
22-
variable_alloc <sizeof(void*) * 1024 * 256>,
23-
fixed_expand_policy<sizeof(void*) * 1024, sizeof(void*) * 1024 * 256>
24-
>,
25-
default_recycler >>>;
20+
//using async_pool_alloc = static_wrapper<variable_wrapper<async_wrapper<
21+
// detail::fixed_alloc<
22+
// variable_alloc <sizeof(void*) * 1024 * 256>,
23+
// fixed_expand_policy<sizeof(void*) * 1024, sizeof(void*) * 1024 * 256>
24+
// >,
25+
// default_recycler >>>;
26+
using async_pool_alloc = ipc::mem::static_alloc;
2627

2728
template <typename T>
2829
using allocator = allocator_wrapper<T, async_pool_alloc>;

src/libipc/utility/utility.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,9 @@ T horrible_cast(U val) {
5353
return u.out;
5454
}
5555

56+
IPC_CONSTEXPR_ std::size_t make_align(std::size_t align, std::size_t size) {
57+
// align must be 2^n
58+
return (size + align - 1) & ~(align - 1);
59+
}
60+
5661
} // namespace ipc

0 commit comments

Comments
 (0)