From 748fd0a586a81e9b1f8be94d550c68f615d53c78 Mon Sep 17 00:00:00 2001 From: marcelb Date: Wed, 11 Jun 2025 09:56:32 +0200 Subject: [PATCH] Write examples and tests, refaktor, tested --- CMakeLists.txt | 3 + README.md | 225 ++------- lib/asynco.hpp | 17 +- lib/asynco_default.hpp | 15 +- lib/trigger.hpp | 5 +- src/asynco.cpp | 16 +- src/asynco_default.cpp | 25 +- src/timers.cpp | 1 - test/CMakeLists.txt | 35 +- test/main.cpp | 625 ------------------------ test/main_async.cpp | 84 ++++ test/main_async_default.cpp | 82 ++++ test/main_coroutine.cpp | 42 ++ test/main_coroutine_default.cpp | 40 ++ test/main_default.cpp | 14 +- test/{main_asynco.cpp => main_init.cpp} | 5 +- test/main_timers.cpp | 41 ++ test/main_timers_default.cpp | 40 ++ test/main_trigger.cpp | 124 +++++ test/main_trigger_default.cpp | 118 +++++ 20 files changed, 704 insertions(+), 853 deletions(-) delete mode 100644 test/main.cpp create mode 100644 test/main_async.cpp create mode 100644 test/main_async_default.cpp create mode 100644 test/main_coroutine.cpp create mode 100644 test/main_coroutine_default.cpp rename test/{main_asynco.cpp => main_init.cpp} (67%) create mode 100644 test/main_timers.cpp create mode 100644 test/main_timers_default.cpp create mode 100644 test/main_trigger.cpp create mode 100644 test/main_trigger_default.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 6522cee..db73881 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,6 +25,9 @@ target_link_libraries(asynco Boost::system) # Dodaj testove add_subdirectory(test) +add_compile_options(-w) + + # Instaliraj biblioteku # install(TARGETS asynco DESTINATION lib) diff --git a/README.md b/README.md index 94fadae..115bbef 100644 --- a/README.md +++ b/README.md @@ -13,14 +13,12 @@ The asynchronous filesystem was included solely to demonstrate how users can wra - Object oriented - Small and easy to integrate -- Header only - Asynchronous programming - Multithread - Asynchronous timer functions: Periodic, Delayed (like setInterval and setTimeout from JS) - Typed events (on, tick, off) (like EventEmitter from JS: on, emit, etc) - Event loops - Multiple parallel execution loops -- Asynchronous file IO - Based on ASIO (Boost Asio) - On C++20 support Boost.Asio coroutines ## Installation @@ -28,37 +26,64 @@ The asynchronous filesystem was included solely to demonstrate how users can wra Just download the latest release and unzip it into your project. ```c++ -#define NUM_OF_RUNNERS 8 // To change the number of threads used by asynco, without this it runs according to the number of cores +// for default global runtime + +#include "asynco/lib/asynco_default.hpp" -#include "asynco/lib/asynco.hpp" // async_ (), await_() -#include "asynco/lib/triggers.hpp" // Trigger (event emitter) -#include "asynco/lib/timers.hpp" // Periodic, Delayed (like setInterval and setTimeout from JS) -#include "asynco/lib/filesystem.hpp" // for async read and write files -#include "asynco/lib/define.hpp" // async_, await_, asyncable_ defines using namespace marcelb; using namespace asynco; -// At the end of the main function, always set -Asynco_Default_Runtime.run(); -return 0; +int main() { + asynco_default_run(); + + // code + + asynco_default_join() + return 0; +} + +// own instace of runtime + +#include "asynco/lib/asynco.hpp" + +using namespace marcelb; +using namespace asynco; + +int main() { + Asynco asynco; + asynco.run(2); + + // code + + asynco.join(); + return 0; +} ``` ## Usage -In the following sections, we will explore timers, function execution via the runtime, asynchronous invocation, and waiting for results. We will cover essential use cases involving triggers, file handling, and coroutines. +In the following sections, we will explore timers, function execution via the runtime, asynchronous invocation, and waiting for results. We will cover essential use cases involving triggers, and coroutines. ### Timers -We have two timer classes, Periodic (which runs a callback function periodically), and Delayed (delayed runs a callback function only once). +We have one timer classes, int two mode Periodic (which runs a callback function periodically), and Delayed (delayed runs a callback function only once). ```c++ // start periodic -Periodic inter1 ([]() { +Timer inter1 = periodic ([]() { cout << "Interval 1" << endl; }, 1000); +// or usint own instance runtime +/** + * Asynco asynco; + * asynco.run(2); + * Timer inter1 = asynco.periodic ([]() { + * cout << "Interval 1" << endl; + * }, 1000); +*/ // stop periodic inter1.stop(); @@ -69,7 +94,7 @@ int t = inter1.ticks(); bool stoped = inter1.stoped(); // start delayed -Delayed time1 ( [] () { +Timer time1 = delayed( [] () { cout << "Timeout 1 " << endl; }, 10000); @@ -93,7 +118,7 @@ Running functions at runtime, asynchronous execution, uses the `async_` call and */ async_ ( []() { - sleep_for(2s); // only for simulating long duration function + sleep(2); // only for simulating long duration function cout << "nonsync " << endl; return 5; }); @@ -126,12 +151,12 @@ async_ ( [&classes] () { }); ``` -To wait for the result (blocking the flow) use `await_` (basically nothing more than a `.get()` call on a future object) +To wait for the result (blocking the flow) use `await_` (This does not block the event loop in principle. If the result is not ready for a short time, it starts another job in place while it waits.) ```c++ auto a = async_ ( []() { - sleep_for(2s); // only for simulating long duration function + sleep(2); // only for simulating long duration function cout << "nonsync " << endl; return 5; }); @@ -143,7 +168,7 @@ cout << await_(a) << endl; */ cout << await_(async_ ( [] () { - sleep_for(chrono::seconds(1)); // only for simulating long duration function + sleep(1); // only for simulating long duration function cout << "await_ end" << endl; return 4; })) << endl; @@ -159,104 +184,7 @@ await_ ([]() { }); ``` -If multiple function calls do not depend on each other, you can call them and wait for the results later, better concurrency. - -```c++ - -auto a = async_ ( []() { - cout << "A" << endl; - return 3; -}); - -auto b = async_ ( []() { - cout << "B" << endl; - throw runtime_error("Test exception"); - return; -}); - -auto c = async_ ( []() { - cout << "C" << endl; - return "Hello"; -}); - -int a_; -string c_; - -auto await_all = [&] () { - a_ = await_(a); - await_(b); - c_ = await_(c); -}; - -try { - await_all(); - cout << "a_ " << a_ << " c_ " << c_ << endl; -} catch (const exception& exc) { - cout << exc.what() << endl; -} - -// // same type - -vector> fut_vec; -for (int i=0; i<5; i++) { - fut_vec.push_back( - async_ ( [i]() { - cout << "Async_ " << i << endl; - }) - ); -} - -auto await_all = [&] () { - for (int i=0; i _promise; - Delayed t( [&]() { - _promise.set_value(); - }, _time); - - return _promise.get_future().get(); -} - -sleep_to(3000); - -/** -* Catch promise reject -*/ - -void promise_reject (int _time) { - promise _promise; - Delayed t( [&]() { - try { - // simulate except - throw runtime_error("Error simulation"); - _promise.set_value(); - } catch (...) { - _promise.set_exception(current_exception()); - } - }, _time); - - return _promise.get_future().get(); -} - -try { - promise_reject(3000); -} catch (runtime_error err) { - cout<< err.what() << endl; -} -``` +Here too you can use your own runtime instance, only the methods are `.async()` and `.await()` ### Triggers @@ -267,9 +195,9 @@ The library implements Triggers, which are basically typed Events. * initialization of typed events */ -Trigger ev2int; -Trigger evintString; -Trigger<> evoid; +Trigger ev2int = trigger(); +Trigger evintString = trigger(); +Trigger<> evoid = trigger<>(); ev2int.on("sum", [](int a, int b) { cout << "Sum " << a+b << endl; @@ -316,7 +244,7 @@ Extend own class whit events ```c++ class myOwnClass : public Trigger { public: - myOwnClass() : Trigger() {}; + myOwnClass() : Trigger(asynco_default_runtime()) {}; }; myOwnClass myclass; @@ -340,6 +268,8 @@ class ClassWithTriggers { Trigger emitter2; public: + ClassWithTriggers(): emitter1(asynco_default_runtime()), emitter2(asynco_default_runtime()) {} + template void on(const string& key, function callback) { if constexpr (sizeof...(T) == 1 && is_same_v>, int>) { @@ -379,48 +309,6 @@ mt.tick("string", string("Hello world")); ``` -Another example: -Asynchronous file IO - -```c++ -string data_; - -fs::read("test.txt", [&data_] (string data, exception* error) { - if (error) { - cout << "Error " << error->what() << endl; - } else { - cout << "Data " << endl << data << endl; - data_ = data; - cout << "Data_" << data_ << endl; - } -}); - -fs::write("test1.txt", "Hello world", [] (exception* error) { - if (error) { - cout << "Error " << error->what() << endl; - } else { - cout << "Write successfuly" << endl; - } -}); - -auto future_data = fs::read("test.txt"); - -try { - string data = await_(future_data); -} catch (exception& err) { - cout << err.what() << endl; -} - -auto future_status = fs::write("test.txt", "Hello world"); - -try { - await_(future_status); -} catch (exception& err) { - cout << err.what() << endl; -} - -``` - ## Coroutine If `define.hpp` is included, you can initialize coroutines using `asyncable`; if not, just use `boost::asio::awaitable`. @@ -473,17 +361,8 @@ await_ ([]() -> asyncable { ``` -Timers and triggers work the same with coroutines; it is important to call the coroutine with `async_` in the callback, and to call `async_`, wrap it with a lambda expression: - -```c++ - -Periodic p([]() { - async_(c2(34)); -}, 2000); - -``` If you need a result, you can also retrieve it with `await_`. - +Here too you can use your own runtime instance, only the methods are `.async()` and `.await()` ## License diff --git a/lib/asynco.hpp b/lib/asynco.hpp index 4b2d15e..3176dc6 100644 --- a/lib/asynco.hpp +++ b/lib/asynco.hpp @@ -11,16 +11,15 @@ using namespace std; #include -using namespace boost::asio; - -#include "timers.hpp" -#include "trigger.hpp" - #if __cplusplus >= 202002L #include #include #include #endif +using namespace boost::asio; + +#include "timers.hpp" +#include "trigger.hpp" namespace marcelb { namespace asynco { @@ -37,10 +36,10 @@ class Asynco { public: io_context io_ctx; - // Asynco(uint8_t threads = thread::hardware_concurrency()); - void run(uint8_t threads = thread::hardware_concurrency()); + void run_on_this(); + void join(); /** @@ -48,8 +47,6 @@ public: */ template auto async(F&& f, Args&&... args) -> future> { - cout << "async" << endl; - using return_type = invoke_result_t; future res = io_ctx.post(boost::asio::use_future(bind(forward(f), forward(args)...))); return res; @@ -157,7 +154,7 @@ public: template Trigger trigger() { - return Trigger(this); + return Trigger(*this); } diff --git a/lib/asynco_default.hpp b/lib/asynco_default.hpp index 5d537b5..7577abd 100644 --- a/lib/asynco_default.hpp +++ b/lib/asynco_default.hpp @@ -8,15 +8,12 @@ namespace asynco { extern Asynco Asynco_Default_Runtime; -// Asynco& Asynco_Default_Runtime(); /** * Run the function asynchronously */ template auto async_(F&& f, Args&&... args) -> future> { - cout << "async_default" << endl; - return Asynco_Default_Runtime.async(bind(forward(f), forward(args)...)); } @@ -104,6 +101,18 @@ Trigger trigger() { #define asyncable boost::asio::awaitable #endif +Asynco& asynco_default_runtime(); + +void asynco_default_run(); + +void asynco_default_run_on_this(); + +void asynco_default_join(); + +io_context& asynco_default_io_context(); + + + } } diff --git a/lib/trigger.hpp b/lib/trigger.hpp index f90f58b..c304796 100644 --- a/lib/trigger.hpp +++ b/lib/trigger.hpp @@ -25,10 +25,9 @@ class Trigger { mutex m_eve; unordered_map>> triggers; - Trigger(Asynco& _engine) - : engine(_engine) {} - public: + Trigger(Asynco& _engine) + : engine(_engine) {} /** * Defines event by key, and callback function diff --git a/src/asynco.cpp b/src/asynco.cpp index 03fff93..7a14554 100644 --- a/src/asynco.cpp +++ b/src/asynco.cpp @@ -5,25 +5,25 @@ namespace marcelb::asynco { void Asynco::init_loops_in_threads(uint8_t threads) { for (int i=0; i(io_ctx); - cout << "Asynco" << endl; init_loops_in_threads(threads); } +void Asynco::run_on_this() { + if (!_work) { + cout << "POKRENE SE KREIRANJE WORK PTR"; + _work = make_unique(io_ctx); + } + io_ctx.run(); +} + void Asynco::join() { for (auto& runner : _runners) { runner.join(); diff --git a/src/asynco_default.cpp b/src/asynco_default.cpp index 1e705f3..3f06e74 100644 --- a/src/asynco_default.cpp +++ b/src/asynco_default.cpp @@ -5,11 +5,6 @@ namespace marcelb::asynco { Asynco Asynco_Default_Runtime; -// Asynco& Asynco_Default_Runtime() { -// static Asynco _default; // ili koliko već treba -// return _default; -// } - Timer delayed(function callback, uint64_t time) { return Timer(Asynco_Default_Runtime.io_ctx, callback, time, TimerType::Delayed); } @@ -18,4 +13,24 @@ Timer periodic(function callback, uint64_t time) { return Timer(Asynco_Default_Runtime.io_ctx, callback, time, TimerType::Periodic); } +Asynco& asynco_default_runtime() { + return Asynco_Default_Runtime; +} + +void asynco_default_run() { + Asynco_Default_Runtime.run(); +} + +void asynco_default_run_on_this() { + Asynco_Default_Runtime.run_on_this(); +} + +void asynco_default_join() { + Asynco_Default_Runtime.join(); +} + +io_context& asynco_default_io_context() { + return Asynco_Default_Runtime.io_ctx; +} + }; diff --git a/src/timers.cpp b/src/timers.cpp index f004d2a..2a21dcc 100644 --- a/src/timers.cpp +++ b/src/timers.cpp @@ -34,7 +34,6 @@ Timer::Timer (io_context& _io_ctx, function _callback, uint64_t _time, T type(_type), callback(_callback), time(_time) { - cout << "Timer" << endl; init(); } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index bae1259..729fb9a 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,14 +1,29 @@ -# add_executable(asynco_test main.cpp) - -# # Linkaj test sa Asynco bibliotekom -# target_link_libraries(asynco_test asynco Boost::system) - add_executable(asynco_default main_default.cpp) - -# Linkaj test sa Asynco bibliotekom target_link_libraries(asynco_default asynco Boost::system) -add_executable(asynco_asynco main_asynco.cpp) +add_executable(asynco_init main_init.cpp) +target_link_libraries(asynco_init asynco Boost::system) -# Linkaj test sa Asynco bibliotekom -target_link_libraries(asynco_asynco asynco Boost::system) \ No newline at end of file +add_executable(asynco_async_default main_async_default.cpp) +target_link_libraries(asynco_async_default asynco Boost::system) + +add_executable(asynco_async main_async.cpp) +target_link_libraries(asynco_async asynco Boost::system) + +add_executable(asynco_timers_default main_timers_default.cpp) +target_link_libraries(asynco_timers_default asynco Boost::system) + +add_executable(asynco_timers main_timers.cpp) +target_link_libraries(asynco_timers asynco Boost::system) + +add_executable(asynco_trigger_default main_trigger_default.cpp) +target_link_libraries(asynco_trigger_default asynco Boost::system) + +add_executable(asynco_trigger main_trigger.cpp) +target_link_libraries(asynco_trigger asynco Boost::system) + +add_executable(asynco_coroutine_default main_coroutine_default.cpp) +target_link_libraries(asynco_coroutine_default asynco Boost::system) + +add_executable(asynco_coroutine main_coroutine.cpp) +target_link_libraries(asynco_coroutine asynco Boost::system) \ No newline at end of file diff --git a/test/main.cpp b/test/main.cpp deleted file mode 100644 index b8f66b9..0000000 --- a/test/main.cpp +++ /dev/null @@ -1,625 +0,0 @@ -#define NUM_OF_RUNNERS 4 - -#include "asynco.hpp" -#include "trigger.hpp" -#include "filesystem.hpp" -#include "timers.hpp" -#include "define.hpp" - -using namespace marcelb::asynco; - -#include -#include -#include -#include -#include - -using namespace std; -using namespace this_thread; - -// asyncable c2 (int a) { -// co_return a*2; -// } - -// asyncable sleep_co (int a) { -// sleep(a); -// cout << "Gotov" << endl; -// co_return; -// } - - -// asyncable c () { -// cout << "Ispisi" << endl; -// co_await c2(0); -// co_return; -// } - - - -// void sleep_to (int _time) { -// promise _promise; -// Delayed t( [&]() { -// _promise.set_value(); -// }, _time); - -// return _promise.get_future().get(); -// } - -// void sleep_to (int _time) { -// promise _promise; -// Delayed t( [&]() { -// _promise.set_value(); -// }, _time); -// await_ (_promise.get_future(), 100); -// } - -// future sleep_to (int _time) { -// promise _promise; -// future _future = _promise.get_future(); - -// Delayed t( [&]() { -// _promise.set_value(); -// }, _time); - -// return _future; -// } - -// void promise_reject (int _time) { -// promise _promise; -// Delayed t( [&]() { -// try { -// // simulate except -// throw runtime_error("Error simulation"); -// _promise.set_value(); -// } catch (...) { -// _promise.set_exception(current_exception()); -// } -// }, _time); - -// return _promise.get_future().get(); -// } - -// void notLambdaFunction() { -// cout << "Call to not lambda function" << endl; -// } - -// class clm { -// public: -// void classMethode() { -// cout << "Call class method" << endl; -// } -// }; - -// // // ------------------ EXTEND OWN CLASS WITH EVENTS ------------------- - -// class myOwnClass : public Trigger { -// public: -// myOwnClass() : Trigger() {}; -// }; - -// // ----------------- MULTIPLE TRIGGERS IN ONE CLASS ------------------ - -// class ClassWithTriggers { -// Trigger emitter1; -// Trigger emitter2; - -// public: -// template -// void on(const string& key, function callback) { -// if constexpr (sizeof...(T) == 1 && is_same_v>, int>) { -// emitter1.on(key, callback); -// } -// else if constexpr (sizeof...(T) == 1 && is_same_v>, string>) { -// emitter2.on(key, callback); -// } -// } - -// template -// void tick(const string& key, Args&&... args) { -// if constexpr (sizeof...(Args) == 1 && is_same_v>, int>) { -// emitter1.tick(key, forward(args)...); -// } -// else if constexpr (sizeof...(Args) == 1 && is_same_v>, string>) { -// emitter2.tick(key, forward(args)...); -// } -// else { -// static_assert(sizeof...(Args) == 0, "Unsupported number or types of arguments"); -// } -// } -// }; - - -int main () { - - auto start = rtime_ms(); - - // --------------- TIME ASYNCHRONOUS FUNCTIONS -------------- - - /** - * Init Periodic and delayed; clear Periodic and delayed - */ - - // Periodic inter1 ([&]() { - // cout << "Periodic prvi " << rtime_ms() - start << endl; - // }, 1000); - - // Periodic inter2 ([&]() { - // cout << "Periodic drugi " << rtime_ms() - start << endl; - // }, 2000); - - // Periodic inter3 ([&]() { - // cout << "Periodic treći " << rtime_ms() - start << endl; - // }, 1000); - - // Periodic inter4 ([&]() { - // // cout << "Periodic cetvrti " << rtime_ms() - start << endl; - // cout << "Ticks " << inter3.ticks() << endl; - // }, 500); - - // Periodic inter5 ([&]() { - // cout << "Periodic peti " << rtime_ms() - start << endl; - // }, 2000); - - // Periodic inter6 ([&]() { - // cout << "Periodic sesti " << rtime_ms() - start << endl; - // }, 3000); - - // Delayed time1 ( [&] () { - // cout << "Close Periodic 1 i 2 " << rtime_ms() - start << endl; - // inter1.stop(); - // cout << "inter1.stop " << endl; - // inter2.stop(); - // cout << "inter2.stop " << endl; - // }, 8000); - - - // Delayed time2 ([&] () { - // cout << "Close Periodic 3 " << rtime_ms() - start << endl; - // inter3.stop(); - // cout << "Stoped " << inter3.stoped() << endl; - // // time1.stop(); - // }, 5000); - - - // if (time2.expired()) { - // cout << "isteko " << endl; - // } else { - // cout << "nije isteko " << endl; - // } - - // // sleep(6); - - // if (time2.expired()) { - // cout << "isteko " << endl; - // } else { - // cout << "nije isteko " << endl; - // } - - // // // // ------------------------ MAKE FUNCTIONS ASYNCHRONOUS ------------------------- - - // // /** - // // * Run an function asyncronic - // // */ - - // async_ ( []() { - // sleep_for(2s); // only for simulate log duration function - // cout << "asynco 1" << endl; - // return 5; - // }); - - // /** - // * Call not lambda function - // */ - - // async_ (notLambdaFunction); - - - // await_ ( - // async_ ( - // notLambdaFunction - // ) - // ); - - - // // async(launch::async, [] () { - // // cout << "Another thread in async style!" << endl; - // // }); - - // // /** - // // * Call class method - // // */ - - // clm classes; - // async_ ( [&classes] () { - // classes.classMethode(); - // }); - - // sleep(5); - - // // /** - // // * await_ after runned as async - // // */ - - // auto aa = async_ ( []() { - // sleep_for(2s); // only for simulate log duration function - // cout << "async_ 2" << endl; - // return 5; - // }); - - // cout << await_(aa) << endl; - // cout << "print after async_ 2" << endl; - - // /** - // * await_ async function call and use i cout - // */ - - // cout << await_(async_ ( [] () { - // sleep_for(chrono::seconds(1)); // only for simulate log duration function - // cout << "await_ end" << endl; - // return 4; - // })) << endl; - - // /** - // * Sleep with Delayed sleep implement - // */ - - // sleep_to(3000); - // cout << "sleep_to " << rtime_ms() - start << endl; - - // /** - // * Catch promise reject - // */ - - // try { - // promise_reject(3000); - // } catch (runtime_error err) { - // cout<< err.what() << endl; - // } - - // cout << "promise_reject " << rtime_ms() - start << endl; - - - // /** - // * Nested asynchronous invocation - // */ - - - // async_ ( [] { - // cout << "idemo ..." << endl; - // async_ ( [] { - // cout << "ugdnježdena async funkcija " << endl; - // }); - // }); - - - // // -------------------------- AWAIT ALL ---------------------------------- - - auto a = async_ ( []() { - cout << "A" << endl; - return 3; - }); - - auto b = async_ ( []() { - cout << "B" << endl; - // throw runtime_error("Test exception"); - return; - }); - - auto c = async_ ( []() { - cout << "C" << endl; - return "Hello"; - }); - - int a_; - string c_; - - // auto all = await_(a, c); - // cout << get<0>(all) << get<1>(all) << endl; - - // ili - - tie(a_, c_) = await_(a, c); - cout << a_ << c_ << endl; - - int d_; - float e_; - tie(d_, e_) = await_( async_ ( []() {return 1;}), async_ ([](){ return 4.3;})); - - cout << d_ << e_ << endl; - - - // auto await_all = [&] () { - // a_ = await_(a); - // await_(b); - // c_ = await_(c); - // }; - - // try { - // await_all(); - // cout << "a_ " << a_ << " c_ " << c_ << endl; - // } catch (const exception& exc) { - // cout << exc.what() << endl; - // } - - // // // same type - - // vector> fut_vec; - // for (int i=0; i<5; i++) { - // fut_vec.push_back( - // async_ ( [i]() { - // cout << "Async_ " << i << endl; - // }) - // ); - // } - - // auto await_all2 = [&] () { - // for (int i=0; i ev2int; - // Trigger evintString; - // Trigger<> evoid; - - // ev2int.on("sum", [](int a, int b) { - // cout << "Sum " << a+b << endl; - // }); - - // ev2int.on("sum", [](int a, int b) { - // cout << "Sum done" << endl; - // }); - - // evintString.on("substract", [](int a, string b) { - // cout << "Substract " << a-stoi(b) << endl; - // }); - - // evoid.on("void", []() { - // cout << "Void emited" << endl; - // }); - - // string emited2 = "2"; - - // evoid.on("void", [&]() { - // cout << "Void emited " << emited2 << endl; - // }); - - // evoid.tick("void"); - // sleep(1); - - // /** - // * Emit - // */ - - // ev2int.tick("sum", 5, 8); - - - // sleep(1); - // evintString.tick("substract", 3, to_string(2)); - - // sleep(1); - // evoid.off("void"); - // evoid.tick("void"); - - - // cout << "Ukupno 2 int " << ev2int.listeners() << endl; - // cout << "Ukupno evintString " << evintString.listeners() << endl; - // cout << "Ukupno evoid " << evoid.listeners() << endl; - // cout << "Ukupno 2 int " << ev2int.listeners("sum") << endl; - - // /** - // * Own class - // */ - - // myOwnClass myclass; - - // Delayed t( [&] { - // myclass.tick("constructed", 1); - // }, 200); - - // myclass.on("constructed", [] (int i) { - // cout << "Constructed " << i << endl; - // }); - - // /** - // * - // * Use class with multiple triggers - // * - // */ - - // ClassWithTriggers mt; - - // mt.on("int", function([&](int i) { - // cout << "Emit int " << i << endl; - // })); - - // mt.on("string", function([&](string s) { - // cout << "Emit string " << s << endl; - // })); - - // mt.tick("int", 5); - // mt.tick("string", string("Hello world")); - - - // auto status = fs::read("test1.txt"); - - - // try { - // auto data = await_(status); - // cout << data; - // } catch (exception& err) { - // cout << err.what() << endl; - // } - - - // string data_; - // auto start_read = rtime_us(); - - // fs::read("test1.txt", [&data_, &start_read] (string data, exception* error) { - // if (error) { - // cout << "Error " << error->what() << endl; - // } else { - // // cout << "Data " << endl << data << endl; - // // data_ = data; - // // cout << "Data_" << data_ << endl; - // cout << "read " << rtime_us() - start_read << endl; - // } - // }); - - - // ---------------------------------------------------------------------------------------------------- - - - // auto i = async_ ( []() -> asyncable { - // cout << "aaaa" << endl; - // co_return 5; - // }); - - // auto i = async_ (retint()); - - // auto i_ = await_(i); - - // cout << i_ << endl; - - - // Periodic a( []() -> asyncable { - // cout << "corutina" << endl; - // // co_await retint(); - // }, 2000); - - - // Periodic b_( []() { - // cout << "funckija" << endl; - // }, 2000); - - - // Trigger ev2int; - // Trigger evintString; - // Trigger<> evoid; - - // ev2int.on("sum", [](int a, int b) -> asyncable { - // cout << "Sum " << a+b << endl; - // }); - - // ev2int.on("sum", [](int a, int b) -> asyncable { - // cout << "Sum done" << endl; - // }); - - // evintString.on("substract", [](int a, string b) -> asyncable { - // cout << "Substract " << a-stoi(b) << endl; - // }); - - // evoid.on("void", []() { - // auto a = await_ (async_ (c2(34))); - // cout << "A " << a << endl; - // }); - - - // auto c1 = []() -> asyncable { - // cout << "Roge " << endl; - // co_return; - - // }; - - // auto a = await_ ( c2(3)); - // cout << a << endl; - - - // await_ ([]() -> asyncable { - // cout << "Hello" << endl; - // co_await c2(4); - // co_return; - // }()); - - // async_ ([]() -> asyncable { - // cout << "1" << endl; - // co_await sleep_co(1); - // co_return; - // }()); - - // async_ ([]() -> asyncable { - // cout << "2" << endl; - // co_await sleep_co(1); - // co_return; - // }()); - - // async_ ([]() -> asyncable { - // cout << "3" << endl; - // co_await sleep_co(1); - // co_return; - // }()); - - // async_ ([]() -> asyncable { - // cout << "4" << endl; - // co_await sleep_co(1); - // co_return; - // }()); - - // async_ ([]() -> asyncable { - // cout << "5" << endl; - // co_await sleep_co(1); - // co_return; - // }()); - - - // await_ ([]() { - // cout << "Hello" << endl; - // }); - - // Periodic p( []() { - // async_ ( - // c2(34) - // ); - // }, 2000); - - // await_( async_ ( [c1 = move(c1)]() -> asyncable { - // cout << "Baba roga" << endl; - // co_await c1(); - // })); - - // string emited2 = "2"; - - // evoid.on("void", [&]() -> asyncable { - // cout << "Void emited " << emited2 << endl; - // }); - - // evoid.tick("void"); - - - - - // vector> futures; - - // for (int i=0; i<20; i++) { - // futures.push_back( - // async_([a = i](){ - // for (int i=0; i<1000; i++) { - // cout << a << " " << i << endl; - // // sleep_to(i); - // } - // }) - // ); - // } - - // for (int i=0; i<20; i++) { - // await_(futures[i]); - // // await_(futures[i]); - // } - - - - - - cout << "-------------end main------------- " << rtime_ms() - start << endl; - Asynco_Default_Runtime.run(); - return 0; -} - diff --git a/test/main_async.cpp b/test/main_async.cpp new file mode 100644 index 0000000..a4b6117 --- /dev/null +++ b/test/main_async.cpp @@ -0,0 +1,84 @@ +#include "../lib/asynco.hpp" +using namespace marcelb::asynco; + +#include +using namespace std; + +Asynco asynco; + +void notLambdaFunction() { + cout << "Call to not lambda function" << endl; +} + + +class clm { + public: + void classMethode() { + cout << "Call class method" << endl; + } +}; + +void sleep_to (int _time) { + promise _promise; + Timer t = asynco.delayed( [&]() { + _promise.set_value(); + }, _time); + + return asynco.await(_promise.get_future()); +} + +int main() { + + asynco.run(2); + + /** + * Run an lambda function asynchronously + */ + + asynco.async ( []() { + cout << "async " << endl; + }); + + + /** + * Run not lambda function + */ + + asynco.async (notLambdaFunction); + + /** + * Run class method + */ + + clm classes; + asynco.async ( [&classes] () { + classes.classMethode(); + }); + + //------------------AWAIT---------------------- + + auto a = asynco.async ( []() { + sleep_to(1000); //only for simulating long duration function + return 5; + }); + + cout << asynco.await(a) << endl; + + /** + * await async function call and use i cout + */ + + cout << asynco.await(asynco.async ( [] () { + sleep_to(1000); + cout << "await_ end" << endl; + return 4; + })) << endl; + + + asynco.await ([]() { // run in runtime and await now + cout << "Hello" << endl; + }); + + asynco.join(); + return 0; +} \ No newline at end of file diff --git a/test/main_async_default.cpp b/test/main_async_default.cpp new file mode 100644 index 0000000..569996f --- /dev/null +++ b/test/main_async_default.cpp @@ -0,0 +1,82 @@ +#include "../lib/asynco_default.hpp" +using namespace marcelb::asynco; + +#include +using namespace std; + +void notLambdaFunction() { + cout << "Call to not lambda function" << endl; +} + + +class clm { + public: + void classMethode() { + cout << "Call class method" << endl; + } +}; + +void sleep_to (int _time) { + promise _promise; + Timer t = delayed( [&]() { + _promise.set_value(); + }, _time); + + return await_(_promise.get_future()); +} + +int main() { + + asynco_default_run(); + + /** + * Run an lambda function asynchronously + */ + + async_ ( []() { + cout << "async " << endl; + }); + + + /** + * Run not lambda function + */ + + async_ (notLambdaFunction); + + /** + * Run class method + */ + + clm classes; + async_ ( [&classes] () { + classes.classMethode(); + }); + + //------------------AWAIT---------------------- + + auto a = async_ ( []() { + sleep_to(1000); //only for simulating long duration function + return 5; + }); + + cout << await_(a) << endl; + + /** + * await async function call and use i cout + */ + + cout << await_(async_ ( [] () { + sleep_to(1000); + cout << "await_ end" << endl; + return 4; + })) << endl; + + + await_ ([]() { // run in runtime and await now + cout << "Hello" << endl; + }); + + asynco_default_join(); + return 0; +} \ No newline at end of file diff --git a/test/main_coroutine.cpp b/test/main_coroutine.cpp new file mode 100644 index 0000000..2c2ecc4 --- /dev/null +++ b/test/main_coroutine.cpp @@ -0,0 +1,42 @@ +#include "../lib/asynco.hpp" +using namespace marcelb::asynco; + +#include +using namespace std; + +int main() { + + Asynco asynco; // or global + asynco.run(2); + + asyncable c2(int a) { + co_return a * 2; + } + + asynco.async(c2(4)); + + asynco.async([]() -> asyncable { + std::cout << "Hello" << std::endl; + co_await c2(4); + co_return; + }()); + + + int r = asynco.await( + asynco.async( + c2(10) + )); + + + auto a = asynco.await( c2(3)); + cout << a << endl; + + asynco.await([]() -> asyncable { + cout << "Hello" << endl; + co_return; + }()); + + + asynco.join(); + return 0; +} \ No newline at end of file diff --git a/test/main_coroutine_default.cpp b/test/main_coroutine_default.cpp new file mode 100644 index 0000000..e7315ae --- /dev/null +++ b/test/main_coroutine_default.cpp @@ -0,0 +1,40 @@ +#include "../lib/asynco_default.hpp" +using namespace marcelb::asynco; + +#include +using namespace std; + +int main() { + asynco_default_run(); + + asyncable c2(int a) { + co_return a * 2; + } + + async_(c2(4)); + + async_([]() -> asyncable { + std::cout << "Hello" << std::endl; + co_await c2(4); + co_return; + }()); + + + int r = await_( + async_( + c2(10) + )); + + + auto a = await_ ( c2(3)); + cout << a << endl; + + await_ ([]() -> asyncable { + cout << "Hello" << endl; + co_return; + }()); + + + asynco_default_join(); + return 0; +} \ No newline at end of file diff --git a/test/main_default.cpp b/test/main_default.cpp index 83be494..472a1d9 100644 --- a/test/main_default.cpp +++ b/test/main_default.cpp @@ -5,18 +5,10 @@ using namespace marcelb::asynco; using namespace std; int main() { - Asynco_Default_Runtime.run(); - cout << "main" << endl; + asynco_default_run(); - async_([](){ - cout << "idemo" << endl; - }); + // code - auto interval = periodic([&](){ - cout << "idemo" << endl; - }, 1000); - - - Asynco_Default_Runtime.join(); + asynco_default_join(); return 0; } \ No newline at end of file diff --git a/test/main_asynco.cpp b/test/main_init.cpp similarity index 67% rename from test/main_asynco.cpp rename to test/main_init.cpp index 7b70bde..858a8a9 100644 --- a/test/main_asynco.cpp +++ b/test/main_init.cpp @@ -9,10 +9,7 @@ int main() { Asynco asynco; asynco.run(2); - auto interval = asynco.periodic([](){ - cout << "idemo" << endl; - }, 1000); - + // code asynco.join(); return 0; diff --git a/test/main_timers.cpp b/test/main_timers.cpp new file mode 100644 index 0000000..d518815 --- /dev/null +++ b/test/main_timers.cpp @@ -0,0 +1,41 @@ +#include "../lib/asynco.hpp" +using namespace marcelb::asynco; + +#include +using namespace std; + +int main() { + Asynco asynco; + asynco.run(2); + + Timer inter1 = asynco.periodic ([]() { + cout << "Interval 1" << endl; + }, 1000); + + // stop periodic + inter1.stop(); + + // how many times it has expired + int ti = inter1.ticks(); + + // is it stopped + bool stoped_i = inter1.stoped(); + + // start delayed + Timer time1 = asynco.delayed ( [] () { + cout << "Timeout 1 " << endl; + }, 10000); + + // stop delayed + time1.stop(); + + // is it expired + int tt = time1.expired(); + + // is it stopped + bool stoped_t = time1.stoped(); + + + asynco.join(); + return 0; +} \ No newline at end of file diff --git a/test/main_timers_default.cpp b/test/main_timers_default.cpp new file mode 100644 index 0000000..d6a3f82 --- /dev/null +++ b/test/main_timers_default.cpp @@ -0,0 +1,40 @@ +#include "../lib/asynco_default.hpp" +using namespace marcelb::asynco; + +#include +using namespace std; + + +int main() { + asynco_default_run(); + + Timer inter1 = periodic ([]() { + cout << "Interval 1" << endl; + }, 1000); + + // stop periodic + inter1.stop(); + + // how many times it has expired + int ti = inter1.ticks(); + + // is it stopped + bool stoped_i = inter1.stoped(); + + // start delayed + Timer time1 = delayed ( [] () { + cout << "Timeout 1 " << endl; + }, 10000); + + // stop delayed + time1.stop(); + + // is it expired + int tt = time1.expired(); + + // is it stopped + bool stoped_t = time1.stoped(); + + asynco_default_join(); + return 0; +} \ No newline at end of file diff --git a/test/main_trigger.cpp b/test/main_trigger.cpp new file mode 100644 index 0000000..bca139a --- /dev/null +++ b/test/main_trigger.cpp @@ -0,0 +1,124 @@ +#include "../lib/asynco.hpp" +using namespace marcelb::asynco; + +#include +using namespace std; + +Asynco asynco; + +class ClassWithTriggers { + Trigger emitter1; + Trigger emitter2; + +public: + ClassWithTriggers(): emitter1(asynco), emitter2(asynco) {} + + template + void on(const string& key, function callback) { + if constexpr (sizeof...(T) == 1 && is_same_v>, int>) { + emitter1.on(key, callback); + } + else if constexpr (sizeof...(T) == 1 && is_same_v>, string>) { + emitter2.on(key, callback); + } + } + + template + void tick(const string& key, Args&&... args) { + if constexpr (sizeof...(Args) == 1 && is_same_v>, int>) { + emitter1.tick(key, forward(args)...); + } + else if constexpr (sizeof...(Args) == 1 && is_same_v>, string>) { + emitter2.tick(key, forward(args)...); + } + else { + static_assert(sizeof...(Args) == 0, "Unsupported number or types of arguments"); + } + } +}; + +int main() { + asynco.run(2); + + /** + * initialization of typed events + */ + + Trigger ev2int = asynco.trigger(); + Trigger evintString = asynco.trigger(); + Trigger<> evoid = asynco.trigger<>(); + + + ev2int.on("sum", [](int a, int b) { + cout << "Sum " << a+b << endl; + }); + + evintString.on("substract", [](int a, string b) { + cout << "Substract " << a-stoi(b) << endl; + }); + + evoid.on("void", []() { + cout << "Void emited" << endl; + }); + + // multiple listeners + + string emited2 = "2"; + + evoid.on("void", [&]() { + cout << "Void emited " << emited2 << endl; + }); + + sleep(1); + + /** + * Emit + */ + + ev2int.tick("sum", 5, 8); + + sleep(1); + evintString.tick("substract", 3, to_string(2)); + + sleep(1); + evoid.tick("void"); + + // Turn off the event listener + + evoid.off("void"); + evoid.tick("void"); // nothing is happening + + + class myOwnClass : public Trigger { + public: + myOwnClass() : Trigger(asynco) {}; + }; + + myOwnClass myclass; + + Timer t = asynco.delayed( [&] { + myclass.tick("constructed", 1); + }, 200); + + myclass.on("constructed", [] (int i) { + cout << "Constructed " << i << endl; + }); + + + ClassWithTriggers mt; + + mt.on("int", function([&](int i) { + cout << "Emit int " << i << endl; + })); + + mt.on("string", function([&](string s) { + cout << "Emit string " << s << endl; + })); + + mt.tick("int", 5); + mt.tick("string", string("Hello world")); + + + asynco.join(); + return 0; +} \ No newline at end of file diff --git a/test/main_trigger_default.cpp b/test/main_trigger_default.cpp new file mode 100644 index 0000000..c4ebe6a --- /dev/null +++ b/test/main_trigger_default.cpp @@ -0,0 +1,118 @@ +#include "../lib/asynco_default.hpp" +using namespace marcelb::asynco; + +#include +using namespace std; + +class ClassWithTriggers { + Trigger emitter1; + Trigger emitter2; + +public: + ClassWithTriggers(): emitter1(asynco_default_runtime()), emitter2(asynco_default_runtime()) {} + + template + void on(const string& key, function callback) { + if constexpr (sizeof...(T) == 1 && is_same_v>, int>) { + emitter1.on(key, callback); + } + else if constexpr (sizeof...(T) == 1 && is_same_v>, string>) { + emitter2.on(key, callback); + } + } + + template + void tick(const string& key, Args&&... args) { + if constexpr (sizeof...(Args) == 1 && is_same_v>, int>) { + emitter1.tick(key, forward(args)...); + } + else if constexpr (sizeof...(Args) == 1 && is_same_v>, string>) { + emitter2.tick(key, forward(args)...); + } + else { + static_assert(sizeof...(Args) == 0, "Unsupported number or types of arguments"); + } + } +}; + +int main() { + asynco_default_run(); + + /** + * initialization of typed events + */ + + Trigger ev2int = trigger(); + Trigger evintString = trigger(); + Trigger<> evoid = trigger<>(); + + ev2int.on("sum", [](int a, int b) { + cout << "Sum " << a+b << endl; + }); + + evintString.on("substract", [](int a, string b) { + cout << "Substract " << a-stoi(b) << endl; + }); + + evoid.on("void", []() { + cout << "Void emited" << endl; + }); + + // multiple listeners + + string emited2 = "2"; + + evoid.on("void", [&]() { + cout << "Void emited " << emited2 << endl; + }); + + sleep(1); + + /** + * Emit + */ + + ev2int.tick("sum", 5, 8); + + sleep(1); + evintString.tick("substract", 3, to_string(2)); + + sleep(1); + evoid.tick("void"); + + // Turn off the event listener + + evoid.off("void"); + evoid.tick("void"); // nothing is happening + + class myOwnClass : public Trigger { + public: + myOwnClass() : Trigger(asynco_default_runtime()) {}; + }; + + myOwnClass myclass; + + Timer t = delayed( [&] { + myclass.tick("constructed", 1); + }, 200); + + myclass.on("constructed", [] (int i) { + cout << "Constructed " << i << endl; + }); + + ClassWithTriggers mt; + + mt.on("int", function([&](int i) { + cout << "Emit int " << i << endl; + })); + + mt.on("string", function([&](string s) { + cout << "Emit string " << s << endl; + })); + + mt.tick("int", 5); + mt.tick("string", string("Hello world")); + + asynco_default_join(); + return 0; +} \ No newline at end of file