forked from boostorg/mqtt5
remove development files
Summary: related to T13118 Reviewers: ivica Reviewed By: ivica Subscribers: miljen, iljazovic Differential Revision: https://repo.mireo.local/D26619
This commit is contained in:
1 parent
73620e5653
commit
cda3bc8ee1
11 files changed
-1395
No files matched your search
@@ -1,155 +0,0 @@
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <boost/asio/prepend.hpp>
|
||||
#include <boost/asio/steady_timer.hpp>
|
||||
#include <boost/asio/associated_executor.hpp>
|
||||
#include <boost/asio/bind_executor.hpp>
|
||||
#include <boost/asio/cancellation_signal.hpp>
|
||||
#include <boost/asio/cancellation_state.hpp>
|
||||
#include <boost/asio/bind_cancellation_slot.hpp>
|
||||
#include <boost/asio/dispatch.hpp>
|
||||
#include <boost/asio/thread_pool.hpp>
|
||||
|
||||
namespace asio = boost::asio;
|
||||
|
||||
template <typename Handler>
|
||||
decltype(auto) tracking_executor(Handler&& handler) {
|
||||
return asio::prefer(
|
||||
asio::get_associated_executor(std::forward<Handler>(handler)),
|
||||
asio::execution::outstanding_work.tracked
|
||||
);
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
using tracking_type = std::decay_t<
|
||||
decltype(tracking_executor(std::declval<Handler>()))
|
||||
>;
|
||||
|
||||
template <typename Handler>
|
||||
class async_op {
|
||||
struct on_timer {};
|
||||
|
||||
std::decay_t<Handler> _handler;
|
||||
tracking_type<Handler> _handler_ex;
|
||||
asio::cancellation_state _cancel_state;
|
||||
|
||||
// must be unique_ptr because move(timer) cancels previous op
|
||||
std::unique_ptr<asio::steady_timer> _timer;
|
||||
public:
|
||||
template <typename Executor>
|
||||
async_op(const Executor& ex, Handler&& handler, const asio::cancellation_slot& cs) :
|
||||
_handler(std::forward<Handler>(handler)),
|
||||
_handler_ex(tracking_executor(_handler)),
|
||||
_cancel_state(cs),
|
||||
_timer(std::make_unique<asio::steady_timer>(ex))
|
||||
{}
|
||||
|
||||
async_op(async_op&&) noexcept = default;
|
||||
async_op& operator=(async_op&&) noexcept = default;
|
||||
|
||||
using executor_type = asio::steady_timer::executor_type;
|
||||
executor_type get_executor() const noexcept {
|
||||
return _timer->get_executor();
|
||||
}
|
||||
|
||||
using allocator_type = asio::associated_allocator_t<Handler>;
|
||||
allocator_type get_allocator() const noexcept {
|
||||
return asio::get_associated_allocator(_handler);
|
||||
}
|
||||
|
||||
using cancellation_slot_type = asio::cancellation_slot;
|
||||
asio::cancellation_slot get_cancellation_slot() const noexcept {
|
||||
return _cancel_state.slot();
|
||||
}
|
||||
|
||||
void perform() {
|
||||
_timer->expires_from_now(std::chrono::seconds(5));
|
||||
_timer->async_wait(asio::prepend(std::move(*this), on_timer {}));
|
||||
}
|
||||
|
||||
void operator()(on_timer, boost::system::error_code ec) {
|
||||
if (ec == asio::error::operation_aborted) {
|
||||
fmt::print(stderr, "Aborted {}\n", ec.message());
|
||||
return;
|
||||
}
|
||||
_cancel_state.slot().clear();
|
||||
|
||||
fmt::print(stderr, "Dispatching with error {}\n", ec.message());
|
||||
asio::dispatch(_handler_ex, [h = std::move(_handler), ec]() mutable {
|
||||
std::move(h)(ec);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
class owner {
|
||||
asio::cancellation_signal _cancel_signal;
|
||||
public:
|
||||
void cancel() {
|
||||
_cancel_signal.emit(asio::cancellation_type::terminal);
|
||||
_cancel_signal.slot().clear();
|
||||
}
|
||||
~owner() {
|
||||
cancel();
|
||||
}
|
||||
|
||||
template <typename CompletionToken>
|
||||
decltype(auto) async_perform(asio::io_context& ioc, CompletionToken&& token) {
|
||||
auto initiation = [this, &ioc](auto handler) {
|
||||
auto slot = asio::get_associated_cancellation_slot(handler);
|
||||
async_op<decltype(handler)>(
|
||||
ioc.get_executor(), std::move(handler),
|
||||
slot.is_connected() ? slot : _cancel_signal.slot()
|
||||
).perform();
|
||||
};
|
||||
|
||||
return asio::async_initiate<CompletionToken, void (boost::system::error_code)>(
|
||||
std::move(initiation), token
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
void cancel_test(asio::io_context& ioc) {
|
||||
asio::cancellation_signal cancel_signal;
|
||||
|
||||
asio::thread_pool thp;
|
||||
|
||||
{
|
||||
owner b;
|
||||
b.async_perform(ioc,
|
||||
asio::bind_cancellation_slot(
|
||||
cancel_signal.slot(),
|
||||
asio::bind_executor(thp.get_executor(),
|
||||
[](boost::system::error_code ec) {
|
||||
fmt::print(stderr, "Finished with error {}\n", ec.message());
|
||||
}
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
{
|
||||
asio::steady_timer timer3(ioc);
|
||||
timer3.expires_from_now(std::chrono::seconds(3));
|
||||
timer3.async_wait(
|
||||
asio::bind_cancellation_slot(
|
||||
cancel_signal.slot(),
|
||||
[&] (boost::system::error_code) {
|
||||
// cancel_signal.emit(asio::cancellation_type::terminal);
|
||||
// b.cancel();
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
*/
|
||||
asio::steady_timer timer2(ioc);
|
||||
timer2.expires_from_now(std::chrono::seconds(1));
|
||||
timer2.async_wait([&] (boost::system::error_code) {
|
||||
// cancel_signal.emit(asio::cancellation_type::terminal);
|
||||
// b.cancel();
|
||||
});
|
||||
|
||||
ioc.run();
|
||||
thp.join();
|
||||
}
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
#include <fmt/format.h>
|
||||
#include <boost/asio/recycling_allocator.hpp>
|
||||
|
||||
#include "../../alloc/memory.h"
|
||||
#include "../../alloc/string.h"
|
||||
#include "../../alloc/vector.h"
|
||||
|
||||
namespace asio = boost::asio;
|
||||
|
||||
struct bx {
|
||||
pma::string s1, s2;
|
||||
|
||||
bx(std::string v1, std::string v2, const pma::alloc<size_t>& alloc) :
|
||||
s1(v1.begin(), v1.end(), alloc),
|
||||
s2(v2.begin(), v2.end(), alloc)
|
||||
{}
|
||||
};
|
||||
|
||||
void test_memory() {
|
||||
asio::recycling_allocator<char> base_alloc;
|
||||
pma::resource_adaptor<asio::recycling_allocator<char>> mem_res { base_alloc };
|
||||
auto alloc = pma::alloc<char>(&mem_res);
|
||||
|
||||
pma::string s1 { "abcdefgrthoasofjasfasf", alloc };
|
||||
pma::string s2 { alloc };
|
||||
s2 = s1;
|
||||
|
||||
//TODO: the commented lines do not compile on Windows
|
||||
//pma::vector<char> v1 { { 'a', 'b'}, alloc };
|
||||
pma::vector<char> v2 { alloc };
|
||||
//v2 = std::move(v1);
|
||||
//pma::vector<char> v3 = v2;
|
||||
//pma::vector<char> v4 = std::move(v3);
|
||||
//v1.swap(v2);
|
||||
|
||||
bx vbx { "ABCD", "EFGH", alloc };
|
||||
|
||||
fmt::print(stderr, "String = {}, is equal: {}\n", s2,
|
||||
s1.get_allocator() == vbx.s2.get_allocator()
|
||||
);
|
||||
|
||||
//fmt::print(stderr, "Vector allocators are equal: {}\n",
|
||||
// v1.get_allocator() == v2.get_allocator()
|
||||
//);
|
||||
|
||||
std::allocator_traits<decltype(alloc)>::rebind_alloc<std::string> char_alloc =
|
||||
alloc;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,199 +0,0 @@
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
#include <boost/asio/any_io_executor.hpp>
|
||||
#include <boost/asio/awaitable.hpp>
|
||||
#include <boost/asio/detached.hpp>
|
||||
#include <boost/asio/co_spawn.hpp>
|
||||
#include <boost/asio/use_awaitable.hpp>
|
||||
#include <async/async.h>
|
||||
|
||||
#include <mqtt-client/detail/internal_types.hpp>
|
||||
#include <mqtt-client/codecs/message_encoders.hpp>
|
||||
#include <mqtt-client/codecs/message_decoders.hpp>
|
||||
|
||||
#include <mqtt-client/impl/assemble_op.hpp>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
namespace asio = boost::asio;
|
||||
|
||||
namespace async_mqtt {
|
||||
|
||||
using byte_iter = detail::byte_iter;
|
||||
|
||||
class fake_stream {
|
||||
asio::any_io_executor _ex;
|
||||
std::string _data;
|
||||
int _chunk_no = -1;
|
||||
|
||||
std::string _read_buff;
|
||||
detail::data_span _data_span;
|
||||
|
||||
public:
|
||||
fake_stream(asio::any_io_executor ex) : _ex(std::move(ex)) {
|
||||
prepare_data();
|
||||
}
|
||||
|
||||
using executor_type = asio::any_io_executor;
|
||||
const executor_type& get_executor() const noexcept { return _ex; }
|
||||
|
||||
template <
|
||||
typename BufferType,
|
||||
typename CompletionToken
|
||||
>
|
||||
auto async_read_some(
|
||||
const BufferType& buffer, detail::duration wait_for,
|
||||
CompletionToken&& token
|
||||
);
|
||||
|
||||
template <typename Stream, typename CompletionToken>
|
||||
decltype(auto) async_assemble(
|
||||
Stream& stream, detail::duration wait_for, CompletionToken&& token
|
||||
);
|
||||
|
||||
private:
|
||||
void prepare_data();
|
||||
std::string_view next_frame();
|
||||
};
|
||||
|
||||
template <
|
||||
typename BufferType,
|
||||
typename CompletionToken
|
||||
>
|
||||
auto fake_stream::async_read_some(
|
||||
const BufferType& buffer, detail::duration wait_for,
|
||||
CompletionToken&& token
|
||||
) {
|
||||
auto read_op = [this] (auto handler, const BufferType& buffer) {
|
||||
auto data = next_frame();
|
||||
size_t bytes_read = data.size();
|
||||
std::copy(data.begin(), data.end(), static_cast<uint8_t*>(buffer.data()));
|
||||
|
||||
asio::post(get_executor(), [h = std::move(handler), bytes_read] () mutable {
|
||||
h(error_code{}, bytes_read);
|
||||
});
|
||||
};
|
||||
|
||||
return asio::async_initiate<CompletionToken, void (error_code, size_t)>(
|
||||
std::move(read_op), token, buffer
|
||||
);
|
||||
}
|
||||
|
||||
template <typename Stream, typename CompletionToken>
|
||||
decltype(auto) fake_stream::async_assemble(
|
||||
Stream& stream, detail::duration wait_for, CompletionToken&& token
|
||||
) {
|
||||
auto initiation = [this] (auto handler, Stream& stream, detail::duration wait_for) mutable {
|
||||
detail::assemble_op (
|
||||
stream, std::move(handler),
|
||||
_read_buff, _data_span
|
||||
).perform(wait_for, asio::transfer_at_least(0));
|
||||
};
|
||||
|
||||
return asio::async_initiate<
|
||||
CompletionToken, void (error_code, uint8_t, byte_iter, byte_iter)
|
||||
> (
|
||||
std::move(initiation), token, std::ref(stream), wait_for
|
||||
);
|
||||
}
|
||||
|
||||
void fake_stream::prepare_data() {
|
||||
connack_props cap;
|
||||
cap[prop::session_expiry_interval] = 60;
|
||||
cap[prop::maximum_packet_size] = 16384;
|
||||
cap[prop::wildcard_subscription_available] = true;
|
||||
_data = encoders::encode_connack(true, 0x8A, cap);
|
||||
|
||||
puback_props pap;
|
||||
pap[prop::user_property].emplace_back("PUBACK user property");
|
||||
_data += encoders::encode_puback(42, 28, pap);
|
||||
}
|
||||
|
||||
std::string_view fake_stream::next_frame() {
|
||||
++_chunk_no;
|
||||
if (_chunk_no == 0)
|
||||
return { _data.begin(), _data.begin() + 2 };
|
||||
if (_chunk_no == 1)
|
||||
return { _data.begin() + 2, _data.begin() + 13 };
|
||||
if (_chunk_no == 2)
|
||||
return { _data.begin() + 13, _data.begin() + 23 };
|
||||
if (_chunk_no == 3)
|
||||
return { _data.begin() + 23, _data.begin() + 35 };
|
||||
if (_chunk_no == 4)
|
||||
return { _data.begin() + 35, _data.end() };
|
||||
return { _data.end(), _data.end() };
|
||||
}
|
||||
|
||||
template <typename Stream, typename CompletionToken>
|
||||
decltype(auto) async_assemble(
|
||||
Stream& stream, detail::duration wait_for,
|
||||
CompletionToken&& token
|
||||
) {
|
||||
return stream.async_assemble(
|
||||
stream, wait_for, std::forward<CompletionToken>(token)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
void test_single(asio::io_context& ioc) {
|
||||
using namespace std::chrono;
|
||||
|
||||
fake_stream s(asio::make_strand(ioc));
|
||||
|
||||
auto on_message = [] (
|
||||
error_code ec, uint8_t control_code, byte_iter first, byte_iter last
|
||||
) {
|
||||
fmt::print(stderr, "Error code: {}\n", ec.message());
|
||||
if (ec) return;
|
||||
size_t remain_length = std::distance(first, last);
|
||||
auto rv = decoders::decode_connack(control_code, remain_length, first);
|
||||
const auto& [session_present, reason_code, cap] = *rv;
|
||||
fmt::print(stderr, "Got CONNACK message, reason_code {}, session {}\n", reason_code, session_present);
|
||||
fmt::print(stderr, "session_expiry_interval: {}\n", *cap[prop::session_expiry_interval]);
|
||||
fmt::print(stderr, "maximum_packet_size: {}\n", *cap[prop::maximum_packet_size]);
|
||||
fmt::print(stderr, "wildcard_subscription_available: {}\n", *cap[prop::wildcard_subscription_available]);
|
||||
};
|
||||
|
||||
async_assemble(s, seconds(1), std::move(on_message));
|
||||
|
||||
ioc.run();
|
||||
ioc.restart();
|
||||
}
|
||||
|
||||
asio::awaitable<void> test_multiple_coro(asio::io_context& ioc) {
|
||||
using namespace std::chrono;
|
||||
|
||||
fake_stream s(asio::make_strand(ioc));
|
||||
|
||||
auto [ec1, cc1, first1, last1] = co_await async_assemble(
|
||||
s, seconds(1), asio::use_nothrow_awaitable
|
||||
);
|
||||
size_t remain_length1 = std::distance(first1, last1);
|
||||
auto rv1 = decoders::decode_connack(cc1, remain_length1, first1);
|
||||
if (rv1)
|
||||
fmt::print(stderr, "CONNACK correctly decoded\n");
|
||||
|
||||
auto [ec2, cc2, first2, last2] = co_await async_assemble(
|
||||
s, seconds(1), asio::use_nothrow_awaitable
|
||||
);
|
||||
size_t remain_length2 = std::distance(first2, last2);
|
||||
auto rv2 = decoders::decode_puback(cc2, remain_length2, first2);
|
||||
|
||||
if (rv2)
|
||||
fmt::print(stderr, "PUBACK correctly decoded\n");
|
||||
}
|
||||
|
||||
void test_multiple(asio::io_context& ioc) {
|
||||
co_spawn(ioc, test_multiple_coro(ioc), asio::detached);
|
||||
ioc.run();
|
||||
ioc.restart();
|
||||
}
|
||||
|
||||
} // end namespace async_mqtt
|
||||
|
||||
void test_assembling(asio::io_context& ioc) {
|
||||
using namespace std::chrono;
|
||||
|
||||
async_mqtt::test_single(ioc);
|
||||
async_mqtt::test_multiple(ioc);
|
||||
}
|
||||
@@ -1,237 +0,0 @@
|
||||
// #include <async/run_loop.h>
|
||||
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/co_spawn.hpp>
|
||||
#include <boost/asio/detached.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
#include <boost/asio/thread_pool.hpp>
|
||||
#include <boost/asio/bind_cancellation_slot.hpp>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
|
||||
#include <mqtt-client/detail/async_mutex.hpp>
|
||||
#include <async/mutex.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#define ANKERL_NANOBENCH_IMPLEMENT
|
||||
#include <nanobench/nanobench.h>
|
||||
|
||||
constexpr size_t nthreads = 4;
|
||||
constexpr size_t per_job_count = 10'000 / nthreads;
|
||||
|
||||
using namespace async_mqtt5::detail;
|
||||
|
||||
void with_async_mutex(async_mutex& mutex, std::size_t* count) {
|
||||
for (int c = 0; c < per_job_count; ++c) {
|
||||
mutex.lock([&mutex, count](error_code) {
|
||||
++(*count);
|
||||
mutex.unlock();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void test_with_async_mutex(asio::any_io_executor e, async_mutex& mutex, size_t* count) {
|
||||
asio::post(e, [&mutex, count]() {
|
||||
with_async_mutex(mutex, count);
|
||||
});
|
||||
}
|
||||
|
||||
void with_old_async_mutex(async::mutex& mutex, std::size_t* count) {
|
||||
for (int c = 0; c < per_job_count; ++c) {
|
||||
mutex.lock([&mutex, count]() {
|
||||
++(*count);
|
||||
mutex.unlock();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void test_with_old_async_mutex(asio::any_io_executor e, async::mutex& mutex, size_t* count) {
|
||||
asio::post(e, [&mutex, count]() {
|
||||
with_old_async_mutex(mutex, count);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
struct std_mutex : public std::mutex {
|
||||
std_mutex(asio::any_io_executor) : std::mutex() { }
|
||||
};
|
||||
|
||||
void with_mutex(std_mutex& mutex, size_t* count) {
|
||||
for (int c = 0; c < per_job_count; ++c) {
|
||||
mutex.lock();
|
||||
++(*count);
|
||||
mutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void test_with_mutex(asio::any_io_executor e, std_mutex& mutex, size_t* count) {
|
||||
asio::post(e, [&mutex, count]() {
|
||||
with_mutex(mutex, count);
|
||||
});
|
||||
}
|
||||
|
||||
template <class Mutex, class Test>
|
||||
void test_with(Test func) {
|
||||
asio::thread_pool pool(nthreads);
|
||||
auto ex = pool.get_executor();
|
||||
auto count = std::make_unique<size_t>(0);
|
||||
Mutex mutex { ex };
|
||||
{
|
||||
for (auto i = 0; i < nthreads; ++i) {
|
||||
func(ex, mutex, count.get());
|
||||
}
|
||||
}
|
||||
pool.wait();
|
||||
if (*count != nthreads * per_job_count)
|
||||
throw "greska!";
|
||||
}
|
||||
|
||||
void test_cancellation() {
|
||||
|
||||
asio::thread_pool tp;
|
||||
asio::cancellation_signal cancel_signal;
|
||||
|
||||
async_mutex mutex(tp.get_executor());
|
||||
asio::steady_timer timer(tp);
|
||||
|
||||
auto op = [&](error_code ec) {
|
||||
if (ec == asio::error::operation_aborted) {
|
||||
mutex.unlock();
|
||||
return;
|
||||
}
|
||||
timer.expires_from_now(std::chrono::seconds(2));
|
||||
timer.async_wait([&] (boost::system::error_code) {
|
||||
fmt::print(stderr, "Async-locked operation done\n");
|
||||
mutex.unlock();
|
||||
});
|
||||
};
|
||||
|
||||
auto cancellable_op = [&](error_code ec) {
|
||||
fmt::print(
|
||||
stderr,
|
||||
"Cancellable async-locked operation finished with ec: {}\n", ec.message()
|
||||
);
|
||||
if (ec == asio::error::operation_aborted)
|
||||
return;
|
||||
mutex.unlock();
|
||||
};
|
||||
|
||||
mutex.lock(std::move(op));
|
||||
|
||||
mutex.lock(
|
||||
asio::bind_cancellation_slot(
|
||||
cancel_signal.slot(), std::move(cancellable_op)
|
||||
)
|
||||
);
|
||||
|
||||
asio::steady_timer timer2(tp);
|
||||
timer2.expires_from_now(std::chrono::seconds(1));
|
||||
timer2.async_wait([&] (boost::system::error_code) {
|
||||
cancel_signal.emit(asio::cancellation_type::terminal);
|
||||
});
|
||||
|
||||
tp.wait();
|
||||
}
|
||||
|
||||
void test_destructor() {
|
||||
asio::thread_pool tp;
|
||||
asio::cancellation_signal cancel_signal;
|
||||
|
||||
{
|
||||
async_mutex mutex(tp.get_executor());
|
||||
asio::steady_timer timer(tp);
|
||||
|
||||
auto op = [&](error_code ec_mtx) {
|
||||
if (ec_mtx == asio::error::operation_aborted) {
|
||||
fmt::print(
|
||||
stderr,
|
||||
"Mutex operation cancelled error_code {}\n",
|
||||
ec_mtx.message()
|
||||
);
|
||||
mutex.unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
timer.expires_from_now(std::chrono::seconds(2));
|
||||
timer.async_wait([&] (boost::system::error_code ec) {
|
||||
if (ec == asio::error::operation_aborted)
|
||||
return;
|
||||
|
||||
fmt::print(
|
||||
stderr,
|
||||
"Async-locked operation done with error_code {}\n",
|
||||
ec.message()
|
||||
);
|
||||
mutex.unlock();
|
||||
});
|
||||
};
|
||||
|
||||
mutex.lock(std::move(op));
|
||||
}
|
||||
|
||||
tp.wait();
|
||||
}
|
||||
|
||||
void test_basics() {
|
||||
asio::thread_pool tp;
|
||||
|
||||
// {
|
||||
asio::cancellation_signal cs;
|
||||
async_mutex mutex(tp.get_executor());
|
||||
auto s1 = asio::make_strand(tp.get_executor());
|
||||
auto s2 = asio::make_strand(tp.get_executor());
|
||||
|
||||
mutex.lock(asio::bind_executor(s1, [&mutex, s1](boost::system::error_code ec) mutable {
|
||||
fmt::print(
|
||||
stderr,
|
||||
"Scoped-locked operation (1) done with error_code {} ({})\n",
|
||||
ec.message(),
|
||||
s1.running_in_this_thread()
|
||||
);
|
||||
if (ec != asio::error::operation_aborted)
|
||||
mutex.unlock();
|
||||
}));
|
||||
|
||||
mutex.lock(
|
||||
asio::bind_cancellation_slot(
|
||||
cs.slot(),
|
||||
asio::bind_executor(s2, [s2](boost::system::error_code ec){
|
||||
fmt::print(
|
||||
stderr,
|
||||
"Scoped-locked operation (2) done with error_code {} ({})\n",
|
||||
ec.message(),
|
||||
s2.running_in_this_thread()
|
||||
);
|
||||
})
|
||||
)
|
||||
);
|
||||
cs.emit(asio::cancellation_type_t::terminal);
|
||||
cs.slot().clear();
|
||||
// }
|
||||
|
||||
tp.wait();
|
||||
}
|
||||
|
||||
void test_mutex() {
|
||||
// test_basics();
|
||||
// return;
|
||||
// test_destructor();
|
||||
// test_cancellation();
|
||||
// return;
|
||||
|
||||
auto bench = ankerl::nanobench::Bench();
|
||||
bench.relative(true);
|
||||
|
||||
bench.run("std::mutex", [] {
|
||||
test_with<std_mutex>(test_with_mutex);
|
||||
});
|
||||
|
||||
bench.run("async_mutex", [] {
|
||||
test_with<async_mutex>(test_with_async_mutex);
|
||||
});
|
||||
|
||||
bench.run("async::mutex", [] {
|
||||
test_with<async::mutex>(test_with_old_async_mutex);
|
||||
});
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
#include <boost/spirit/home/x3.hpp>
|
||||
|
||||
template <typename T>
|
||||
static constexpr auto to_(T& arg) {
|
||||
return [&](auto& ctx) { arg = boost::spirit::x3::_attr(ctx); };
|
||||
}
|
||||
|
||||
template <typename T, typename Parser>
|
||||
static constexpr auto as_(Parser&& p){
|
||||
return boost::spirit::x3::rule<struct _, T>{} = std::forward<Parser>(p);
|
||||
}
|
||||
|
||||
void test_uri_parser(){
|
||||
struct authority_path { std::string host, port, path; };
|
||||
std::vector<authority_path> _servers;
|
||||
|
||||
std::string brokers = "iot.fcluster.mireo.hr:1234, fc/nesto";
|
||||
std::string default_port = "8883";
|
||||
|
||||
namespace x3 = boost::spirit::x3;
|
||||
|
||||
std::string host, port, path;
|
||||
|
||||
// loosely based on RFC 3986
|
||||
auto unreserved_ = x3::char_("-a-zA-Z_0-9._~");
|
||||
auto digit_ = x3::char_("0-9");
|
||||
auto separator_ = x3::char_(',');
|
||||
|
||||
auto host_ = as_<std::string>(+unreserved_)[to_(host)];
|
||||
auto port_ = as_<std::string>(':' >> +digit_)[to_(port)];
|
||||
auto path_ = as_<std::string>('/' >> *unreserved_)[to_(path)];
|
||||
auto uri_ = *x3::omit[x3::space] >> (host_ >> *port_ >> *path_) >>
|
||||
(*x3::omit[x3::space] >> x3::omit[separator_ | x3::eoi]);
|
||||
|
||||
for (auto b = brokers.begin(); b != brokers.end(); ) {
|
||||
host.clear(); port.clear(); path.clear();
|
||||
if (phrase_parse(b, brokers.end(), uri_, x3::eps(false))) {
|
||||
_servers.push_back({
|
||||
std::move(host), port.empty() ? default_port : std::move(port),
|
||||
std::move(path)
|
||||
});
|
||||
}
|
||||
else b = brokers.end();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user