Spaces:
Running
Running
批量生成函数注释
Browse files- crazy_functions/test_project/cpp/cppipc/buffer.cpp +87 -0
- crazy_functions/test_project/cpp/cppipc/ipc.cpp +701 -0
- crazy_functions/test_project/cpp/cppipc/policy.h +25 -0
- crazy_functions/test_project/cpp/cppipc/pool_alloc.cpp +17 -0
- crazy_functions/test_project/cpp/cppipc/prod_cons.h +433 -0
- crazy_functions/test_project/cpp/cppipc/queue.h +216 -0
- crazy_functions/test_project/cpp/cppipc/shm.cpp +103 -0
- crazy_functions/test_project/cpp/cppipc/waiter.h +83 -0
- crazy_functions/test_project/{Cpp → cpp}/libJPG/JpegLibrary.tps +0 -0
- crazy_functions/test_project/{Cpp → cpp}/libJPG/UElibJPG.Build.cs +0 -0
- crazy_functions/test_project/{Cpp → cpp}/libJPG/jpeg-compressor.tps +0 -0
- crazy_functions/test_project/{Cpp → cpp}/libJPG/jpgd.cpp +0 -0
- crazy_functions/test_project/{Cpp → cpp}/libJPG/jpgd.h +0 -0
- crazy_functions/test_project/{Cpp → cpp}/libJPG/jpge.cpp +0 -0
- crazy_functions/test_project/{Cpp → cpp}/libJPG/jpge.h +0 -0
- crazy_functions/test_project/{Cpp → cpp}/libJPG/来源 +0 -0
- crazy_functions/test_project/其他测试 +9 -0
- crazy_functions/生成函数注释.py +63 -0
- functional_crazy.py +6 -1
- toolbox.py +1 -1
crazy_functions/test_project/cpp/cppipc/buffer.cpp
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "libipc/buffer.h"
|
| 2 |
+
#include "libipc/utility/pimpl.h"
|
| 3 |
+
|
| 4 |
+
#include <cstring>
|
| 5 |
+
|
| 6 |
+
namespace ipc {
|
| 7 |
+
|
| 8 |
+
bool operator==(buffer const & b1, buffer const & b2) {
|
| 9 |
+
return (b1.size() == b2.size()) && (std::memcmp(b1.data(), b2.data(), b1.size()) == 0);
|
| 10 |
+
}
|
| 11 |
+
|
| 12 |
+
bool operator!=(buffer const & b1, buffer const & b2) {
|
| 13 |
+
return !(b1 == b2);
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
class buffer::buffer_ : public pimpl<buffer_> {
|
| 17 |
+
public:
|
| 18 |
+
void* p_;
|
| 19 |
+
std::size_t s_;
|
| 20 |
+
void* a_;
|
| 21 |
+
buffer::destructor_t d_;
|
| 22 |
+
|
| 23 |
+
buffer_(void* p, std::size_t s, buffer::destructor_t d, void* a)
|
| 24 |
+
: p_(p), s_(s), a_(a), d_(d) {
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
~buffer_() {
|
| 28 |
+
if (d_ == nullptr) return;
|
| 29 |
+
d_((a_ == nullptr) ? p_ : a_, s_);
|
| 30 |
+
}
|
| 31 |
+
};
|
| 32 |
+
|
| 33 |
+
buffer::buffer()
|
| 34 |
+
: buffer(nullptr, 0, nullptr, nullptr) {
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
buffer::buffer(void* p, std::size_t s, destructor_t d)
|
| 38 |
+
: p_(p_->make(p, s, d, nullptr)) {
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
buffer::buffer(void* p, std::size_t s, destructor_t d, void* additional)
|
| 42 |
+
: p_(p_->make(p, s, d, additional)) {
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
buffer::buffer(void* p, std::size_t s)
|
| 46 |
+
: buffer(p, s, nullptr) {
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
buffer::buffer(char const & c)
|
| 50 |
+
: buffer(const_cast<char*>(&c), 1) {
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
buffer::buffer(buffer&& rhs)
|
| 54 |
+
: buffer() {
|
| 55 |
+
swap(rhs);
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
buffer::~buffer() {
|
| 59 |
+
p_->clear();
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
void buffer::swap(buffer& rhs) {
|
| 63 |
+
std::swap(p_, rhs.p_);
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
buffer& buffer::operator=(buffer rhs) {
|
| 67 |
+
swap(rhs);
|
| 68 |
+
return *this;
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
bool buffer::empty() const noexcept {
|
| 72 |
+
return (impl(p_)->p_ == nullptr) || (impl(p_)->s_ == 0);
|
| 73 |
+
}
|
| 74 |
+
|
| 75 |
+
void* buffer::data() noexcept {
|
| 76 |
+
return impl(p_)->p_;
|
| 77 |
+
}
|
| 78 |
+
|
| 79 |
+
void const * buffer::data() const noexcept {
|
| 80 |
+
return impl(p_)->p_;
|
| 81 |
+
}
|
| 82 |
+
|
| 83 |
+
std::size_t buffer::size() const noexcept {
|
| 84 |
+
return impl(p_)->s_;
|
| 85 |
+
}
|
| 86 |
+
|
| 87 |
+
} // namespace ipc
|
crazy_functions/test_project/cpp/cppipc/ipc.cpp
ADDED
|
@@ -0,0 +1,701 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
#include <type_traits>
|
| 3 |
+
#include <cstring>
|
| 4 |
+
#include <algorithm>
|
| 5 |
+
#include <utility> // std::pair, std::move, std::forward
|
| 6 |
+
#include <atomic>
|
| 7 |
+
#include <type_traits> // aligned_storage_t
|
| 8 |
+
#include <string>
|
| 9 |
+
#include <vector>
|
| 10 |
+
#include <array>
|
| 11 |
+
#include <cassert>
|
| 12 |
+
|
| 13 |
+
#include "libipc/ipc.h"
|
| 14 |
+
#include "libipc/def.h"
|
| 15 |
+
#include "libipc/shm.h"
|
| 16 |
+
#include "libipc/pool_alloc.h"
|
| 17 |
+
#include "libipc/queue.h"
|
| 18 |
+
#include "libipc/policy.h"
|
| 19 |
+
#include "libipc/rw_lock.h"
|
| 20 |
+
#include "libipc/waiter.h"
|
| 21 |
+
|
| 22 |
+
#include "libipc/utility/log.h"
|
| 23 |
+
#include "libipc/utility/id_pool.h"
|
| 24 |
+
#include "libipc/utility/scope_guard.h"
|
| 25 |
+
#include "libipc/utility/utility.h"
|
| 26 |
+
|
| 27 |
+
#include "libipc/memory/resource.h"
|
| 28 |
+
#include "libipc/platform/detail.h"
|
| 29 |
+
#include "libipc/circ/elem_array.h"
|
| 30 |
+
|
| 31 |
+
namespace {
|
| 32 |
+
|
| 33 |
+
using msg_id_t = std::uint32_t;
|
| 34 |
+
using acc_t = std::atomic<msg_id_t>;
|
| 35 |
+
|
| 36 |
+
template <std::size_t DataSize, std::size_t AlignSize>
|
| 37 |
+
struct msg_t;
|
| 38 |
+
|
| 39 |
+
template <std::size_t AlignSize>
|
| 40 |
+
struct msg_t<0, AlignSize> {
|
| 41 |
+
msg_id_t cc_id_;
|
| 42 |
+
msg_id_t id_;
|
| 43 |
+
std::int32_t remain_;
|
| 44 |
+
bool storage_;
|
| 45 |
+
};
|
| 46 |
+
|
| 47 |
+
template <std::size_t DataSize, std::size_t AlignSize>
|
| 48 |
+
struct msg_t : msg_t<0, AlignSize> {
|
| 49 |
+
std::aligned_storage_t<DataSize, AlignSize> data_ {};
|
| 50 |
+
|
| 51 |
+
msg_t() = default;
|
| 52 |
+
msg_t(msg_id_t cc_id, msg_id_t id, std::int32_t remain, void const * data, std::size_t size)
|
| 53 |
+
: msg_t<0, AlignSize> {cc_id, id, remain, (data == nullptr) || (size == 0)} {
|
| 54 |
+
if (this->storage_) {
|
| 55 |
+
if (data != nullptr) {
|
| 56 |
+
// copy storage-id
|
| 57 |
+
*reinterpret_cast<ipc::storage_id_t*>(&data_) =
|
| 58 |
+
*static_cast<ipc::storage_id_t const *>(data);
|
| 59 |
+
}
|
| 60 |
+
}
|
| 61 |
+
else std::memcpy(&data_, data, size);
|
| 62 |
+
}
|
| 63 |
+
};
|
| 64 |
+
|
| 65 |
+
template <typename T>
|
| 66 |
+
ipc::buff_t make_cache(T& data, std::size_t size) {
|
| 67 |
+
auto ptr = ipc::mem::alloc(size);
|
| 68 |
+
std::memcpy(ptr, &data, (ipc::detail::min)(sizeof(data), size));
|
| 69 |
+
return { ptr, size, ipc::mem::free };
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
struct cache_t {
|
| 73 |
+
std::size_t fill_;
|
| 74 |
+
ipc::buff_t buff_;
|
| 75 |
+
|
| 76 |
+
cache_t(std::size_t f, ipc::buff_t && b)
|
| 77 |
+
: fill_(f), buff_(std::move(b))
|
| 78 |
+
{}
|
| 79 |
+
|
| 80 |
+
void append(void const * data, std::size_t size) {
|
| 81 |
+
if (fill_ >= buff_.size() || data == nullptr || size == 0) return;
|
| 82 |
+
auto new_fill = (ipc::detail::min)(fill_ + size, buff_.size());
|
| 83 |
+
std::memcpy(static_cast<ipc::byte_t*>(buff_.data()) + fill_, data, new_fill - fill_);
|
| 84 |
+
fill_ = new_fill;
|
| 85 |
+
}
|
| 86 |
+
};
|
| 87 |
+
|
| 88 |
+
auto cc_acc() {
|
| 89 |
+
static ipc::shm::handle acc_h("__CA_CONN__", sizeof(acc_t));
|
| 90 |
+
return static_cast<acc_t*>(acc_h.get());
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
+
IPC_CONSTEXPR_ std::size_t align_chunk_size(std::size_t size) noexcept {
|
| 94 |
+
return (((size - 1) / ipc::large_msg_align) + 1) * ipc::large_msg_align;
|
| 95 |
+
}
|
| 96 |
+
|
| 97 |
+
IPC_CONSTEXPR_ std::size_t calc_chunk_size(std::size_t size) noexcept {
|
| 98 |
+
return ipc::make_align(alignof(std::max_align_t), align_chunk_size(
|
| 99 |
+
ipc::make_align(alignof(std::max_align_t), sizeof(std::atomic<ipc::circ::cc_t>)) + size));
|
| 100 |
+
}
|
| 101 |
+
|
| 102 |
+
struct chunk_t {
|
| 103 |
+
std::atomic<ipc::circ::cc_t> &conns() noexcept {
|
| 104 |
+
return *reinterpret_cast<std::atomic<ipc::circ::cc_t> *>(this);
|
| 105 |
+
}
|
| 106 |
+
|
| 107 |
+
void *data() noexcept {
|
| 108 |
+
return reinterpret_cast<ipc::byte_t *>(this)
|
| 109 |
+
+ ipc::make_align(alignof(std::max_align_t), sizeof(std::atomic<ipc::circ::cc_t>));
|
| 110 |
+
}
|
| 111 |
+
};
|
| 112 |
+
|
| 113 |
+
struct chunk_info_t {
|
| 114 |
+
ipc::id_pool<> pool_;
|
| 115 |
+
ipc::spin_lock lock_;
|
| 116 |
+
|
| 117 |
+
IPC_CONSTEXPR_ static std::size_t chunks_mem_size(std::size_t chunk_size) noexcept {
|
| 118 |
+
return ipc::id_pool<>::max_count * chunk_size;
|
| 119 |
+
}
|
| 120 |
+
|
| 121 |
+
ipc::byte_t *chunks_mem() noexcept {
|
| 122 |
+
return reinterpret_cast<ipc::byte_t *>(this + 1);
|
| 123 |
+
}
|
| 124 |
+
|
| 125 |
+
chunk_t *at(std::size_t chunk_size, ipc::storage_id_t id) noexcept {
|
| 126 |
+
if (id < 0) return nullptr;
|
| 127 |
+
return reinterpret_cast<chunk_t *>(chunks_mem() + (chunk_size * id));
|
| 128 |
+
}
|
| 129 |
+
};
|
| 130 |
+
|
| 131 |
+
auto& chunk_storages() {
|
| 132 |
+
class chunk_handle_t {
|
| 133 |
+
ipc::shm::handle handle_;
|
| 134 |
+
|
| 135 |
+
public:
|
| 136 |
+
chunk_info_t *get_info(std::size_t chunk_size) {
|
| 137 |
+
if (!handle_.valid() &&
|
| 138 |
+
!handle_.acquire( ("__CHUNK_INFO__" + ipc::to_string(chunk_size)).c_str(),
|
| 139 |
+
sizeof(chunk_info_t) + chunk_info_t::chunks_mem_size(chunk_size) )) {
|
| 140 |
+
ipc::error("[chunk_storages] chunk_shm.id_info_.acquire failed: chunk_size = %zd\n", chunk_size);
|
| 141 |
+
return nullptr;
|
| 142 |
+
}
|
| 143 |
+
auto info = static_cast<chunk_info_t*>(handle_.get());
|
| 144 |
+
if (info == nullptr) {
|
| 145 |
+
ipc::error("[chunk_storages] chunk_shm.id_info_.get failed: chunk_size = %zd\n", chunk_size);
|
| 146 |
+
return nullptr;
|
| 147 |
+
}
|
| 148 |
+
return info;
|
| 149 |
+
}
|
| 150 |
+
};
|
| 151 |
+
static ipc::map<std::size_t, chunk_handle_t> chunk_hs;
|
| 152 |
+
return chunk_hs;
|
| 153 |
+
}
|
| 154 |
+
|
| 155 |
+
chunk_info_t *chunk_storage_info(std::size_t chunk_size) {
|
| 156 |
+
auto &storages = chunk_storages();
|
| 157 |
+
std::decay_t<decltype(storages)>::iterator it;
|
| 158 |
+
{
|
| 159 |
+
static ipc::rw_lock lock;
|
| 160 |
+
IPC_UNUSED_ std::shared_lock<ipc::rw_lock> guard {lock};
|
| 161 |
+
if ((it = storages.find(chunk_size)) == storages.end()) {
|
| 162 |
+
using chunk_handle_t = std::decay_t<decltype(storages)>::value_type::second_type;
|
| 163 |
+
guard.unlock();
|
| 164 |
+
IPC_UNUSED_ std::lock_guard<ipc::rw_lock> guard {lock};
|
| 165 |
+
it = storages.emplace(chunk_size, chunk_handle_t{}).first;
|
| 166 |
+
}
|
| 167 |
+
}
|
| 168 |
+
return it->second.get_info(chunk_size);
|
| 169 |
+
}
|
| 170 |
+
|
| 171 |
+
std::pair<ipc::storage_id_t, void*> acquire_storage(std::size_t size, ipc::circ::cc_t conns) {
|
| 172 |
+
std::size_t chunk_size = calc_chunk_size(size);
|
| 173 |
+
auto info = chunk_storage_info(chunk_size);
|
| 174 |
+
if (info == nullptr) return {};
|
| 175 |
+
|
| 176 |
+
info->lock_.lock();
|
| 177 |
+
info->pool_.prepare();
|
| 178 |
+
// got an unique id
|
| 179 |
+
auto id = info->pool_.acquire();
|
| 180 |
+
info->lock_.unlock();
|
| 181 |
+
|
| 182 |
+
auto chunk = info->at(chunk_size, id);
|
| 183 |
+
if (chunk == nullptr) return {};
|
| 184 |
+
chunk->conns().store(conns, std::memory_order_relaxed);
|
| 185 |
+
return { id, chunk->data() };
|
| 186 |
+
}
|
| 187 |
+
|
| 188 |
+
void *find_storage(ipc::storage_id_t id, std::size_t size) {
|
| 189 |
+
if (id < 0) {
|
| 190 |
+
ipc::error("[find_storage] id is invalid: id = %ld, size = %zd\n", (long)id, size);
|
| 191 |
+
return nullptr;
|
| 192 |
+
}
|
| 193 |
+
std::size_t chunk_size = calc_chunk_size(size);
|
| 194 |
+
auto info = chunk_storage_info(chunk_size);
|
| 195 |
+
if (info == nullptr) return nullptr;
|
| 196 |
+
return info->at(chunk_size, id)->data();
|
| 197 |
+
}
|
| 198 |
+
|
| 199 |
+
void release_storage(ipc::storage_id_t id, std::size_t size) {
|
| 200 |
+
if (id < 0) {
|
| 201 |
+
ipc::error("[release_storage] id is invalid: id = %ld, size = %zd\n", (long)id, size);
|
| 202 |
+
return;
|
| 203 |
+
}
|
| 204 |
+
std::size_t chunk_size = calc_chunk_size(size);
|
| 205 |
+
auto info = chunk_storage_info(chunk_size);
|
| 206 |
+
if (info == nullptr) return;
|
| 207 |
+
info->lock_.lock();
|
| 208 |
+
info->pool_.release(id);
|
| 209 |
+
info->lock_.unlock();
|
| 210 |
+
}
|
| 211 |
+
|
| 212 |
+
template <ipc::relat Rp, ipc::relat Rc>
|
| 213 |
+
bool sub_rc(ipc::wr<Rp, Rc, ipc::trans::unicast>,
|
| 214 |
+
std::atomic<ipc::circ::cc_t> &/*conns*/, ipc::circ::cc_t /*curr_conns*/, ipc::circ::cc_t /*conn_id*/) noexcept {
|
| 215 |
+
return true;
|
| 216 |
+
}
|
| 217 |
+
|
| 218 |
+
template <ipc::relat Rp, ipc::relat Rc>
|
| 219 |
+
bool sub_rc(ipc::wr<Rp, Rc, ipc::trans::broadcast>,
|
| 220 |
+
std::atomic<ipc::circ::cc_t> &conns, ipc::circ::cc_t curr_conns, ipc::circ::cc_t conn_id) noexcept {
|
| 221 |
+
auto last_conns = curr_conns & ~conn_id;
|
| 222 |
+
for (unsigned k = 0;;) {
|
| 223 |
+
auto chunk_conns = conns.load(std::memory_order_acquire);
|
| 224 |
+
if (conns.compare_exchange_weak(chunk_conns, chunk_conns & last_conns, std::memory_order_release)) {
|
| 225 |
+
return (chunk_conns & last_conns) == 0;
|
| 226 |
+
}
|
| 227 |
+
ipc::yield(k);
|
| 228 |
+
}
|
| 229 |
+
}
|
| 230 |
+
|
| 231 |
+
template <typename Flag>
|
| 232 |
+
void recycle_storage(ipc::storage_id_t id, std::size_t size, ipc::circ::cc_t curr_conns, ipc::circ::cc_t conn_id) {
|
| 233 |
+
if (id < 0) {
|
| 234 |
+
ipc::error("[recycle_storage] id is invalid: id = %ld, size = %zd\n", (long)id, size);
|
| 235 |
+
return;
|
| 236 |
+
}
|
| 237 |
+
std::size_t chunk_size = calc_chunk_size(size);
|
| 238 |
+
auto info = chunk_storage_info(chunk_size);
|
| 239 |
+
if (info == nullptr) return;
|
| 240 |
+
|
| 241 |
+
auto chunk = info->at(chunk_size, id);
|
| 242 |
+
if (chunk == nullptr) return;
|
| 243 |
+
|
| 244 |
+
if (!sub_rc(Flag{}, chunk->conns(), curr_conns, conn_id)) {
|
| 245 |
+
return;
|
| 246 |
+
}
|
| 247 |
+
info->lock_.lock();
|
| 248 |
+
info->pool_.release(id);
|
| 249 |
+
info->lock_.unlock();
|
| 250 |
+
}
|
| 251 |
+
|
| 252 |
+
template <typename MsgT>
|
| 253 |
+
bool clear_message(void* p) {
|
| 254 |
+
auto msg = static_cast<MsgT*>(p);
|
| 255 |
+
if (msg->storage_) {
|
| 256 |
+
std::int32_t r_size = static_cast<std::int32_t>(ipc::data_length) + msg->remain_;
|
| 257 |
+
if (r_size <= 0) {
|
| 258 |
+
ipc::error("[clear_message] invalid msg size: %d\n", (int)r_size);
|
| 259 |
+
return true;
|
| 260 |
+
}
|
| 261 |
+
release_storage(
|
| 262 |
+
*reinterpret_cast<ipc::storage_id_t*>(&msg->data_),
|
| 263 |
+
static_cast<std::size_t>(r_size));
|
| 264 |
+
}
|
| 265 |
+
return true;
|
| 266 |
+
}
|
| 267 |
+
|
| 268 |
+
struct conn_info_head {
|
| 269 |
+
|
| 270 |
+
ipc::string name_;
|
| 271 |
+
msg_id_t cc_id_; // connection-info id
|
| 272 |
+
ipc::detail::waiter cc_waiter_, wt_waiter_, rd_waiter_;
|
| 273 |
+
ipc::shm::handle acc_h_;
|
| 274 |
+
|
| 275 |
+
conn_info_head(char const * name)
|
| 276 |
+
: name_ {name}
|
| 277 |
+
, cc_id_ {(cc_acc() == nullptr) ? 0 : cc_acc()->fetch_add(1, std::memory_order_relaxed)}
|
| 278 |
+
, cc_waiter_{("__CC_CONN__" + name_).c_str()}
|
| 279 |
+
, wt_waiter_{("__WT_CONN__" + name_).c_str()}
|
| 280 |
+
, rd_waiter_{("__RD_CONN__" + name_).c_str()}
|
| 281 |
+
, acc_h_ {("__AC_CONN__" + name_).c_str(), sizeof(acc_t)} {
|
| 282 |
+
}
|
| 283 |
+
|
| 284 |
+
void quit_waiting() {
|
| 285 |
+
cc_waiter_.quit_waiting();
|
| 286 |
+
wt_waiter_.quit_waiting();
|
| 287 |
+
rd_waiter_.quit_waiting();
|
| 288 |
+
}
|
| 289 |
+
|
| 290 |
+
auto acc() {
|
| 291 |
+
return static_cast<acc_t*>(acc_h_.get());
|
| 292 |
+
}
|
| 293 |
+
|
| 294 |
+
auto& recv_cache() {
|
| 295 |
+
thread_local ipc::unordered_map<msg_id_t, cache_t> tls;
|
| 296 |
+
return tls;
|
| 297 |
+
}
|
| 298 |
+
};
|
| 299 |
+
|
| 300 |
+
template <typename W, typename F>
|
| 301 |
+
bool wait_for(W& waiter, F&& pred, std::uint64_t tm) {
|
| 302 |
+
if (tm == 0) return !pred();
|
| 303 |
+
for (unsigned k = 0; pred();) {
|
| 304 |
+
bool ret = true;
|
| 305 |
+
ipc::sleep(k, [&k, &ret, &waiter, &pred, tm] {
|
| 306 |
+
ret = waiter.wait_if(std::forward<F>(pred), tm);
|
| 307 |
+
k = 0;
|
| 308 |
+
});
|
| 309 |
+
if (!ret) return false; // timeout or fail
|
| 310 |
+
if (k == 0) break; // k has been reset
|
| 311 |
+
}
|
| 312 |
+
return true;
|
| 313 |
+
}
|
| 314 |
+
|
| 315 |
+
template <typename Policy,
|
| 316 |
+
std::size_t DataSize = ipc::data_length,
|
| 317 |
+
std::size_t AlignSize = (ipc::detail::min)(DataSize, alignof(std::max_align_t))>
|
| 318 |
+
struct queue_generator {
|
| 319 |
+
|
| 320 |
+
using queue_t = ipc::queue<msg_t<DataSize, AlignSize>, Policy>;
|
| 321 |
+
|
| 322 |
+
struct conn_info_t : conn_info_head {
|
| 323 |
+
queue_t que_;
|
| 324 |
+
|
| 325 |
+
conn_info_t(char const * name)
|
| 326 |
+
: conn_info_head{name}
|
| 327 |
+
, que_{("__QU_CONN__" +
|
| 328 |
+
ipc::to_string(DataSize) + "__" +
|
| 329 |
+
ipc::to_string(AlignSize) + "__" + name).c_str()} {
|
| 330 |
+
}
|
| 331 |
+
|
| 332 |
+
void disconnect_receiver() {
|
| 333 |
+
bool dis = que_.disconnect();
|
| 334 |
+
this->quit_waiting();
|
| 335 |
+
if (dis) {
|
| 336 |
+
this->recv_cache().clear();
|
| 337 |
+
}
|
| 338 |
+
}
|
| 339 |
+
};
|
| 340 |
+
};
|
| 341 |
+
|
| 342 |
+
template <typename Policy>
|
| 343 |
+
struct detail_impl {
|
| 344 |
+
|
| 345 |
+
using policy_t = Policy;
|
| 346 |
+
using flag_t = typename policy_t::flag_t;
|
| 347 |
+
using queue_t = typename queue_generator<policy_t>::queue_t;
|
| 348 |
+
using conn_info_t = typename queue_generator<policy_t>::conn_info_t;
|
| 349 |
+
|
| 350 |
+
constexpr static conn_info_t* info_of(ipc::handle_t h) noexcept {
|
| 351 |
+
return static_cast<conn_info_t*>(h);
|
| 352 |
+
}
|
| 353 |
+
|
| 354 |
+
constexpr static queue_t* queue_of(ipc::handle_t h) noexcept {
|
| 355 |
+
return (info_of(h) == nullptr) ? nullptr : &(info_of(h)->que_);
|
| 356 |
+
}
|
| 357 |
+
|
| 358 |
+
/* API implementations */
|
| 359 |
+
|
| 360 |
+
static void disconnect(ipc::handle_t h) {
|
| 361 |
+
auto que = queue_of(h);
|
| 362 |
+
if (que == nullptr) {
|
| 363 |
+
return;
|
| 364 |
+
}
|
| 365 |
+
que->shut_sending();
|
| 366 |
+
assert(info_of(h) != nullptr);
|
| 367 |
+
info_of(h)->disconnect_receiver();
|
| 368 |
+
}
|
| 369 |
+
|
| 370 |
+
static bool reconnect(ipc::handle_t * ph, bool start_to_recv) {
|
| 371 |
+
assert(ph != nullptr);
|
| 372 |
+
assert(*ph != nullptr);
|
| 373 |
+
auto que = queue_of(*ph);
|
| 374 |
+
if (que == nullptr) {
|
| 375 |
+
return false;
|
| 376 |
+
}
|
| 377 |
+
if (start_to_recv) {
|
| 378 |
+
que->shut_sending();
|
| 379 |
+
if (que->connect()) { // wouldn't connect twice
|
| 380 |
+
info_of(*ph)->cc_waiter_.broadcast();
|
| 381 |
+
return true;
|
| 382 |
+
}
|
| 383 |
+
return false;
|
| 384 |
+
}
|
| 385 |
+
// start_to_recv == false
|
| 386 |
+
if (que->connected()) {
|
| 387 |
+
info_of(*ph)->disconnect_receiver();
|
| 388 |
+
}
|
| 389 |
+
return que->ready_sending();
|
| 390 |
+
}
|
| 391 |
+
|
| 392 |
+
static bool connect(ipc::handle_t * ph, char const * name, bool start_to_recv) {
|
| 393 |
+
assert(ph != nullptr);
|
| 394 |
+
if (*ph == nullptr) {
|
| 395 |
+
*ph = ipc::mem::alloc<conn_info_t>(name);
|
| 396 |
+
}
|
| 397 |
+
return reconnect(ph, start_to_recv);
|
| 398 |
+
}
|
| 399 |
+
|
| 400 |
+
static void destroy(ipc::handle_t h) {
|
| 401 |
+
disconnect(h);
|
| 402 |
+
ipc::mem::free(info_of(h));
|
| 403 |
+
}
|
| 404 |
+
|
| 405 |
+
static std::size_t recv_count(ipc::handle_t h) noexcept {
|
| 406 |
+
auto que = queue_of(h);
|
| 407 |
+
if (que == nullptr) {
|
| 408 |
+
return ipc::invalid_value;
|
| 409 |
+
}
|
| 410 |
+
return que->conn_count();
|
| 411 |
+
}
|
| 412 |
+
|
| 413 |
+
static bool wait_for_recv(ipc::handle_t h, std::size_t r_count, std::uint64_t tm) {
|
| 414 |
+
auto que = queue_of(h);
|
| 415 |
+
if (que == nullptr) {
|
| 416 |
+
return false;
|
| 417 |
+
}
|
| 418 |
+
return wait_for(info_of(h)->cc_waiter_, [que, r_count] {
|
| 419 |
+
return que->conn_count() < r_count;
|
| 420 |
+
}, tm);
|
| 421 |
+
}
|
| 422 |
+
|
| 423 |
+
template <typename F>
|
| 424 |
+
static bool send(F&& gen_push, ipc::handle_t h, void const * data, std::size_t size) {
|
| 425 |
+
if (data == nullptr || size == 0) {
|
| 426 |
+
ipc::error("fail: send(%p, %zd)\n", data, size);
|
| 427 |
+
return false;
|
| 428 |
+
}
|
| 429 |
+
auto que = queue_of(h);
|
| 430 |
+
if (que == nullptr) {
|
| 431 |
+
ipc::error("fail: send, queue_of(h) == nullptr\n");
|
| 432 |
+
return false;
|
| 433 |
+
}
|
| 434 |
+
if (que->elems() == nullptr) {
|
| 435 |
+
ipc::error("fail: send, queue_of(h)->elems() == nullptr\n");
|
| 436 |
+
return false;
|
| 437 |
+
}
|
| 438 |
+
if (!que->ready_sending()) {
|
| 439 |
+
ipc::error("fail: send, que->ready_sending() == false\n");
|
| 440 |
+
return false;
|
| 441 |
+
}
|
| 442 |
+
ipc::circ::cc_t conns = que->elems()->connections(std::memory_order_relaxed);
|
| 443 |
+
if (conns == 0) {
|
| 444 |
+
ipc::error("fail: send, there is no receiver on this connection.\n");
|
| 445 |
+
return false;
|
| 446 |
+
}
|
| 447 |
+
// calc a new message id
|
| 448 |
+
auto acc = info_of(h)->acc();
|
| 449 |
+
if (acc == nullptr) {
|
| 450 |
+
ipc::error("fail: send, info_of(h)->acc() == nullptr\n");
|
| 451 |
+
return false;
|
| 452 |
+
}
|
| 453 |
+
auto msg_id = acc->fetch_add(1, std::memory_order_relaxed);
|
| 454 |
+
auto try_push = std::forward<F>(gen_push)(info_of(h), que, msg_id);
|
| 455 |
+
if (size > ipc::large_msg_limit) {
|
| 456 |
+
auto dat = acquire_storage(size, conns);
|
| 457 |
+
void * buf = dat.second;
|
| 458 |
+
if (buf != nullptr) {
|
| 459 |
+
std::memcpy(buf, data, size);
|
| 460 |
+
return try_push(static_cast<std::int32_t>(size) -
|
| 461 |
+
static_cast<std::int32_t>(ipc::data_length), &(dat.first), 0);
|
| 462 |
+
}
|
| 463 |
+
// try using message fragment
|
| 464 |
+
//ipc::log("fail: shm::handle for big message. msg_id: %zd, size: %zd\n", msg_id, size);
|
| 465 |
+
}
|
| 466 |
+
// push message fragment
|
| 467 |
+
std::int32_t offset = 0;
|
| 468 |
+
for (std::int32_t i = 0; i < static_cast<std::int32_t>(size / ipc::data_length); ++i, offset += ipc::data_length) {
|
| 469 |
+
if (!try_push(static_cast<std::int32_t>(size) - offset - static_cast<std::int32_t>(ipc::data_length),
|
| 470 |
+
static_cast<ipc::byte_t const *>(data) + offset, ipc::data_length)) {
|
| 471 |
+
return false;
|
| 472 |
+
}
|
| 473 |
+
}
|
| 474 |
+
// if remain > 0, this is the last message fragment
|
| 475 |
+
std::int32_t remain = static_cast<std::int32_t>(size) - offset;
|
| 476 |
+
if (remain > 0) {
|
| 477 |
+
if (!try_push(remain - static_cast<std::int32_t>(ipc::data_length),
|
| 478 |
+
static_cast<ipc::byte_t const *>(data) + offset,
|
| 479 |
+
static_cast<std::size_t>(remain))) {
|
| 480 |
+
return false;
|
| 481 |
+
}
|
| 482 |
+
}
|
| 483 |
+
return true;
|
| 484 |
+
}
|
| 485 |
+
|
| 486 |
+
static bool send(ipc::handle_t h, void const * data, std::size_t size, std::uint64_t tm) {
|
| 487 |
+
return send([tm](auto info, auto que, auto msg_id) {
|
| 488 |
+
return [tm, info, que, msg_id](std::int32_t remain, void const * data, std::size_t size) {
|
| 489 |
+
if (!wait_for(info->wt_waiter_, [&] {
|
| 490 |
+
return !que->push(
|
| 491 |
+
[](void*) { return true; },
|
| 492 |
+
info->cc_id_, msg_id, remain, data, size);
|
| 493 |
+
}, tm)) {
|
| 494 |
+
ipc::log("force_push: msg_id = %zd, remain = %d, size = %zd\n", msg_id, remain, size);
|
| 495 |
+
if (!que->force_push(
|
| 496 |
+
clear_message<typename queue_t::value_t>,
|
| 497 |
+
info->cc_id_, msg_id, remain, data, size)) {
|
| 498 |
+
return false;
|
| 499 |
+
}
|
| 500 |
+
}
|
| 501 |
+
info->rd_waiter_.broadcast();
|
| 502 |
+
return true;
|
| 503 |
+
};
|
| 504 |
+
}, h, data, size);
|
| 505 |
+
}
|
| 506 |
+
|
| 507 |
+
static bool try_send(ipc::handle_t h, void const * data, std::size_t size, std::uint64_t tm) {
|
| 508 |
+
return send([tm](auto info, auto que, auto msg_id) {
|
| 509 |
+
return [tm, info, que, msg_id](std::int32_t remain, void const * data, std::size_t size) {
|
| 510 |
+
if (!wait_for(info->wt_waiter_, [&] {
|
| 511 |
+
return !que->push(
|
| 512 |
+
[](void*) { return true; },
|
| 513 |
+
info->cc_id_, msg_id, remain, data, size);
|
| 514 |
+
}, tm)) {
|
| 515 |
+
return false;
|
| 516 |
+
}
|
| 517 |
+
info->rd_waiter_.broadcast();
|
| 518 |
+
return true;
|
| 519 |
+
};
|
| 520 |
+
}, h, data, size);
|
| 521 |
+
}
|
| 522 |
+
|
| 523 |
+
static ipc::buff_t recv(ipc::handle_t h, std::uint64_t tm) {
|
| 524 |
+
auto que = queue_of(h);
|
| 525 |
+
if (que == nullptr) {
|
| 526 |
+
ipc::error("fail: recv, queue_of(h) == nullptr\n");
|
| 527 |
+
return {};
|
| 528 |
+
}
|
| 529 |
+
if (!que->connected()) {
|
| 530 |
+
// hasn't connected yet, just return.
|
| 531 |
+
return {};
|
| 532 |
+
}
|
| 533 |
+
auto& rc = info_of(h)->recv_cache();
|
| 534 |
+
for (;;) {
|
| 535 |
+
// pop a new message
|
| 536 |
+
typename queue_t::value_t msg;
|
| 537 |
+
if (!wait_for(info_of(h)->rd_waiter_, [que, &msg] {
|
| 538 |
+
return !que->pop(msg);
|
| 539 |
+
}, tm)) {
|
| 540 |
+
// pop failed, just return.
|
| 541 |
+
return {};
|
| 542 |
+
}
|
| 543 |
+
info_of(h)->wt_waiter_.broadcast();
|
| 544 |
+
if ((info_of(h)->acc() != nullptr) && (msg.cc_id_ == info_of(h)->cc_id_)) {
|
| 545 |
+
continue; // ignore message to self
|
| 546 |
+
}
|
| 547 |
+
// msg.remain_ may minus & abs(msg.remain_) < data_length
|
| 548 |
+
std::int32_t r_size = static_cast<std::int32_t>(ipc::data_length) + msg.remain_;
|
| 549 |
+
if (r_size <= 0) {
|
| 550 |
+
ipc::error("fail: recv, r_size = %d\n", (int)r_size);
|
| 551 |
+
return {};
|
| 552 |
+
}
|
| 553 |
+
std::size_t msg_size = static_cast<std::size_t>(r_size);
|
| 554 |
+
// large message
|
| 555 |
+
if (msg.storage_) {
|
| 556 |
+
ipc::storage_id_t buf_id = *reinterpret_cast<ipc::storage_id_t*>(&msg.data_);
|
| 557 |
+
void* buf = find_storage(buf_id, msg_size);
|
| 558 |
+
if (buf != nullptr) {
|
| 559 |
+
struct recycle_t {
|
| 560 |
+
ipc::storage_id_t storage_id;
|
| 561 |
+
ipc::circ::cc_t curr_conns;
|
| 562 |
+
ipc::circ::cc_t conn_id;
|
| 563 |
+
} *r_info = ipc::mem::alloc<recycle_t>(recycle_t{
|
| 564 |
+
buf_id, que->elems()->connections(std::memory_order_relaxed), que->connected_id()
|
| 565 |
+
});
|
| 566 |
+
if (r_info == nullptr) {
|
| 567 |
+
ipc::log("fail: ipc::mem::alloc<recycle_t>.\n");
|
| 568 |
+
return ipc::buff_t{buf, msg_size}; // no recycle
|
| 569 |
+
} else {
|
| 570 |
+
return ipc::buff_t{buf, msg_size, [](void* p_info, std::size_t size) {
|
| 571 |
+
auto r_info = static_cast<recycle_t *>(p_info);
|
| 572 |
+
IPC_UNUSED_ auto finally = ipc::guard([r_info] {
|
| 573 |
+
ipc::mem::free(r_info);
|
| 574 |
+
});
|
| 575 |
+
recycle_storage<flag_t>(r_info->storage_id, size, r_info->curr_conns, r_info->conn_id);
|
| 576 |
+
}, r_info};
|
| 577 |
+
}
|
| 578 |
+
} else {
|
| 579 |
+
ipc::log("fail: shm::handle for large message. msg_id: %zd, buf_id: %zd, size: %zd\n", msg.id_, buf_id, msg_size);
|
| 580 |
+
continue;
|
| 581 |
+
}
|
| 582 |
+
}
|
| 583 |
+
// find cache with msg.id_
|
| 584 |
+
auto cac_it = rc.find(msg.id_);
|
| 585 |
+
if (cac_it == rc.end()) {
|
| 586 |
+
if (msg_size <= ipc::data_length) {
|
| 587 |
+
return make_cache(msg.data_, msg_size);
|
| 588 |
+
}
|
| 589 |
+
// gc
|
| 590 |
+
if (rc.size() > 1024) {
|
| 591 |
+
std::vector<msg_id_t> need_del;
|
| 592 |
+
for (auto const & pair : rc) {
|
| 593 |
+
auto cmp = std::minmax(msg.id_, pair.first);
|
| 594 |
+
if (cmp.second - cmp.first > 8192) {
|
| 595 |
+
need_del.push_back(pair.first);
|
| 596 |
+
}
|
| 597 |
+
}
|
| 598 |
+
for (auto id : need_del) rc.erase(id);
|
| 599 |
+
}
|
| 600 |
+
// cache the first message fragment
|
| 601 |
+
rc.emplace(msg.id_, cache_t { ipc::data_length, make_cache(msg.data_, msg_size) });
|
| 602 |
+
}
|
| 603 |
+
// has cached before this message
|
| 604 |
+
else {
|
| 605 |
+
auto& cac = cac_it->second;
|
| 606 |
+
// this is the last message fragment
|
| 607 |
+
if (msg.remain_ <= 0) {
|
| 608 |
+
cac.append(&(msg.data_), msg_size);
|
| 609 |
+
// finish this message, erase it from cache
|
| 610 |
+
auto buff = std::move(cac.buff_);
|
| 611 |
+
rc.erase(cac_it);
|
| 612 |
+
return buff;
|
| 613 |
+
}
|
| 614 |
+
// there are remain datas after this message
|
| 615 |
+
cac.append(&(msg.data_), ipc::data_length);
|
| 616 |
+
}
|
| 617 |
+
}
|
| 618 |
+
}
|
| 619 |
+
|
| 620 |
+
static ipc::buff_t try_recv(ipc::handle_t h) {
|
| 621 |
+
return recv(h, 0);
|
| 622 |
+
}
|
| 623 |
+
|
| 624 |
+
}; // detail_impl<Policy>
|
| 625 |
+
|
| 626 |
+
template <typename Flag>
|
| 627 |
+
using policy_t = ipc::policy::choose<ipc::circ::elem_array, Flag>;
|
| 628 |
+
|
| 629 |
+
} // internal-linkage
|
| 630 |
+
|
| 631 |
+
namespace ipc {
|
| 632 |
+
|
| 633 |
+
template <typename Flag>
|
| 634 |
+
ipc::handle_t chan_impl<Flag>::inited() {
|
| 635 |
+
ipc::detail::waiter::init();
|
| 636 |
+
return nullptr;
|
| 637 |
+
}
|
| 638 |
+
|
| 639 |
+
template <typename Flag>
|
| 640 |
+
bool chan_impl<Flag>::connect(ipc::handle_t * ph, char const * name, unsigned mode) {
|
| 641 |
+
return detail_impl<policy_t<Flag>>::connect(ph, name, mode & receiver);
|
| 642 |
+
}
|
| 643 |
+
|
| 644 |
+
template <typename Flag>
|
| 645 |
+
bool chan_impl<Flag>::reconnect(ipc::handle_t * ph, unsigned mode) {
|
| 646 |
+
return detail_impl<policy_t<Flag>>::reconnect(ph, mode & receiver);
|
| 647 |
+
}
|
| 648 |
+
|
| 649 |
+
template <typename Flag>
|
| 650 |
+
void chan_impl<Flag>::disconnect(ipc::handle_t h) {
|
| 651 |
+
detail_impl<policy_t<Flag>>::disconnect(h);
|
| 652 |
+
}
|
| 653 |
+
|
| 654 |
+
template <typename Flag>
|
| 655 |
+
void chan_impl<Flag>::destroy(ipc::handle_t h) {
|
| 656 |
+
detail_impl<policy_t<Flag>>::destroy(h);
|
| 657 |
+
}
|
| 658 |
+
|
| 659 |
+
template <typename Flag>
|
| 660 |
+
char const * chan_impl<Flag>::name(ipc::handle_t h) {
|
| 661 |
+
auto info = detail_impl<policy_t<Flag>>::info_of(h);
|
| 662 |
+
return (info == nullptr) ? nullptr : info->name_.c_str();
|
| 663 |
+
}
|
| 664 |
+
|
| 665 |
+
template <typename Flag>
|
| 666 |
+
std::size_t chan_impl<Flag>::recv_count(ipc::handle_t h) {
|
| 667 |
+
return detail_impl<policy_t<Flag>>::recv_count(h);
|
| 668 |
+
}
|
| 669 |
+
|
| 670 |
+
template <typename Flag>
|
| 671 |
+
bool chan_impl<Flag>::wait_for_recv(ipc::handle_t h, std::size_t r_count, std::uint64_t tm) {
|
| 672 |
+
return detail_impl<policy_t<Flag>>::wait_for_recv(h, r_count, tm);
|
| 673 |
+
}
|
| 674 |
+
|
| 675 |
+
template <typename Flag>
|
| 676 |
+
bool chan_impl<Flag>::send(ipc::handle_t h, void const * data, std::size_t size, std::uint64_t tm) {
|
| 677 |
+
return detail_impl<policy_t<Flag>>::send(h, data, size, tm);
|
| 678 |
+
}
|
| 679 |
+
|
| 680 |
+
template <typename Flag>
|
| 681 |
+
buff_t chan_impl<Flag>::recv(ipc::handle_t h, std::uint64_t tm) {
|
| 682 |
+
return detail_impl<policy_t<Flag>>::recv(h, tm);
|
| 683 |
+
}
|
| 684 |
+
|
| 685 |
+
template <typename Flag>
|
| 686 |
+
bool chan_impl<Flag>::try_send(ipc::handle_t h, void const * data, std::size_t size, std::uint64_t tm) {
|
| 687 |
+
return detail_impl<policy_t<Flag>>::try_send(h, data, size, tm);
|
| 688 |
+
}
|
| 689 |
+
|
| 690 |
+
template <typename Flag>
|
| 691 |
+
buff_t chan_impl<Flag>::try_recv(ipc::handle_t h) {
|
| 692 |
+
return detail_impl<policy_t<Flag>>::try_recv(h);
|
| 693 |
+
}
|
| 694 |
+
|
| 695 |
+
template struct chan_impl<ipc::wr<relat::single, relat::single, trans::unicast >>;
|
| 696 |
+
// template struct chan_impl<ipc::wr<relat::single, relat::multi , trans::unicast >>; // TBD
|
| 697 |
+
// template struct chan_impl<ipc::wr<relat::multi , relat::multi , trans::unicast >>; // TBD
|
| 698 |
+
template struct chan_impl<ipc::wr<relat::single, relat::multi , trans::broadcast>>;
|
| 699 |
+
template struct chan_impl<ipc::wr<relat::multi , relat::multi , trans::broadcast>>;
|
| 700 |
+
|
| 701 |
+
} // namespace ipc
|
crazy_functions/test_project/cpp/cppipc/policy.h
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
#include <type_traits>
|
| 4 |
+
|
| 5 |
+
#include "libipc/def.h"
|
| 6 |
+
#include "libipc/prod_cons.h"
|
| 7 |
+
|
| 8 |
+
#include "libipc/circ/elem_array.h"
|
| 9 |
+
|
| 10 |
+
namespace ipc {
|
| 11 |
+
namespace policy {
|
| 12 |
+
|
| 13 |
+
template <template <typename, std::size_t...> class Elems, typename Flag>
|
| 14 |
+
struct choose;
|
| 15 |
+
|
| 16 |
+
template <typename Flag>
|
| 17 |
+
struct choose<circ::elem_array, Flag> {
|
| 18 |
+
using flag_t = Flag;
|
| 19 |
+
|
| 20 |
+
template <std::size_t DataSize, std::size_t AlignSize>
|
| 21 |
+
using elems_t = circ::elem_array<ipc::prod_cons_impl<flag_t>, DataSize, AlignSize>;
|
| 22 |
+
};
|
| 23 |
+
|
| 24 |
+
} // namespace policy
|
| 25 |
+
} // namespace ipc
|
crazy_functions/test_project/cpp/cppipc/pool_alloc.cpp
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "libipc/pool_alloc.h"
|
| 2 |
+
|
| 3 |
+
#include "libipc/memory/resource.h"
|
| 4 |
+
|
| 5 |
+
namespace ipc {
|
| 6 |
+
namespace mem {
|
| 7 |
+
|
| 8 |
+
void* pool_alloc::alloc(std::size_t size) {
|
| 9 |
+
return async_pool_alloc::alloc(size);
|
| 10 |
+
}
|
| 11 |
+
|
| 12 |
+
void pool_alloc::free(void* p, std::size_t size) {
|
| 13 |
+
async_pool_alloc::free(p, size);
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
} // namespace mem
|
| 17 |
+
} // namespace ipc
|
crazy_functions/test_project/cpp/cppipc/prod_cons.h
ADDED
|
@@ -0,0 +1,433 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
#include <atomic>
|
| 4 |
+
#include <utility>
|
| 5 |
+
#include <cstring>
|
| 6 |
+
#include <type_traits>
|
| 7 |
+
#include <cstdint>
|
| 8 |
+
|
| 9 |
+
#include "libipc/def.h"
|
| 10 |
+
|
| 11 |
+
#include "libipc/platform/detail.h"
|
| 12 |
+
#include "libipc/circ/elem_def.h"
|
| 13 |
+
#include "libipc/utility/log.h"
|
| 14 |
+
#include "libipc/utility/utility.h"
|
| 15 |
+
|
| 16 |
+
namespace ipc {
|
| 17 |
+
|
| 18 |
+
////////////////////////////////////////////////////////////////
|
| 19 |
+
/// producer-consumer implementation
|
| 20 |
+
////////////////////////////////////////////////////////////////
|
| 21 |
+
|
| 22 |
+
template <typename Flag>
|
| 23 |
+
struct prod_cons_impl;
|
| 24 |
+
|
| 25 |
+
template <>
|
| 26 |
+
struct prod_cons_impl<wr<relat::single, relat::single, trans::unicast>> {
|
| 27 |
+
|
| 28 |
+
template <std::size_t DataSize, std::size_t AlignSize>
|
| 29 |
+
struct elem_t {
|
| 30 |
+
std::aligned_storage_t<DataSize, AlignSize> data_ {};
|
| 31 |
+
};
|
| 32 |
+
|
| 33 |
+
alignas(cache_line_size) std::atomic<circ::u2_t> rd_; // read index
|
| 34 |
+
alignas(cache_line_size) std::atomic<circ::u2_t> wt_; // write index
|
| 35 |
+
|
| 36 |
+
constexpr circ::u2_t cursor() const noexcept {
|
| 37 |
+
return 0;
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
template <typename W, typename F, typename E>
|
| 41 |
+
bool push(W* /*wrapper*/, F&& f, E* elems) {
|
| 42 |
+
auto cur_wt = circ::index_of(wt_.load(std::memory_order_relaxed));
|
| 43 |
+
if (cur_wt == circ::index_of(rd_.load(std::memory_order_acquire) - 1)) {
|
| 44 |
+
return false; // full
|
| 45 |
+
}
|
| 46 |
+
std::forward<F>(f)(&(elems[cur_wt].data_));
|
| 47 |
+
wt_.fetch_add(1, std::memory_order_release);
|
| 48 |
+
return true;
|
| 49 |
+
}
|
| 50 |
+
|
| 51 |
+
/**
|
| 52 |
+
* In single-single-unicast, 'force_push' means 'no reader' or 'the only one reader is dead'.
|
| 53 |
+
* So we could just disconnect all connections of receiver, and return false.
|
| 54 |
+
*/
|
| 55 |
+
template <typename W, typename F, typename E>
|
| 56 |
+
bool force_push(W* wrapper, F&&, E*) {
|
| 57 |
+
wrapper->elems()->disconnect_receiver(~static_cast<circ::cc_t>(0u));
|
| 58 |
+
return false;
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
template <typename W, typename F, typename R, typename E>
|
| 62 |
+
bool pop(W* /*wrapper*/, circ::u2_t& /*cur*/, F&& f, R&& out, E* elems) {
|
| 63 |
+
auto cur_rd = circ::index_of(rd_.load(std::memory_order_relaxed));
|
| 64 |
+
if (cur_rd == circ::index_of(wt_.load(std::memory_order_acquire))) {
|
| 65 |
+
return false; // empty
|
| 66 |
+
}
|
| 67 |
+
std::forward<F>(f)(&(elems[cur_rd].data_));
|
| 68 |
+
std::forward<R>(out)(true);
|
| 69 |
+
rd_.fetch_add(1, std::memory_order_release);
|
| 70 |
+
return true;
|
| 71 |
+
}
|
| 72 |
+
};
|
| 73 |
+
|
| 74 |
+
template <>
|
| 75 |
+
struct prod_cons_impl<wr<relat::single, relat::multi , trans::unicast>>
|
| 76 |
+
: prod_cons_impl<wr<relat::single, relat::single, trans::unicast>> {
|
| 77 |
+
|
| 78 |
+
template <typename W, typename F, typename E>
|
| 79 |
+
bool force_push(W* wrapper, F&&, E*) {
|
| 80 |
+
wrapper->elems()->disconnect_receiver(1);
|
| 81 |
+
return false;
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
template <typename W, typename F, typename R,
|
| 85 |
+
template <std::size_t, std::size_t> class E, std::size_t DS, std::size_t AS>
|
| 86 |
+
bool pop(W* /*wrapper*/, circ::u2_t& /*cur*/, F&& f, R&& out, E<DS, AS>* elems) {
|
| 87 |
+
byte_t buff[DS];
|
| 88 |
+
for (unsigned k = 0;;) {
|
| 89 |
+
auto cur_rd = rd_.load(std::memory_order_relaxed);
|
| 90 |
+
if (circ::index_of(cur_rd) ==
|
| 91 |
+
circ::index_of(wt_.load(std::memory_order_acquire))) {
|
| 92 |
+
return false; // empty
|
| 93 |
+
}
|
| 94 |
+
std::memcpy(buff, &(elems[circ::index_of(cur_rd)].data_), sizeof(buff));
|
| 95 |
+
if (rd_.compare_exchange_weak(cur_rd, cur_rd + 1, std::memory_order_release)) {
|
| 96 |
+
std::forward<F>(f)(buff);
|
| 97 |
+
std::forward<R>(out)(true);
|
| 98 |
+
return true;
|
| 99 |
+
}
|
| 100 |
+
ipc::yield(k);
|
| 101 |
+
}
|
| 102 |
+
}
|
| 103 |
+
};
|
| 104 |
+
|
| 105 |
+
template <>
|
| 106 |
+
struct prod_cons_impl<wr<relat::multi , relat::multi, trans::unicast>>
|
| 107 |
+
: prod_cons_impl<wr<relat::single, relat::multi, trans::unicast>> {
|
| 108 |
+
|
| 109 |
+
using flag_t = std::uint64_t;
|
| 110 |
+
|
| 111 |
+
template <std::size_t DataSize, std::size_t AlignSize>
|
| 112 |
+
struct elem_t {
|
| 113 |
+
std::aligned_storage_t<DataSize, AlignSize> data_ {};
|
| 114 |
+
std::atomic<flag_t> f_ct_ { 0 }; // commit flag
|
| 115 |
+
};
|
| 116 |
+
|
| 117 |
+
alignas(cache_line_size) std::atomic<circ::u2_t> ct_; // commit index
|
| 118 |
+
|
| 119 |
+
template <typename W, typename F, typename E>
|
| 120 |
+
bool push(W* /*wrapper*/, F&& f, E* elems) {
|
| 121 |
+
circ::u2_t cur_ct, nxt_ct;
|
| 122 |
+
for (unsigned k = 0;;) {
|
| 123 |
+
cur_ct = ct_.load(std::memory_order_relaxed);
|
| 124 |
+
if (circ::index_of(nxt_ct = cur_ct + 1) ==
|
| 125 |
+
circ::index_of(rd_.load(std::memory_order_acquire))) {
|
| 126 |
+
return false; // full
|
| 127 |
+
}
|
| 128 |
+
if (ct_.compare_exchange_weak(cur_ct, nxt_ct, std::memory_order_acq_rel)) {
|
| 129 |
+
break;
|
| 130 |
+
}
|
| 131 |
+
ipc::yield(k);
|
| 132 |
+
}
|
| 133 |
+
auto* el = elems + circ::index_of(cur_ct);
|
| 134 |
+
std::forward<F>(f)(&(el->data_));
|
| 135 |
+
// set flag & try update wt
|
| 136 |
+
el->f_ct_.store(~static_cast<flag_t>(cur_ct), std::memory_order_release);
|
| 137 |
+
while (1) {
|
| 138 |
+
auto cac_ct = el->f_ct_.load(std::memory_order_acquire);
|
| 139 |
+
if (cur_ct != wt_.load(std::memory_order_relaxed)) {
|
| 140 |
+
return true;
|
| 141 |
+
}
|
| 142 |
+
if ((~cac_ct) != cur_ct) {
|
| 143 |
+
return true;
|
| 144 |
+
}
|
| 145 |
+
if (!el->f_ct_.compare_exchange_strong(cac_ct, 0, std::memory_order_relaxed)) {
|
| 146 |
+
return true;
|
| 147 |
+
}
|
| 148 |
+
wt_.store(nxt_ct, std::memory_order_release);
|
| 149 |
+
cur_ct = nxt_ct;
|
| 150 |
+
nxt_ct = cur_ct + 1;
|
| 151 |
+
el = elems + circ::index_of(cur_ct);
|
| 152 |
+
}
|
| 153 |
+
return true;
|
| 154 |
+
}
|
| 155 |
+
|
| 156 |
+
template <typename W, typename F, typename E>
|
| 157 |
+
bool force_push(W* wrapper, F&&, E*) {
|
| 158 |
+
wrapper->elems()->disconnect_receiver(1);
|
| 159 |
+
return false;
|
| 160 |
+
}
|
| 161 |
+
|
| 162 |
+
template <typename W, typename F, typename R,
|
| 163 |
+
template <std::size_t, std::size_t> class E, std::size_t DS, std::size_t AS>
|
| 164 |
+
bool pop(W* /*wrapper*/, circ::u2_t& /*cur*/, F&& f, R&& out, E<DS, AS>* elems) {
|
| 165 |
+
byte_t buff[DS];
|
| 166 |
+
for (unsigned k = 0;;) {
|
| 167 |
+
auto cur_rd = rd_.load(std::memory_order_relaxed);
|
| 168 |
+
auto cur_wt = wt_.load(std::memory_order_acquire);
|
| 169 |
+
auto id_rd = circ::index_of(cur_rd);
|
| 170 |
+
auto id_wt = circ::index_of(cur_wt);
|
| 171 |
+
if (id_rd == id_wt) {
|
| 172 |
+
auto* el = elems + id_wt;
|
| 173 |
+
auto cac_ct = el->f_ct_.load(std::memory_order_acquire);
|
| 174 |
+
if ((~cac_ct) != cur_wt) {
|
| 175 |
+
return false; // empty
|
| 176 |
+
}
|
| 177 |
+
if (el->f_ct_.compare_exchange_weak(cac_ct, 0, std::memory_order_relaxed)) {
|
| 178 |
+
wt_.store(cur_wt + 1, std::memory_order_release);
|
| 179 |
+
}
|
| 180 |
+
k = 0;
|
| 181 |
+
}
|
| 182 |
+
else {
|
| 183 |
+
std::memcpy(buff, &(elems[circ::index_of(cur_rd)].data_), sizeof(buff));
|
| 184 |
+
if (rd_.compare_exchange_weak(cur_rd, cur_rd + 1, std::memory_order_release)) {
|
| 185 |
+
std::forward<F>(f)(buff);
|
| 186 |
+
std::forward<R>(out)(true);
|
| 187 |
+
return true;
|
| 188 |
+
}
|
| 189 |
+
ipc::yield(k);
|
| 190 |
+
}
|
| 191 |
+
}
|
| 192 |
+
}
|
| 193 |
+
};
|
| 194 |
+
|
| 195 |
+
template <>
|
| 196 |
+
struct prod_cons_impl<wr<relat::single, relat::multi, trans::broadcast>> {
|
| 197 |
+
|
| 198 |
+
using rc_t = std::uint64_t;
|
| 199 |
+
|
| 200 |
+
enum : rc_t {
|
| 201 |
+
ep_mask = 0x00000000ffffffffull,
|
| 202 |
+
ep_incr = 0x0000000100000000ull
|
| 203 |
+
};
|
| 204 |
+
|
| 205 |
+
template <std::size_t DataSize, std::size_t AlignSize>
|
| 206 |
+
struct elem_t {
|
| 207 |
+
std::aligned_storage_t<DataSize, AlignSize> data_ {};
|
| 208 |
+
std::atomic<rc_t> rc_ { 0 }; // read-counter
|
| 209 |
+
};
|
| 210 |
+
|
| 211 |
+
alignas(cache_line_size) std::atomic<circ::u2_t> wt_; // write index
|
| 212 |
+
alignas(cache_line_size) rc_t epoch_ { 0 }; // only one writer
|
| 213 |
+
|
| 214 |
+
circ::u2_t cursor() const noexcept {
|
| 215 |
+
return wt_.load(std::memory_order_acquire);
|
| 216 |
+
}
|
| 217 |
+
|
| 218 |
+
template <typename W, typename F, typename E>
|
| 219 |
+
bool push(W* wrapper, F&& f, E* elems) {
|
| 220 |
+
E* el;
|
| 221 |
+
for (unsigned k = 0;;) {
|
| 222 |
+
circ::cc_t cc = wrapper->elems()->connections(std::memory_order_relaxed);
|
| 223 |
+
if (cc == 0) return false; // no reader
|
| 224 |
+
el = elems + circ::index_of(wt_.load(std::memory_order_relaxed));
|
| 225 |
+
// check all consumers have finished reading this element
|
| 226 |
+
auto cur_rc = el->rc_.load(std::memory_order_acquire);
|
| 227 |
+
circ::cc_t rem_cc = cur_rc & ep_mask;
|
| 228 |
+
if ((cc & rem_cc) && ((cur_rc & ~ep_mask) == epoch_)) {
|
| 229 |
+
return false; // has not finished yet
|
| 230 |
+
}
|
| 231 |
+
// consider rem_cc to be 0 here
|
| 232 |
+
if (el->rc_.compare_exchange_weak(
|
| 233 |
+
cur_rc, epoch_ | static_cast<rc_t>(cc), std::memory_order_release)) {
|
| 234 |
+
break;
|
| 235 |
+
}
|
| 236 |
+
ipc::yield(k);
|
| 237 |
+
}
|
| 238 |
+
std::forward<F>(f)(&(el->data_));
|
| 239 |
+
wt_.fetch_add(1, std::memory_order_release);
|
| 240 |
+
return true;
|
| 241 |
+
}
|
| 242 |
+
|
| 243 |
+
template <typename W, typename F, typename E>
|
| 244 |
+
bool force_push(W* wrapper, F&& f, E* elems) {
|
| 245 |
+
E* el;
|
| 246 |
+
epoch_ += ep_incr;
|
| 247 |
+
for (unsigned k = 0;;) {
|
| 248 |
+
circ::cc_t cc = wrapper->elems()->connections(std::memory_order_relaxed);
|
| 249 |
+
if (cc == 0) return false; // no reader
|
| 250 |
+
el = elems + circ::index_of(wt_.load(std::memory_order_relaxed));
|
| 251 |
+
// check all consumers have finished reading this element
|
| 252 |
+
auto cur_rc = el->rc_.load(std::memory_order_acquire);
|
| 253 |
+
circ::cc_t rem_cc = cur_rc & ep_mask;
|
| 254 |
+
if (cc & rem_cc) {
|
| 255 |
+
ipc::log("force_push: k = %u, cc = %u, rem_cc = %u\n", k, cc, rem_cc);
|
| 256 |
+
cc = wrapper->elems()->disconnect_receiver(rem_cc); // disconnect all invalid readers
|
| 257 |
+
if (cc == 0) return false; // no reader
|
| 258 |
+
}
|
| 259 |
+
// just compare & exchange
|
| 260 |
+
if (el->rc_.compare_exchange_weak(
|
| 261 |
+
cur_rc, epoch_ | static_cast<rc_t>(cc), std::memory_order_release)) {
|
| 262 |
+
break;
|
| 263 |
+
}
|
| 264 |
+
ipc::yield(k);
|
| 265 |
+
}
|
| 266 |
+
std::forward<F>(f)(&(el->data_));
|
| 267 |
+
wt_.fetch_add(1, std::memory_order_release);
|
| 268 |
+
return true;
|
| 269 |
+
}
|
| 270 |
+
|
| 271 |
+
template <typename W, typename F, typename R, typename E>
|
| 272 |
+
bool pop(W* wrapper, circ::u2_t& cur, F&& f, R&& out, E* elems) {
|
| 273 |
+
if (cur == cursor()) return false; // acquire
|
| 274 |
+
auto* el = elems + circ::index_of(cur++);
|
| 275 |
+
std::forward<F>(f)(&(el->data_));
|
| 276 |
+
for (unsigned k = 0;;) {
|
| 277 |
+
auto cur_rc = el->rc_.load(std::memory_order_acquire);
|
| 278 |
+
if ((cur_rc & ep_mask) == 0) {
|
| 279 |
+
std::forward<R>(out)(true);
|
| 280 |
+
return true;
|
| 281 |
+
}
|
| 282 |
+
auto nxt_rc = cur_rc & ~static_cast<rc_t>(wrapper->connected_id());
|
| 283 |
+
if (el->rc_.compare_exchange_weak(cur_rc, nxt_rc, std::memory_order_release)) {
|
| 284 |
+
std::forward<R>(out)((nxt_rc & ep_mask) == 0);
|
| 285 |
+
return true;
|
| 286 |
+
}
|
| 287 |
+
ipc::yield(k);
|
| 288 |
+
}
|
| 289 |
+
}
|
| 290 |
+
};
|
| 291 |
+
|
| 292 |
+
template <>
|
| 293 |
+
struct prod_cons_impl<wr<relat::multi, relat::multi, trans::broadcast>> {
|
| 294 |
+
|
| 295 |
+
using rc_t = std::uint64_t;
|
| 296 |
+
using flag_t = std::uint64_t;
|
| 297 |
+
|
| 298 |
+
enum : rc_t {
|
| 299 |
+
rc_mask = 0x00000000ffffffffull,
|
| 300 |
+
ep_mask = 0x00ffffffffffffffull,
|
| 301 |
+
ep_incr = 0x0100000000000000ull,
|
| 302 |
+
ic_mask = 0xff000000ffffffffull,
|
| 303 |
+
ic_incr = 0x0000000100000000ull
|
| 304 |
+
};
|
| 305 |
+
|
| 306 |
+
template <std::size_t DataSize, std::size_t AlignSize>
|
| 307 |
+
struct elem_t {
|
| 308 |
+
std::aligned_storage_t<DataSize, AlignSize> data_ {};
|
| 309 |
+
std::atomic<rc_t > rc_ { 0 }; // read-counter
|
| 310 |
+
std::atomic<flag_t> f_ct_ { 0 }; // commit flag
|
| 311 |
+
};
|
| 312 |
+
|
| 313 |
+
alignas(cache_line_size) std::atomic<circ::u2_t> ct_; // commit index
|
| 314 |
+
alignas(cache_line_size) std::atomic<rc_t> epoch_ { 0 };
|
| 315 |
+
|
| 316 |
+
circ::u2_t cursor() const noexcept {
|
| 317 |
+
return ct_.load(std::memory_order_acquire);
|
| 318 |
+
}
|
| 319 |
+
|
| 320 |
+
constexpr static rc_t inc_rc(rc_t rc) noexcept {
|
| 321 |
+
return (rc & ic_mask) | ((rc + ic_incr) & ~ic_mask);
|
| 322 |
+
}
|
| 323 |
+
|
| 324 |
+
constexpr static rc_t inc_mask(rc_t rc) noexcept {
|
| 325 |
+
return inc_rc(rc) & ~rc_mask;
|
| 326 |
+
}
|
| 327 |
+
|
| 328 |
+
template <typename W, typename F, typename E>
|
| 329 |
+
bool push(W* wrapper, F&& f, E* elems) {
|
| 330 |
+
E* el;
|
| 331 |
+
circ::u2_t cur_ct;
|
| 332 |
+
rc_t epoch = epoch_.load(std::memory_order_acquire);
|
| 333 |
+
for (unsigned k = 0;;) {
|
| 334 |
+
circ::cc_t cc = wrapper->elems()->connections(std::memory_order_relaxed);
|
| 335 |
+
if (cc == 0) return false; // no reader
|
| 336 |
+
el = elems + circ::index_of(cur_ct = ct_.load(std::memory_order_relaxed));
|
| 337 |
+
// check all consumers have finished reading this element
|
| 338 |
+
auto cur_rc = el->rc_.load(std::memory_order_relaxed);
|
| 339 |
+
circ::cc_t rem_cc = cur_rc & rc_mask;
|
| 340 |
+
if ((cc & rem_cc) && ((cur_rc & ~ep_mask) == epoch)) {
|
| 341 |
+
return false; // has not finished yet
|
| 342 |
+
}
|
| 343 |
+
else if (!rem_cc) {
|
| 344 |
+
auto cur_fl = el->f_ct_.load(std::memory_order_acquire);
|
| 345 |
+
if ((cur_fl != cur_ct) && cur_fl) {
|
| 346 |
+
return false; // full
|
| 347 |
+
}
|
| 348 |
+
}
|
| 349 |
+
// consider rem_cc to be 0 here
|
| 350 |
+
if (el->rc_.compare_exchange_weak(
|
| 351 |
+
cur_rc, inc_mask(epoch | (cur_rc & ep_mask)) | static_cast<rc_t>(cc), std::memory_order_relaxed) &&
|
| 352 |
+
epoch_.compare_exchange_weak(epoch, epoch, std::memory_order_acq_rel)) {
|
| 353 |
+
break;
|
| 354 |
+
}
|
| 355 |
+
ipc::yield(k);
|
| 356 |
+
}
|
| 357 |
+
// only one thread/process would touch here at one time
|
| 358 |
+
ct_.store(cur_ct + 1, std::memory_order_release);
|
| 359 |
+
std::forward<F>(f)(&(el->data_));
|
| 360 |
+
// set flag & try update wt
|
| 361 |
+
el->f_ct_.store(~static_cast<flag_t>(cur_ct), std::memory_order_release);
|
| 362 |
+
return true;
|
| 363 |
+
}
|
| 364 |
+
|
| 365 |
+
template <typename W, typename F, typename E>
|
| 366 |
+
bool force_push(W* wrapper, F&& f, E* elems) {
|
| 367 |
+
E* el;
|
| 368 |
+
circ::u2_t cur_ct;
|
| 369 |
+
rc_t epoch = epoch_.fetch_add(ep_incr, std::memory_order_release) + ep_incr;
|
| 370 |
+
for (unsigned k = 0;;) {
|
| 371 |
+
circ::cc_t cc = wrapper->elems()->connections(std::memory_order_relaxed);
|
| 372 |
+
if (cc == 0) return false; // no reader
|
| 373 |
+
el = elems + circ::index_of(cur_ct = ct_.load(std::memory_order_relaxed));
|
| 374 |
+
// check all consumers have finished reading this element
|
| 375 |
+
auto cur_rc = el->rc_.load(std::memory_order_acquire);
|
| 376 |
+
circ::cc_t rem_cc = cur_rc & rc_mask;
|
| 377 |
+
if (cc & rem_cc) {
|
| 378 |
+
ipc::log("force_push: k = %u, cc = %u, rem_cc = %u\n", k, cc, rem_cc);
|
| 379 |
+
cc = wrapper->elems()->disconnect_receiver(rem_cc); // disconnect all invalid readers
|
| 380 |
+
if (cc == 0) return false; // no reader
|
| 381 |
+
}
|
| 382 |
+
// just compare & exchange
|
| 383 |
+
if (el->rc_.compare_exchange_weak(
|
| 384 |
+
cur_rc, inc_mask(epoch | (cur_rc & ep_mask)) | static_cast<rc_t>(cc), std::memory_order_relaxed)) {
|
| 385 |
+
if (epoch == epoch_.load(std::memory_order_acquire)) {
|
| 386 |
+
break;
|
| 387 |
+
}
|
| 388 |
+
else if (push(wrapper, std::forward<F>(f), elems)) {
|
| 389 |
+
return true;
|
| 390 |
+
}
|
| 391 |
+
epoch = epoch_.fetch_add(ep_incr, std::memory_order_release) + ep_incr;
|
| 392 |
+
}
|
| 393 |
+
ipc::yield(k);
|
| 394 |
+
}
|
| 395 |
+
// only one thread/process would touch here at one time
|
| 396 |
+
ct_.store(cur_ct + 1, std::memory_order_release);
|
| 397 |
+
std::forward<F>(f)(&(el->data_));
|
| 398 |
+
// set flag & try update wt
|
| 399 |
+
el->f_ct_.store(~static_cast<flag_t>(cur_ct), std::memory_order_release);
|
| 400 |
+
return true;
|
| 401 |
+
}
|
| 402 |
+
|
| 403 |
+
template <typename W, typename F, typename R, typename E, std::size_t N>
|
| 404 |
+
bool pop(W* wrapper, circ::u2_t& cur, F&& f, R&& out, E(& elems)[N]) {
|
| 405 |
+
auto* el = elems + circ::index_of(cur);
|
| 406 |
+
auto cur_fl = el->f_ct_.load(std::memory_order_acquire);
|
| 407 |
+
if (cur_fl != ~static_cast<flag_t>(cur)) {
|
| 408 |
+
return false; // empty
|
| 409 |
+
}
|
| 410 |
+
++cur;
|
| 411 |
+
std::forward<F>(f)(&(el->data_));
|
| 412 |
+
for (unsigned k = 0;;) {
|
| 413 |
+
auto cur_rc = el->rc_.load(std::memory_order_acquire);
|
| 414 |
+
if ((cur_rc & rc_mask) == 0) {
|
| 415 |
+
std::forward<R>(out)(true);
|
| 416 |
+
el->f_ct_.store(cur + N - 1, std::memory_order_release);
|
| 417 |
+
return true;
|
| 418 |
+
}
|
| 419 |
+
auto nxt_rc = inc_rc(cur_rc) & ~static_cast<rc_t>(wrapper->connected_id());
|
| 420 |
+
bool last_one = false;
|
| 421 |
+
if ((last_one = (nxt_rc & rc_mask) == 0)) {
|
| 422 |
+
el->f_ct_.store(cur + N - 1, std::memory_order_release);
|
| 423 |
+
}
|
| 424 |
+
if (el->rc_.compare_exchange_weak(cur_rc, nxt_rc, std::memory_order_release)) {
|
| 425 |
+
std::forward<R>(out)(last_one);
|
| 426 |
+
return true;
|
| 427 |
+
}
|
| 428 |
+
ipc::yield(k);
|
| 429 |
+
}
|
| 430 |
+
}
|
| 431 |
+
};
|
| 432 |
+
|
| 433 |
+
} // namespace ipc
|
crazy_functions/test_project/cpp/cppipc/queue.h
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
#include <type_traits>
|
| 4 |
+
#include <new>
|
| 5 |
+
#include <utility> // [[since C++14]]: std::exchange
|
| 6 |
+
#include <algorithm>
|
| 7 |
+
#include <atomic>
|
| 8 |
+
#include <tuple>
|
| 9 |
+
#include <thread>
|
| 10 |
+
#include <chrono>
|
| 11 |
+
#include <string>
|
| 12 |
+
#include <cassert> // assert
|
| 13 |
+
|
| 14 |
+
#include "libipc/def.h"
|
| 15 |
+
#include "libipc/shm.h"
|
| 16 |
+
#include "libipc/rw_lock.h"
|
| 17 |
+
|
| 18 |
+
#include "libipc/utility/log.h"
|
| 19 |
+
#include "libipc/platform/detail.h"
|
| 20 |
+
#include "libipc/circ/elem_def.h"
|
| 21 |
+
|
| 22 |
+
namespace ipc {
|
| 23 |
+
namespace detail {
|
| 24 |
+
|
| 25 |
+
class queue_conn {
|
| 26 |
+
protected:
|
| 27 |
+
circ::cc_t connected_ = 0;
|
| 28 |
+
shm::handle elems_h_;
|
| 29 |
+
|
| 30 |
+
template <typename Elems>
|
| 31 |
+
Elems* open(char const * name) {
|
| 32 |
+
if (name == nullptr || name[0] == '\0') {
|
| 33 |
+
ipc::error("fail open waiter: name is empty!\n");
|
| 34 |
+
return nullptr;
|
| 35 |
+
}
|
| 36 |
+
if (!elems_h_.acquire(name, sizeof(Elems))) {
|
| 37 |
+
return nullptr;
|
| 38 |
+
}
|
| 39 |
+
auto elems = static_cast<Elems*>(elems_h_.get());
|
| 40 |
+
if (elems == nullptr) {
|
| 41 |
+
ipc::error("fail acquire elems: %s\n", name);
|
| 42 |
+
return nullptr;
|
| 43 |
+
}
|
| 44 |
+
elems->init();
|
| 45 |
+
return elems;
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
void close() {
|
| 49 |
+
elems_h_.release();
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
public:
|
| 53 |
+
queue_conn() = default;
|
| 54 |
+
queue_conn(const queue_conn&) = delete;
|
| 55 |
+
queue_conn& operator=(const queue_conn&) = delete;
|
| 56 |
+
|
| 57 |
+
bool connected() const noexcept {
|
| 58 |
+
return connected_ != 0;
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
circ::cc_t connected_id() const noexcept {
|
| 62 |
+
return connected_;
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
template <typename Elems>
|
| 66 |
+
auto connect(Elems* elems) noexcept
|
| 67 |
+
/*needs 'optional' here*/
|
| 68 |
+
-> std::tuple<bool, bool, decltype(std::declval<Elems>().cursor())> {
|
| 69 |
+
if (elems == nullptr) return {};
|
| 70 |
+
// if it's already connected, just return
|
| 71 |
+
if (connected()) return {connected(), false, 0};
|
| 72 |
+
connected_ = elems->connect_receiver();
|
| 73 |
+
return {connected(), true, elems->cursor()};
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
template <typename Elems>
|
| 77 |
+
bool disconnect(Elems* elems) noexcept {
|
| 78 |
+
if (elems == nullptr) return false;
|
| 79 |
+
// if it's already disconnected, just return false
|
| 80 |
+
if (!connected()) return false;
|
| 81 |
+
elems->disconnect_receiver(std::exchange(connected_, 0));
|
| 82 |
+
return true;
|
| 83 |
+
}
|
| 84 |
+
};
|
| 85 |
+
|
| 86 |
+
template <typename Elems>
|
| 87 |
+
class queue_base : public queue_conn {
|
| 88 |
+
using base_t = queue_conn;
|
| 89 |
+
|
| 90 |
+
public:
|
| 91 |
+
using elems_t = Elems;
|
| 92 |
+
using policy_t = typename elems_t::policy_t;
|
| 93 |
+
|
| 94 |
+
protected:
|
| 95 |
+
elems_t * elems_ = nullptr;
|
| 96 |
+
decltype(std::declval<elems_t>().cursor()) cursor_ = 0;
|
| 97 |
+
bool sender_flag_ = false;
|
| 98 |
+
|
| 99 |
+
public:
|
| 100 |
+
using base_t::base_t;
|
| 101 |
+
|
| 102 |
+
queue_base() = default;
|
| 103 |
+
|
| 104 |
+
explicit queue_base(char const * name)
|
| 105 |
+
: queue_base{} {
|
| 106 |
+
elems_ = open<elems_t>(name);
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
explicit queue_base(elems_t * elems) noexcept
|
| 110 |
+
: queue_base{} {
|
| 111 |
+
assert(elems != nullptr);
|
| 112 |
+
elems_ = elems;
|
| 113 |
+
}
|
| 114 |
+
|
| 115 |
+
/* not virtual */ ~queue_base() {
|
| 116 |
+
base_t::close();
|
| 117 |
+
}
|
| 118 |
+
|
| 119 |
+
elems_t * elems() noexcept { return elems_; }
|
| 120 |
+
elems_t const * elems() const noexcept { return elems_; }
|
| 121 |
+
|
| 122 |
+
bool ready_sending() noexcept {
|
| 123 |
+
if (elems_ == nullptr) return false;
|
| 124 |
+
return sender_flag_ || (sender_flag_ = elems_->connect_sender());
|
| 125 |
+
}
|
| 126 |
+
|
| 127 |
+
void shut_sending() noexcept {
|
| 128 |
+
if (elems_ == nullptr) return;
|
| 129 |
+
if (!sender_flag_) return;
|
| 130 |
+
elems_->disconnect_sender();
|
| 131 |
+
}
|
| 132 |
+
|
| 133 |
+
bool connect() noexcept {
|
| 134 |
+
auto tp = base_t::connect(elems_);
|
| 135 |
+
if (std::get<0>(tp) && std::get<1>(tp)) {
|
| 136 |
+
cursor_ = std::get<2>(tp);
|
| 137 |
+
return true;
|
| 138 |
+
}
|
| 139 |
+
return std::get<0>(tp);
|
| 140 |
+
}
|
| 141 |
+
|
| 142 |
+
bool disconnect() noexcept {
|
| 143 |
+
return base_t::disconnect(elems_);
|
| 144 |
+
}
|
| 145 |
+
|
| 146 |
+
std::size_t conn_count() const noexcept {
|
| 147 |
+
return (elems_ == nullptr) ? static_cast<std::size_t>(invalid_value) : elems_->conn_count();
|
| 148 |
+
}
|
| 149 |
+
|
| 150 |
+
bool valid() const noexcept {
|
| 151 |
+
return elems_ != nullptr;
|
| 152 |
+
}
|
| 153 |
+
|
| 154 |
+
bool empty() const noexcept {
|
| 155 |
+
return !valid() || (cursor_ == elems_->cursor());
|
| 156 |
+
}
|
| 157 |
+
|
| 158 |
+
template <typename T, typename F, typename... P>
|
| 159 |
+
bool push(F&& prep, P&&... params) {
|
| 160 |
+
if (elems_ == nullptr) return false;
|
| 161 |
+
return elems_->push(this, [&](void* p) {
|
| 162 |
+
if (prep(p)) ::new (p) T(std::forward<P>(params)...);
|
| 163 |
+
});
|
| 164 |
+
}
|
| 165 |
+
|
| 166 |
+
template <typename T, typename F, typename... P>
|
| 167 |
+
bool force_push(F&& prep, P&&... params) {
|
| 168 |
+
if (elems_ == nullptr) return false;
|
| 169 |
+
return elems_->force_push(this, [&](void* p) {
|
| 170 |
+
if (prep(p)) ::new (p) T(std::forward<P>(params)...);
|
| 171 |
+
});
|
| 172 |
+
}
|
| 173 |
+
|
| 174 |
+
template <typename T, typename F>
|
| 175 |
+
bool pop(T& item, F&& out) {
|
| 176 |
+
if (elems_ == nullptr) {
|
| 177 |
+
return false;
|
| 178 |
+
}
|
| 179 |
+
return elems_->pop(this, &(this->cursor_), [&item](void* p) {
|
| 180 |
+
::new (&item) T(std::move(*static_cast<T*>(p)));
|
| 181 |
+
}, std::forward<F>(out));
|
| 182 |
+
}
|
| 183 |
+
};
|
| 184 |
+
|
| 185 |
+
} // namespace detail
|
| 186 |
+
|
| 187 |
+
template <typename T, typename Policy>
|
| 188 |
+
class queue final : public detail::queue_base<typename Policy::template elems_t<sizeof(T), alignof(T)>> {
|
| 189 |
+
using base_t = detail::queue_base<typename Policy::template elems_t<sizeof(T), alignof(T)>>;
|
| 190 |
+
|
| 191 |
+
public:
|
| 192 |
+
using value_t = T;
|
| 193 |
+
|
| 194 |
+
using base_t::base_t;
|
| 195 |
+
|
| 196 |
+
template <typename... P>
|
| 197 |
+
bool push(P&&... params) {
|
| 198 |
+
return base_t::template push<T>(std::forward<P>(params)...);
|
| 199 |
+
}
|
| 200 |
+
|
| 201 |
+
template <typename... P>
|
| 202 |
+
bool force_push(P&&... params) {
|
| 203 |
+
return base_t::template force_push<T>(std::forward<P>(params)...);
|
| 204 |
+
}
|
| 205 |
+
|
| 206 |
+
bool pop(T& item) {
|
| 207 |
+
return base_t::pop(item, [](bool) {});
|
| 208 |
+
}
|
| 209 |
+
|
| 210 |
+
template <typename F>
|
| 211 |
+
bool pop(T& item, F&& out) {
|
| 212 |
+
return base_t::pop(item, std::forward<F>(out));
|
| 213 |
+
}
|
| 214 |
+
};
|
| 215 |
+
|
| 216 |
+
} // namespace ipc
|
crazy_functions/test_project/cpp/cppipc/shm.cpp
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
#include <string>
|
| 3 |
+
#include <utility>
|
| 4 |
+
|
| 5 |
+
#include "libipc/shm.h"
|
| 6 |
+
|
| 7 |
+
#include "libipc/utility/pimpl.h"
|
| 8 |
+
#include "libipc/memory/resource.h"
|
| 9 |
+
|
| 10 |
+
namespace ipc {
|
| 11 |
+
namespace shm {
|
| 12 |
+
|
| 13 |
+
class handle::handle_ : public pimpl<handle_> {
|
| 14 |
+
public:
|
| 15 |
+
shm::id_t id_ = nullptr;
|
| 16 |
+
void* m_ = nullptr;
|
| 17 |
+
|
| 18 |
+
ipc::string n_;
|
| 19 |
+
std::size_t s_ = 0;
|
| 20 |
+
};
|
| 21 |
+
|
| 22 |
+
handle::handle()
|
| 23 |
+
: p_(p_->make()) {
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
handle::handle(char const * name, std::size_t size, unsigned mode)
|
| 27 |
+
: handle() {
|
| 28 |
+
acquire(name, size, mode);
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
handle::handle(handle&& rhs)
|
| 32 |
+
: handle() {
|
| 33 |
+
swap(rhs);
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
handle::~handle() {
|
| 37 |
+
release();
|
| 38 |
+
p_->clear();
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
void handle::swap(handle& rhs) {
|
| 42 |
+
std::swap(p_, rhs.p_);
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
handle& handle::operator=(handle rhs) {
|
| 46 |
+
swap(rhs);
|
| 47 |
+
return *this;
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
bool handle::valid() const noexcept {
|
| 51 |
+
return impl(p_)->m_ != nullptr;
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
std::size_t handle::size() const noexcept {
|
| 55 |
+
return impl(p_)->s_;
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
char const * handle::name() const noexcept {
|
| 59 |
+
return impl(p_)->n_.c_str();
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
std::int32_t handle::ref() const noexcept {
|
| 63 |
+
return shm::get_ref(impl(p_)->id_);
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
void handle::sub_ref() noexcept {
|
| 67 |
+
shm::sub_ref(impl(p_)->id_);
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
bool handle::acquire(char const * name, std::size_t size, unsigned mode) {
|
| 71 |
+
release();
|
| 72 |
+
impl(p_)->id_ = shm::acquire((impl(p_)->n_ = name).c_str(), size, mode);
|
| 73 |
+
impl(p_)->m_ = shm::get_mem(impl(p_)->id_, &(impl(p_)->s_));
|
| 74 |
+
return valid();
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
std::int32_t handle::release() {
|
| 78 |
+
if (impl(p_)->id_ == nullptr) return -1;
|
| 79 |
+
return shm::release(detach());
|
| 80 |
+
}
|
| 81 |
+
|
| 82 |
+
void* handle::get() const {
|
| 83 |
+
return impl(p_)->m_;
|
| 84 |
+
}
|
| 85 |
+
|
| 86 |
+
void handle::attach(id_t id) {
|
| 87 |
+
if (id == nullptr) return;
|
| 88 |
+
release();
|
| 89 |
+
impl(p_)->id_ = id;
|
| 90 |
+
impl(p_)->m_ = shm::get_mem(impl(p_)->id_, &(impl(p_)->s_));
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
+
id_t handle::detach() {
|
| 94 |
+
auto old = impl(p_)->id_;
|
| 95 |
+
impl(p_)->id_ = nullptr;
|
| 96 |
+
impl(p_)->m_ = nullptr;
|
| 97 |
+
impl(p_)->s_ = 0;
|
| 98 |
+
impl(p_)->n_.clear();
|
| 99 |
+
return old;
|
| 100 |
+
}
|
| 101 |
+
|
| 102 |
+
} // namespace shm
|
| 103 |
+
} // namespace ipc
|
crazy_functions/test_project/cpp/cppipc/waiter.h
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
#include <utility>
|
| 4 |
+
#include <string>
|
| 5 |
+
#include <mutex>
|
| 6 |
+
#include <atomic>
|
| 7 |
+
|
| 8 |
+
#include "libipc/def.h"
|
| 9 |
+
#include "libipc/mutex.h"
|
| 10 |
+
#include "libipc/condition.h"
|
| 11 |
+
#include "libipc/platform/detail.h"
|
| 12 |
+
|
| 13 |
+
namespace ipc {
|
| 14 |
+
namespace detail {
|
| 15 |
+
|
| 16 |
+
class waiter {
|
| 17 |
+
ipc::sync::condition cond_;
|
| 18 |
+
ipc::sync::mutex lock_;
|
| 19 |
+
std::atomic<bool> quit_ {false};
|
| 20 |
+
|
| 21 |
+
public:
|
| 22 |
+
static void init();
|
| 23 |
+
|
| 24 |
+
waiter() = default;
|
| 25 |
+
waiter(char const *name) {
|
| 26 |
+
open(name);
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
~waiter() {
|
| 30 |
+
close();
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
bool valid() const noexcept {
|
| 34 |
+
return cond_.valid() && lock_.valid();
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
bool open(char const *name) noexcept {
|
| 38 |
+
quit_.store(false, std::memory_order_relaxed);
|
| 39 |
+
if (!cond_.open((std::string{"_waiter_cond_"} + name).c_str())) {
|
| 40 |
+
return false;
|
| 41 |
+
}
|
| 42 |
+
if (!lock_.open((std::string{"_waiter_lock_"} + name).c_str())) {
|
| 43 |
+
cond_.close();
|
| 44 |
+
return false;
|
| 45 |
+
}
|
| 46 |
+
return valid();
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
void close() noexcept {
|
| 50 |
+
cond_.close();
|
| 51 |
+
lock_.close();
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
template <typename F>
|
| 55 |
+
bool wait_if(F &&pred, std::uint64_t tm = ipc::invalid_value) noexcept {
|
| 56 |
+
IPC_UNUSED_ std::lock_guard<ipc::sync::mutex> guard {lock_};
|
| 57 |
+
while ([this, &pred] {
|
| 58 |
+
return !quit_.load(std::memory_order_relaxed)
|
| 59 |
+
&& std::forward<F>(pred)();
|
| 60 |
+
}()) {
|
| 61 |
+
if (!cond_.wait(lock_, tm)) return false;
|
| 62 |
+
}
|
| 63 |
+
return true;
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
bool notify() noexcept {
|
| 67 |
+
std::lock_guard<ipc::sync::mutex>{lock_}; // barrier
|
| 68 |
+
return cond_.notify(lock_);
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
bool broadcast() noexcept {
|
| 72 |
+
std::lock_guard<ipc::sync::mutex>{lock_}; // barrier
|
| 73 |
+
return cond_.broadcast(lock_);
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
bool quit_waiting() {
|
| 77 |
+
quit_.store(true, std::memory_order_release);
|
| 78 |
+
return broadcast();
|
| 79 |
+
}
|
| 80 |
+
};
|
| 81 |
+
|
| 82 |
+
} // namespace detail
|
| 83 |
+
} // namespace ipc
|
crazy_functions/test_project/{Cpp → cpp}/libJPG/JpegLibrary.tps
RENAMED
|
File without changes
|
crazy_functions/test_project/{Cpp → cpp}/libJPG/UElibJPG.Build.cs
RENAMED
|
File without changes
|
crazy_functions/test_project/{Cpp → cpp}/libJPG/jpeg-compressor.tps
RENAMED
|
File without changes
|
crazy_functions/test_project/{Cpp → cpp}/libJPG/jpgd.cpp
RENAMED
|
File without changes
|
crazy_functions/test_project/{Cpp → cpp}/libJPG/jpgd.h
RENAMED
|
File without changes
|
crazy_functions/test_project/{Cpp → cpp}/libJPG/jpge.cpp
RENAMED
|
File without changes
|
crazy_functions/test_project/{Cpp → cpp}/libJPG/jpge.h
RENAMED
|
File without changes
|
crazy_functions/test_project/{Cpp → cpp}/libJPG/来源
RENAMED
|
File without changes
|
crazy_functions/test_project/其他测试
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"In practice, we found that a high-entropy initial state is more likely to increase the speed of training.
|
| 2 |
+
The entropy is calculated by:
|
| 3 |
+
$$H=-\sum_{k= 1}^{n_k} p(k) \cdot \log p(k), p(k)=\frac{|A_k|}{|\mathcal{A}|}$$
|
| 4 |
+
where $H$ is the entropy, $|A_k|$ is the number of agent nodes in $k$-th cluster, $|\mathcal{A}|$ is the total number of agents.
|
| 5 |
+
To ensure the Cooperation Graph initialization has higher entropy,
|
| 6 |
+
we will randomly generate multiple initial states,
|
| 7 |
+
rank by their entropy and then pick the one with maximum $H$."
|
| 8 |
+
|
| 9 |
+
|
crazy_functions/生成函数注释.py
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from predict import predict_no_ui
|
| 2 |
+
from toolbox import CatchException, report_execption, write_results_to_file
|
| 3 |
+
fast_debug = False
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
def 生成函数注释(file_manifest, project_folder, top_p, temperature, chatbot, history, systemPromptTxt):
|
| 7 |
+
import time, glob, os
|
| 8 |
+
print('begin analysis on:', file_manifest)
|
| 9 |
+
for index, fp in enumerate(file_manifest):
|
| 10 |
+
with open(fp, 'r', encoding='utf-8') as f:
|
| 11 |
+
file_content = f.read()
|
| 12 |
+
|
| 13 |
+
i_say = f'请对下面的程序文件做一个概述,并对文件中的所有函数生成注释,使用markdown表格输出结果,文件名是{os.path.relpath(fp, project_folder)},文件内容是 ```{file_content}```'
|
| 14 |
+
i_say_show_user = f'[{index}/{len(file_manifest)}] 请对下面的程序文件做一个概述,并对文件中的所有函数生成注释: {os.path.abspath(fp)}'
|
| 15 |
+
chatbot.append((i_say_show_user, "[Local Message] waiting gpt response."))
|
| 16 |
+
print('[1] yield chatbot, history')
|
| 17 |
+
yield chatbot, history, '正常'
|
| 18 |
+
|
| 19 |
+
if not fast_debug:
|
| 20 |
+
msg = '正常'
|
| 21 |
+
# ** gpt request **
|
| 22 |
+
while True:
|
| 23 |
+
try:
|
| 24 |
+
gpt_say = predict_no_ui(inputs=i_say, top_p=top_p, temperature=temperature)
|
| 25 |
+
break
|
| 26 |
+
except ConnectionAbortedError as e:
|
| 27 |
+
i_say = i_say[:len(i_say)//2]
|
| 28 |
+
msg = '文件太长,进行了拦腰截断'
|
| 29 |
+
|
| 30 |
+
print('[2] end gpt req')
|
| 31 |
+
chatbot[-1] = (i_say_show_user, gpt_say)
|
| 32 |
+
history.append(i_say_show_user); history.append(gpt_say)
|
| 33 |
+
print('[3] yield chatbot, history')
|
| 34 |
+
yield chatbot, history, msg
|
| 35 |
+
print('[4] next')
|
| 36 |
+
if not fast_debug: time.sleep(2)
|
| 37 |
+
|
| 38 |
+
if not fast_debug:
|
| 39 |
+
res = write_results_to_file(history)
|
| 40 |
+
chatbot.append(("完成了吗?", res))
|
| 41 |
+
yield chatbot, history, msg
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
@CatchException
|
| 46 |
+
def 批量生成函数注释(txt, top_p, temperature, chatbot, history, systemPromptTxt, WEB_PORT):
|
| 47 |
+
history = [] # 清空历史,以免输入溢出
|
| 48 |
+
import glob, os
|
| 49 |
+
if os.path.exists(txt):
|
| 50 |
+
project_folder = txt
|
| 51 |
+
else:
|
| 52 |
+
if txt == "": txt = '空空如也的输入栏'
|
| 53 |
+
report_execption(chatbot, history, a = f"解析项目: {txt}", b = f"找不到本地项目或无权访问: {txt}")
|
| 54 |
+
yield chatbot, history, '正常'
|
| 55 |
+
return
|
| 56 |
+
file_manifest = [f for f in glob.glob(f'{project_folder}/**/*.py', recursive=True)] + \
|
| 57 |
+
[f for f in glob.glob(f'{project_folder}/**/*.cpp', recursive=True)]
|
| 58 |
+
|
| 59 |
+
if len(file_manifest) == 0:
|
| 60 |
+
report_execption(chatbot, history, a = f"解析项目: {txt}", b = f"找不到任何.tex文件: {txt}")
|
| 61 |
+
yield chatbot, history, '正常'
|
| 62 |
+
return
|
| 63 |
+
yield from 生成函数注释(file_manifest, project_folder, top_p, temperature, chatbot, history, systemPromptTxt)
|
functional_crazy.py
CHANGED
|
@@ -157,9 +157,10 @@ def 解析一个C项目的头文件(txt, top_p, temperature, chatbot, history, s
|
|
| 157 |
|
| 158 |
def get_crazy_functionals():
|
| 159 |
from crazy_functions.读文章写摘要 import 读文章写摘要
|
|
|
|
|
|
|
| 160 |
return {
|
| 161 |
"[实验功能] 请解析并解构此项目本身": {
|
| 162 |
-
"Color": "stop", # 按钮颜色
|
| 163 |
"Function": 解析项目本身
|
| 164 |
},
|
| 165 |
"[实验功能] 解析整个Python项目(input输入项目根路径)": {
|
|
@@ -174,6 +175,10 @@ def get_crazy_functionals():
|
|
| 174 |
"Color": "stop", # 按钮颜色
|
| 175 |
"Function": 读文章写摘要
|
| 176 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
| 177 |
"[实验功能] 高阶功能模板函数": {
|
| 178 |
"Color": "stop", # 按钮颜色
|
| 179 |
"Function": 高阶功能模板函数
|
|
|
|
| 157 |
|
| 158 |
def get_crazy_functionals():
|
| 159 |
from crazy_functions.读文章写摘要 import 读文章写摘要
|
| 160 |
+
from crazy_functions.生成函数注释 import 批量生成函数注释
|
| 161 |
+
|
| 162 |
return {
|
| 163 |
"[实验功能] 请解析并解构此项目本身": {
|
|
|
|
| 164 |
"Function": 解析项目本身
|
| 165 |
},
|
| 166 |
"[实验功能] 解析整个Python项目(input输入项目根路径)": {
|
|
|
|
| 175 |
"Color": "stop", # 按钮颜色
|
| 176 |
"Function": 读文章写摘要
|
| 177 |
},
|
| 178 |
+
"[实验功能] 批量生成函数注释(input输入项目根路径)": {
|
| 179 |
+
"Color": "stop", # 按钮颜色
|
| 180 |
+
"Function": 批量生成函数注释
|
| 181 |
+
},
|
| 182 |
"[实验功能] 高阶功能模板函数": {
|
| 183 |
"Color": "stop", # 按钮颜色
|
| 184 |
"Function": 高阶功能模板函数
|
toolbox.py
CHANGED
|
@@ -13,7 +13,7 @@ def write_results_to_file(history, file_name=None):
|
|
| 13 |
if i%2==0: f.write('## ')
|
| 14 |
f.write(content)
|
| 15 |
f.write('\n\n')
|
| 16 |
-
res ='以上材料已经被写入'
|
| 17 |
print(res)
|
| 18 |
return res
|
| 19 |
|
|
|
|
| 13 |
if i%2==0: f.write('## ')
|
| 14 |
f.write(content)
|
| 15 |
f.write('\n\n')
|
| 16 |
+
res = '以上材料已经被写入' + os.path.abspath(f'./gpt_log/{file_name}')
|
| 17 |
print(res)
|
| 18 |
return res
|
| 19 |
|