Write examples and tests, refaktor, tested

This commit is contained in:
marcelb 2025-06-11 09:56:32 +02:00
parent e76623bef0
commit 748fd0a586
20 changed files with 704 additions and 853 deletions

View File

@ -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)

225
README.md
View File

@ -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<future<void>> 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<fut_vec.size(); i++) {
await_ (fut_vec[i]);
}
};
```
Just an example:
```c++
/**
* Sleep with delayed sleep implement
**/
void sleep_to (int _time) {
promise<void> _promise;
Delayed t( [&]() {
_promise.set_value();
}, _time);
return _promise.get_future().get();
}
sleep_to(3000);
/**
* Catch promise reject
*/
void promise_reject (int _time) {
promise<void> _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<int, int> ev2int;
Trigger<int, string> evintString;
Trigger<> evoid;
Trigger<int, int> ev2int = trigger<int, int>();
Trigger<int, string> evintString = trigger<int, string>();
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<int> {
public:
myOwnClass() : Trigger() {};
myOwnClass() : Trigger(asynco_default_runtime()) {};
};
myOwnClass myclass;
@ -340,6 +268,8 @@ class ClassWithTriggers {
Trigger<string> emitter2;
public:
ClassWithTriggers(): emitter1(asynco_default_runtime()), emitter2(asynco_default_runtime()) {}
template<typename... T>
void on(const string& key, function<void(T...)> callback) {
if constexpr (sizeof...(T) == 1 && is_same_v<tuple_element_t<0, tuple<T...>>, 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<T>`; if not, just use `boost::asio::awaitable<T>`.
@ -473,17 +361,8 @@ await_ ([]() -> asyncable<void> {
```
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

View File

@ -11,16 +11,15 @@
using namespace std;
#include <boost/asio.hpp>
using namespace boost::asio;
#include "timers.hpp"
#include "trigger.hpp"
#if __cplusplus >= 202002L
#include <boost/asio/awaitable.hpp>
#include <boost/asio/co_spawn.hpp>
#include <boost/asio/use_awaitable.hpp>
#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<class F, class... Args>
auto async(F&& f, Args&&... args) -> future<invoke_result_t<F, Args...>> {
cout << "async" << endl;
using return_type = invoke_result_t<F, Args...>;
future<return_type> res = io_ctx.post(boost::asio::use_future(bind(forward<F>(f), forward<Args>(args)...)));
return res;
@ -157,7 +154,7 @@ public:
template<typename... T>
Trigger<T...> trigger() {
return Trigger<T...>(this);
return Trigger<T...>(*this);
}

View File

@ -8,15 +8,12 @@ namespace asynco {
extern Asynco Asynco_Default_Runtime;
// Asynco& Asynco_Default_Runtime();
/**
* Run the function asynchronously
*/
template<class F, class... Args>
auto async_(F&& f, Args&&... args) -> future<invoke_result_t<F, Args...>> {
cout << "async_default" << endl;
return Asynco_Default_Runtime.async(bind(forward<F>(f), forward<Args>(args)...));
}
@ -104,6 +101,18 @@ Trigger<T...> 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();
}
}

View File

@ -25,10 +25,9 @@ class Trigger {
mutex m_eve;
unordered_map<string, vector<function<void(T...)>>> triggers;
Trigger(Asynco& _engine)
: engine(_engine) {}
public:
Trigger(Asynco& _engine)
: engine(_engine) {}
/**
* Defines event by key, and callback function

View File

@ -5,25 +5,25 @@ namespace marcelb::asynco {
void Asynco::init_loops_in_threads(uint8_t threads) {
for (int i=0; i<threads; i++) {
cout << "loops init " << endl;
_runners.push_back(thread ( [this] () {
io_ctx.run();
}));
}
}
// Asynco::Asynco(uint8_t threads){//:
// // _work(io_service::work(io_ctx)) {
// run(threads);
// }
void Asynco::run(uint8_t threads) {
_work = make_unique<io_service::work>(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_service::work>(io_ctx);
}
io_ctx.run();
}
void Asynco::join() {
for (auto& runner : _runners) {
runner.join();

View File

@ -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<void()> callback, uint64_t time) {
return Timer(Asynco_Default_Runtime.io_ctx, callback, time, TimerType::Delayed);
}
@ -18,4 +13,24 @@ Timer periodic(function<void()> 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;
}
};

View File

@ -34,7 +34,6 @@ Timer::Timer (io_context& _io_ctx, function<void()> _callback, uint64_t _time, T
type(_type),
callback(_callback),
time(_time) {
cout << "Timer" << endl;
init();
}

View File

@ -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)
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)

View File

@ -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 <iostream>
#include <unistd.h>
#include <thread>
#include <future>
#include <vector>
using namespace std;
using namespace this_thread;
// asyncable<int> c2 (int a) {
// co_return a*2;
// }
// asyncable<void> sleep_co (int a) {
// sleep(a);
// cout << "Gotov" << endl;
// co_return;
// }
// asyncable<void> c () {
// cout << "Ispisi" << endl;
// co_await c2(0);
// co_return;
// }
// void sleep_to (int _time) {
// promise<void> _promise;
// Delayed t( [&]() {
// _promise.set_value();
// }, _time);
// return _promise.get_future().get();
// }
// void sleep_to (int _time) {
// promise<void> _promise;
// Delayed t( [&]() {
// _promise.set_value();
// }, _time);
// await_ (_promise.get_future(), 100);
// }
// future<void> sleep_to (int _time) {
// promise<void> _promise;
// future<void> _future = _promise.get_future();
// Delayed t( [&]() {
// _promise.set_value();
// }, _time);
// return _future;
// }
// void promise_reject (int _time) {
// promise<void> _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<int> {
// public:
// myOwnClass() : Trigger() {};
// };
// // ----------------- MULTIPLE TRIGGERS IN ONE CLASS ------------------
// class ClassWithTriggers {
// Trigger<int> emitter1;
// Trigger<string> emitter2;
// public:
// template<typename... T>
// void on(const string& key, function<void(T...)> callback) {
// if constexpr (sizeof...(T) == 1 && is_same_v<tuple_element_t<0, tuple<T...>>, int>) {
// emitter1.on(key, callback);
// }
// else if constexpr (sizeof...(T) == 1 && is_same_v<tuple_element_t<0, tuple<T...>>, string>) {
// emitter2.on(key, callback);
// }
// }
// template <typename... Args>
// void tick(const string& key, Args&&... args) {
// if constexpr (sizeof...(Args) == 1 && is_same_v<tuple_element_t<0, tuple<Args...>>, int>) {
// emitter1.tick(key, forward<Args>(args)...);
// }
// else if constexpr (sizeof...(Args) == 1 && is_same_v<tuple_element_t<0, tuple<Args...>>, string>) {
// emitter2.tick(key, forward<Args>(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<future<void>> 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<fut_vec.size(); i++) {
// await_ (fut_vec[i]);
// }
// };
// await_all2();
// // --------------- EVENTS -------------------
// /**
// * initialization of typed events
// */
// Trigger<int, int> ev2int;
// Trigger<int, string> 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>("int", function<void(int)>([&](int i) {
// cout << "Emit int " << i << endl;
// }));
// mt.on<string>("string", function<void(string)>([&](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<int> {
// cout << "aaaa" << endl;
// co_return 5;
// });
// auto i = async_ (retint());
// auto i_ = await_(i);
// cout << i_ << endl;
// Periodic a( []() -> asyncable<void> {
// cout << "corutina" << endl;
// // co_await retint();
// }, 2000);
// Periodic b_( []() {
// cout << "funckija" << endl;
// }, 2000);
// Trigger<int, int> ev2int;
// Trigger<int, string> evintString;
// Trigger<> evoid;
// ev2int.on("sum", [](int a, int b) -> asyncable<void> {
// cout << "Sum " << a+b << endl;
// });
// ev2int.on("sum", [](int a, int b) -> asyncable<void> {
// cout << "Sum done" << endl;
// });
// evintString.on("substract", [](int a, string b) -> asyncable<void> {
// cout << "Substract " << a-stoi(b) << endl;
// });
// evoid.on("void", []() {
// auto a = await_ (async_ (c2(34)));
// cout << "A " << a << endl;
// });
// auto c1 = []() -> asyncable<void> {
// cout << "Roge " << endl;
// co_return;
// };
// auto a = await_ ( c2(3));
// cout << a << endl;
// await_ ([]() -> asyncable<void> {
// cout << "Hello" << endl;
// co_await c2(4);
// co_return;
// }());
// async_ ([]() -> asyncable<void> {
// cout << "1" << endl;
// co_await sleep_co(1);
// co_return;
// }());
// async_ ([]() -> asyncable<void> {
// cout << "2" << endl;
// co_await sleep_co(1);
// co_return;
// }());
// async_ ([]() -> asyncable<void> {
// cout << "3" << endl;
// co_await sleep_co(1);
// co_return;
// }());
// async_ ([]() -> asyncable<void> {
// cout << "4" << endl;
// co_await sleep_co(1);
// co_return;
// }());
// async_ ([]() -> asyncable<void> {
// 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<void> {
// cout << "Baba roga" << endl;
// co_await c1();
// }));
// string emited2 = "2";
// evoid.on("void", [&]() -> asyncable<void> {
// cout << "Void emited " << emited2 << endl;
// });
// evoid.tick("void");
// vector<future<void>> 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;
}

84
test/main_async.cpp Normal file
View File

@ -0,0 +1,84 @@
#include "../lib/asynco.hpp"
using namespace marcelb::asynco;
#include <iostream>
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<void> _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;
}

View File

@ -0,0 +1,82 @@
#include "../lib/asynco_default.hpp"
using namespace marcelb::asynco;
#include <iostream>
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<void> _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;
}

42
test/main_coroutine.cpp Normal file
View File

@ -0,0 +1,42 @@
#include "../lib/asynco.hpp"
using namespace marcelb::asynco;
#include <iostream>
using namespace std;
int main() {
Asynco asynco; // or global
asynco.run(2);
asyncable<int> c2(int a) {
co_return a * 2;
}
asynco.async(c2(4));
asynco.async([]() -> asyncable<void> {
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<void> {
cout << "Hello" << endl;
co_return;
}());
asynco.join();
return 0;
}

View File

@ -0,0 +1,40 @@
#include "../lib/asynco_default.hpp"
using namespace marcelb::asynco;
#include <iostream>
using namespace std;
int main() {
asynco_default_run();
asyncable<int> c2(int a) {
co_return a * 2;
}
async_(c2(4));
async_([]() -> asyncable<void> {
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<void> {
cout << "Hello" << endl;
co_return;
}());
asynco_default_join();
return 0;
}

View File

@ -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;
}

View File

@ -9,10 +9,7 @@ int main() {
Asynco asynco;
asynco.run(2);
auto interval = asynco.periodic([](){
cout << "idemo" << endl;
}, 1000);
// code
asynco.join();
return 0;

41
test/main_timers.cpp Normal file
View File

@ -0,0 +1,41 @@
#include "../lib/asynco.hpp"
using namespace marcelb::asynco;
#include <iostream>
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;
}

View File

@ -0,0 +1,40 @@
#include "../lib/asynco_default.hpp"
using namespace marcelb::asynco;
#include <iostream>
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;
}

124
test/main_trigger.cpp Normal file
View File

@ -0,0 +1,124 @@
#include "../lib/asynco.hpp"
using namespace marcelb::asynco;
#include <iostream>
using namespace std;
Asynco asynco;
class ClassWithTriggers {
Trigger<int> emitter1;
Trigger<string> emitter2;
public:
ClassWithTriggers(): emitter1(asynco), emitter2(asynco) {}
template<typename... T>
void on(const string& key, function<void(T...)> callback) {
if constexpr (sizeof...(T) == 1 && is_same_v<tuple_element_t<0, tuple<T...>>, int>) {
emitter1.on(key, callback);
}
else if constexpr (sizeof...(T) == 1 && is_same_v<tuple_element_t<0, tuple<T...>>, string>) {
emitter2.on(key, callback);
}
}
template <typename... Args>
void tick(const string& key, Args&&... args) {
if constexpr (sizeof...(Args) == 1 && is_same_v<tuple_element_t<0, tuple<Args...>>, int>) {
emitter1.tick(key, forward<Args>(args)...);
}
else if constexpr (sizeof...(Args) == 1 && is_same_v<tuple_element_t<0, tuple<Args...>>, string>) {
emitter2.tick(key, forward<Args>(args)...);
}
else {
static_assert(sizeof...(Args) == 0, "Unsupported number or types of arguments");
}
}
};
int main() {
asynco.run(2);
/**
* initialization of typed events
*/
Trigger<int, int> ev2int = asynco.trigger<int, int>();
Trigger<int, string> evintString = asynco.trigger<int, string>();
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<int> {
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>("int", function<void(int)>([&](int i) {
cout << "Emit int " << i << endl;
}));
mt.on<string>("string", function<void(string)>([&](string s) {
cout << "Emit string " << s << endl;
}));
mt.tick("int", 5);
mt.tick("string", string("Hello world"));
asynco.join();
return 0;
}

View File

@ -0,0 +1,118 @@
#include "../lib/asynco_default.hpp"
using namespace marcelb::asynco;
#include <iostream>
using namespace std;
class ClassWithTriggers {
Trigger<int> emitter1;
Trigger<string> emitter2;
public:
ClassWithTriggers(): emitter1(asynco_default_runtime()), emitter2(asynco_default_runtime()) {}
template<typename... T>
void on(const string& key, function<void(T...)> callback) {
if constexpr (sizeof...(T) == 1 && is_same_v<tuple_element_t<0, tuple<T...>>, int>) {
emitter1.on(key, callback);
}
else if constexpr (sizeof...(T) == 1 && is_same_v<tuple_element_t<0, tuple<T...>>, string>) {
emitter2.on(key, callback);
}
}
template <typename... Args>
void tick(const string& key, Args&&... args) {
if constexpr (sizeof...(Args) == 1 && is_same_v<tuple_element_t<0, tuple<Args...>>, int>) {
emitter1.tick(key, forward<Args>(args)...);
}
else if constexpr (sizeof...(Args) == 1 && is_same_v<tuple_element_t<0, tuple<Args...>>, string>) {
emitter2.tick(key, forward<Args>(args)...);
}
else {
static_assert(sizeof...(Args) == 0, "Unsupported number or types of arguments");
}
}
};
int main() {
asynco_default_run();
/**
* initialization of typed events
*/
Trigger<int, int> ev2int = trigger<int, int>();
Trigger<int, string> evintString = trigger<int, string>();
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<int> {
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>("int", function<void(int)>([&](int i) {
cout << "Emit int " << i << endl;
}));
mt.on<string>("string", function<void(string)>([&](string s) {
cout << "Emit string " << s << endl;
}));
mt.tick("int", 5);
mt.tick("string", string("Hello world"));
asynco_default_join();
return 0;
}