Compare commits
No commits in common. "105c15b06bd77e65842a2201f54b28e761158b6a" and "b123e9305d6275d0cc9f2c3365dfcb131d07b062" have entirely different histories.
105c15b06b
...
b123e9305d
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,2 +1 @@
|
|||||||
test/test
|
test/test
|
||||||
test/*.txt
|
|
46
.vscode/settings.json
vendored
46
.vscode/settings.json
vendored
@ -25,50 +25,6 @@
|
|||||||
"future": "cpp",
|
"future": "cpp",
|
||||||
"*.ipp": "cpp",
|
"*.ipp": "cpp",
|
||||||
"bitset": "cpp",
|
"bitset": "cpp",
|
||||||
"algorithm": "cpp",
|
"algorithm": "cpp"
|
||||||
"string": "cpp",
|
|
||||||
"string_view": "cpp",
|
|
||||||
"fstream": "cpp",
|
|
||||||
"cctype": "cpp",
|
|
||||||
"clocale": "cpp",
|
|
||||||
"cmath": "cpp",
|
|
||||||
"csignal": "cpp",
|
|
||||||
"cstdarg": "cpp",
|
|
||||||
"cstddef": "cpp",
|
|
||||||
"cstdio": "cpp",
|
|
||||||
"cstdlib": "cpp",
|
|
||||||
"cstring": "cpp",
|
|
||||||
"ctime": "cpp",
|
|
||||||
"cwctype": "cpp",
|
|
||||||
"any": "cpp",
|
|
||||||
"bit": "cpp",
|
|
||||||
"*.tcc": "cpp",
|
|
||||||
"codecvt": "cpp",
|
|
||||||
"compare": "cpp",
|
|
||||||
"complex": "cpp",
|
|
||||||
"concepts": "cpp",
|
|
||||||
"cstdint": "cpp",
|
|
||||||
"list": "cpp",
|
|
||||||
"map": "cpp",
|
|
||||||
"set": "cpp",
|
|
||||||
"iterator": "cpp",
|
|
||||||
"memory": "cpp",
|
|
||||||
"memory_resource": "cpp",
|
|
||||||
"numeric": "cpp",
|
|
||||||
"optional": "cpp",
|
|
||||||
"random": "cpp",
|
|
||||||
"system_error": "cpp",
|
|
||||||
"iomanip": "cpp",
|
|
||||||
"istream": "cpp",
|
|
||||||
"limits": "cpp",
|
|
||||||
"numbers": "cpp",
|
|
||||||
"semaphore": "cpp",
|
|
||||||
"sstream": "cpp",
|
|
||||||
"stop_token": "cpp",
|
|
||||||
"streambuf": "cpp",
|
|
||||||
"cinttypes": "cpp",
|
|
||||||
"typeindex": "cpp",
|
|
||||||
"typeinfo": "cpp",
|
|
||||||
"variant": "cpp"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
112
README.md
112
README.md
@ -11,27 +11,24 @@ A C++ library for event-driven asynchronous multi-threaded programming.
|
|||||||
- Asynchronous programming
|
- Asynchronous programming
|
||||||
- Multithread
|
- Multithread
|
||||||
- Asynchronous timer functions: interval, timeout
|
- Asynchronous timer functions: interval, timeout
|
||||||
- Typed events (on, emit, off)
|
- Typed events (on, emit)
|
||||||
- Event loops
|
- Event loops
|
||||||
- Multiple parallel execution loops
|
- Parallel execution loops
|
||||||
- Asynchronous file IO
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Just download the latest release and unzip it into your project.
|
Just download the latest release and unzip it into your project.
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
#define NUM_OF_RUNNERS 8 // To change the number of threads used by atask, without this it runs according to the number of cores
|
#include "asynco/lib/asynco.hpp" // asynco(), wait()
|
||||||
|
#include "asynco/lib/event.hpp" // event
|
||||||
#include "asynco/lib/asynco.hpp" // atask(), wait()
|
#include "asynco/lib/rotor.hpp" // interval, timeout
|
||||||
#include "asynco/lib/event.hpp" // event
|
#include "asynco/lib/runner.hpp" // on_async
|
||||||
#include "asynco/lib/rotor.hpp" // interval, timeout
|
|
||||||
#include "asynco/lib/runner.hpp" // for own loop
|
|
||||||
#include "asynco/lib/filesystem.hpp" // for async read and write files
|
|
||||||
|
|
||||||
using namespace marcelb;
|
using namespace marcelb;
|
||||||
using namespace asynco;
|
|
||||||
using namespace events;
|
|
||||||
|
|
||||||
|
#ifndef ON_RUNNER
|
||||||
|
#define ON_RUNNER
|
||||||
|
runner on_async;
|
||||||
|
#endif
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
@ -59,12 +56,27 @@ Make functions asynchronous
|
|||||||
|
|
||||||
```c++
|
```c++
|
||||||
/**
|
/**
|
||||||
* Run an lambda function asynchronously
|
* Put task directly and get returned value - it is not recommended to use it
|
||||||
*/
|
*/
|
||||||
|
|
||||||
atask( []() {
|
auto res1 = on_async.put_task( [] () {
|
||||||
|
cout << "Not except " <<endl;
|
||||||
|
throw string ("Is except!");
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
res1.get();
|
||||||
|
} catch (const string except) {
|
||||||
|
cout << except << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run an lambda function asyncronic
|
||||||
|
*/
|
||||||
|
|
||||||
|
asynco( []() {
|
||||||
sleep_for(2s); // only for simulating long duration function
|
sleep_for(2s); // only for simulating long duration function
|
||||||
cout << "atask" << endl;
|
cout << "asynco" << endl;
|
||||||
return 5;
|
return 5;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -77,7 +89,7 @@ void notLambdaFunction() {
|
|||||||
cout << "Call to not lambda function" << endl;
|
cout << "Call to not lambda function" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
atask (notLambdaFunction);
|
asynco (notLambdaFunction);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run class method
|
* Run class method
|
||||||
@ -91,7 +103,7 @@ class clm {
|
|||||||
};
|
};
|
||||||
|
|
||||||
clm classes;
|
clm classes;
|
||||||
atask( [&classes] () {
|
asynco( [&classes] () {
|
||||||
classes.classMethode();
|
classes.classMethode();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -101,19 +113,19 @@ atask( [&classes] () {
|
|||||||
* Wait after runned as async
|
* Wait after runned as async
|
||||||
*/
|
*/
|
||||||
|
|
||||||
auto a = atask( []() {
|
auto a = asynco( []() {
|
||||||
sleep_for(2s); // only for simulating long duration function
|
sleep_for(2s); // only for simulating long duration function
|
||||||
cout << "atask" << endl;
|
cout << "asynco" << endl;
|
||||||
return 5;
|
return 5;
|
||||||
});
|
});
|
||||||
|
|
||||||
cout << wait(a) << endl;
|
cout << wait(move(a)) << endl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wait async function call and use i cout
|
* Wait async function call and use i cout
|
||||||
*/
|
*/
|
||||||
|
|
||||||
cout << wait(atask( [] () {
|
cout << wait(asynco( [] () {
|
||||||
sleep_for(chrono::seconds(1)); // only for simulating long duration function
|
sleep_for(chrono::seconds(1)); // only for simulating long duration function
|
||||||
cout << "wait end" << endl;
|
cout << "wait end" << endl;
|
||||||
return 4;
|
return 4;
|
||||||
@ -182,14 +194,6 @@ evoid.on("void", []() {
|
|||||||
cout << "Void emited" << endl;
|
cout << "Void emited" << endl;
|
||||||
});
|
});
|
||||||
|
|
||||||
// multiple listeners
|
|
||||||
|
|
||||||
string emited2 = "2";
|
|
||||||
|
|
||||||
evoid.on("void", [&]() {
|
|
||||||
cout << "Void emited " << emited2 << endl;
|
|
||||||
});
|
|
||||||
|
|
||||||
sleep(1);
|
sleep(1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -203,12 +207,6 @@ evintString.emit("substract", 3, to_string(2));
|
|||||||
|
|
||||||
sleep(1);
|
sleep(1);
|
||||||
evoid.emit("void");
|
evoid.emit("void");
|
||||||
|
|
||||||
// Turn off the event listener
|
|
||||||
|
|
||||||
evoid.off("void");
|
|
||||||
evoid.emit("void"); // nothing is happening
|
|
||||||
|
|
||||||
```
|
```
|
||||||
Extend own class whit events
|
Extend own class whit events
|
||||||
|
|
||||||
@ -229,48 +227,6 @@ myclass.on("constructed", [] (int i) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
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 = wait(future_data);
|
|
||||||
} catch (exception& err) {
|
|
||||||
cout << err.what() << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto future_status = fs::write("test.txt", "Hello world");
|
|
||||||
|
|
||||||
try {
|
|
||||||
wait(future_status);
|
|
||||||
} catch (exception& err) {
|
|
||||||
cout << err.what() << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
[APACHE 2.0](http://www.apache.org/licenses/LICENSE-2.0/)
|
[APACHE 2.0](http://www.apache.org/licenses/LICENSE-2.0/)
|
||||||
|
@ -6,16 +6,20 @@
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
namespace marcelb {
|
namespace marcelb {
|
||||||
namespace asynco {
|
|
||||||
|
#ifndef ON_RUNNER
|
||||||
|
#define ON_RUNNER
|
||||||
|
runner on_async;
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run the function asynchronously
|
* Run the function asynchronously
|
||||||
*/
|
*/
|
||||||
template<class F, class... Args>
|
template<class F, class... Args>
|
||||||
auto atask(F&& f, Args&&... args) -> future<typename result_of<F(Args...)>::type> {
|
auto asynco(F&& f, Args&&... args) -> future<typename result_of<F(Args...)>::type> {
|
||||||
using return_type = typename result_of<F(Args...)>::type;
|
using return_type = typename result_of<F(Args...)>::type;
|
||||||
|
|
||||||
future<return_type> res = _asyncon.put_task(bind(forward<F>(f), forward<Args>(args)...));
|
future<return_type> res = on_async.put_task(bind(forward<F>(f), forward<Args>(args)...));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,19 +27,10 @@ auto atask(F&& f, Args&&... args) -> future<typename result_of<F(Args...)>::type
|
|||||||
* Block until the asynchronous call completes
|
* Block until the asynchronous call completes
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T wait(future<T>& r) {
|
T wait(future<T> r) {
|
||||||
return r.get();
|
return r.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Block until the asynchronous call completes
|
|
||||||
*/
|
|
||||||
template<typename T>
|
|
||||||
T wait(future<T>&& r) {
|
|
||||||
return move(r).get();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include "runner.hpp"
|
#include "runner.hpp"
|
||||||
@ -11,8 +10,11 @@
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
namespace marcelb {
|
namespace marcelb {
|
||||||
namespace asynco {
|
|
||||||
namespace events {
|
#ifndef ON_RUNNER
|
||||||
|
#define ON_RUNNER
|
||||||
|
runner on_async;
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event class, for event-driven programming.
|
* Event class, for event-driven programming.
|
||||||
@ -21,8 +23,7 @@ namespace events {
|
|||||||
template<typename... T>
|
template<typename... T>
|
||||||
class event {
|
class event {
|
||||||
private:
|
private:
|
||||||
mutex m_eve;
|
unordered_map<string, function<void(T...)>> events;
|
||||||
unordered_map<string, vector<function<void(T...)>>> events;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -30,8 +31,7 @@ class event {
|
|||||||
* Defines event by key, and callback function
|
* Defines event by key, and callback function
|
||||||
*/
|
*/
|
||||||
void on(const string& key, function<void(T...)> callback) {
|
void on(const string& key, function<void(T...)> callback) {
|
||||||
lock_guard _off(m_eve);
|
events[key] = callback;
|
||||||
events[key].push_back(callback);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -39,28 +39,16 @@ class event {
|
|||||||
*/
|
*/
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
void emit(const string& key, Args... args) {
|
void emit(const string& key, Args... args) {
|
||||||
auto it_eve = events.find(key);
|
auto it = events.find(key);
|
||||||
if (it_eve != events.end()) {
|
if (it != events.end()) {
|
||||||
for (uint i =0; i<it_eve->second.size(); i++) {
|
auto callback = bind(it->second, forward<Args>(args)...);
|
||||||
auto callback = bind(it_eve->second[i], forward<Args>(args)...);
|
on_async.put_task(callback);
|
||||||
_asyncon.put_task(callback);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove an event listener from an event
|
|
||||||
*/
|
|
||||||
void off(const string& key) {
|
|
||||||
lock_guard _off(m_eve);
|
|
||||||
events.erase(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -1,116 +0,0 @@
|
|||||||
#ifndef _ASYNCO_FS_
|
|
||||||
#define _ASYNCO_FS_
|
|
||||||
|
|
||||||
#include "asynco.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace marcelb;
|
|
||||||
using namespace asynco;
|
|
||||||
|
|
||||||
namespace marcelb {
|
|
||||||
namespace asynco {
|
|
||||||
namespace fs {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Asynchronous file reading with callback after read complete
|
|
||||||
*/
|
|
||||||
template<typename Callback>
|
|
||||||
void read(string path, Callback&& callback) {
|
|
||||||
async( [&path, callback] () {
|
|
||||||
string content;
|
|
||||||
try {
|
|
||||||
string line;
|
|
||||||
ifstream file (path);
|
|
||||||
if (file.is_open()) {
|
|
||||||
line.clear();
|
|
||||||
while ( getline (file,line) ) {
|
|
||||||
content += line + "\n";
|
|
||||||
}
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
|
||||||
throw runtime_error("Unable to open file");
|
|
||||||
}
|
|
||||||
|
|
||||||
callback(content, nullptr);
|
|
||||||
} catch(exception& error) {
|
|
||||||
callback(content, &error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Asynchronous file reading
|
|
||||||
*/
|
|
||||||
future<string> read(string path) {
|
|
||||||
return async( [&path] () {
|
|
||||||
string content;
|
|
||||||
string line;
|
|
||||||
ifstream file (path);
|
|
||||||
if (file.is_open()) {
|
|
||||||
line.clear();
|
|
||||||
while ( getline (file,line) ) {
|
|
||||||
content += line + "\n";
|
|
||||||
}
|
|
||||||
file.close();
|
|
||||||
return content;
|
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
|
||||||
throw runtime_error("Unable to open file");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Asynchronous file writing with callback after write complete
|
|
||||||
*/
|
|
||||||
template<typename Callback>
|
|
||||||
void write(string path, string content, Callback&& callback) {
|
|
||||||
async( [&path, &content, callback] () {
|
|
||||||
try {
|
|
||||||
ofstream file (path);
|
|
||||||
if (file.is_open()) {
|
|
||||||
file << content;
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw runtime_error("Unable to open file");
|
|
||||||
}
|
|
||||||
|
|
||||||
callback(nullptr);
|
|
||||||
} catch(exception& error) {
|
|
||||||
callback(&error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Asynchronous file writing with callback after write complete
|
|
||||||
*/
|
|
||||||
future<void> write(string path, string content) {
|
|
||||||
return async( [&path, &content] () {
|
|
||||||
ofstream file (path);
|
|
||||||
if (file.is_open()) {
|
|
||||||
file << content;
|
|
||||||
file.close();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw runtime_error("Unable to open file");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
310
lib/rotor.hpp
310
lib/rotor.hpp
@ -3,16 +3,18 @@
|
|||||||
|
|
||||||
#include "runner.hpp"
|
#include "runner.hpp"
|
||||||
#include "chrono"
|
#include "chrono"
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "iostream"
|
#include "iostream"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace marcelb;
|
using namespace marcelb;
|
||||||
using namespace asynco;
|
|
||||||
|
#ifndef ON_RUNNER
|
||||||
|
#define ON_RUNNER
|
||||||
|
runner on_async;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace marcelb {
|
namespace marcelb {
|
||||||
namespace asynco {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the time in ms from the epoch
|
* Get the time in ms from the epoch
|
||||||
@ -24,39 +26,152 @@ int64_t rtime_ms() {
|
|||||||
.count();
|
.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t rtime_us() {
|
|
||||||
return chrono::duration_cast<chrono::microseconds>(chrono::system_clock::now()
|
|
||||||
.time_since_epoch())
|
|
||||||
.count();
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Intern class for timer async loop
|
* Structure for time events
|
||||||
*/
|
*/
|
||||||
class timer_core {
|
|
||||||
public:
|
struct time_event {
|
||||||
mutex hangon;
|
|
||||||
function<void()> callback;
|
function<void()> callback;
|
||||||
int64_t init;
|
int64_t init;
|
||||||
int64_t time;
|
int64_t time;
|
||||||
bool repeat;
|
bool repeat;
|
||||||
bool stop;
|
bool stop;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event loop for time events
|
||||||
|
*/
|
||||||
|
|
||||||
|
class rotor {
|
||||||
|
vector<struct time_event *> tevents;
|
||||||
|
mutex te_m;
|
||||||
|
bool rotating = true;
|
||||||
|
int64_t sampling;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loop method, started by the constructor in a separate runner
|
||||||
|
* It checks the events on the stack and sends the expired ones to the runner
|
||||||
|
*/
|
||||||
|
void loop() {
|
||||||
|
while (rotating) {
|
||||||
|
for (int i=0; i<tevents.size(); i++) {
|
||||||
|
|
||||||
|
if (tevents[i]->stop) {
|
||||||
|
remove(i);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (expired(tevents[i])) {
|
||||||
|
on_async.put_task(tevents[i]->callback);
|
||||||
|
if (tevents[i]->repeat) {
|
||||||
|
tevents[i]->init = rtime_ms();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
remove(i);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this_thread::sleep_for(chrono::milliseconds(sampling));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The method checks whether the time event has expired
|
||||||
|
*/
|
||||||
|
bool expired(struct time_event *tevent) {
|
||||||
|
return rtime_ms() - tevent->init >= tevent->time;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The method deletes a non-repeating or stopped event from the stack
|
||||||
|
*/
|
||||||
|
void remove(const int& position) {
|
||||||
|
lock_guard<mutex> lock(te_m);
|
||||||
|
tevents.erase(tevents.begin()+position);
|
||||||
|
update_sampling();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the idle time of the loop, according to twice the frequency of available events
|
||||||
|
*/
|
||||||
|
void update_sampling() {
|
||||||
|
if (tevents.empty()) {
|
||||||
|
sampling = 100;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sampling = tevents[0]->time;
|
||||||
|
for (int i=0; i<tevents.size(); i++) {
|
||||||
|
if (sampling > tevents[i]->time) {
|
||||||
|
sampling = tevents[i]->time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sampling /= tevents.size()*2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for the rotor, starts the given loop by occupying one runner
|
||||||
|
*/
|
||||||
|
rotor() {
|
||||||
|
on_async.put_task( [&] () {
|
||||||
|
loop();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a time event to the stack
|
||||||
|
*/
|
||||||
|
void insert(struct time_event *tevent) {
|
||||||
|
lock_guard<mutex> lock(te_m);
|
||||||
|
tevents.push_back(tevent);
|
||||||
|
update_sampling();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of active events
|
||||||
|
*/
|
||||||
|
int active() {
|
||||||
|
return tevents.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops all active events and stops the rotor
|
||||||
|
*/
|
||||||
|
~rotor() {
|
||||||
|
for (int i=0; i<tevents.size(); i++) {
|
||||||
|
tevents[i]->stop = true;
|
||||||
|
}
|
||||||
|
rotating = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* It is intended that there is only one global declaration
|
||||||
|
*/
|
||||||
|
rotor _rotor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class for all timer functions
|
||||||
|
*/
|
||||||
|
class timer_core {
|
||||||
|
public:
|
||||||
|
struct time_event t_event;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Timer constructor, receives a callback function and time
|
* Timer constructor, receives a callback function and time
|
||||||
*/
|
*/
|
||||||
timer_core( function<void()> _callback, int64_t _time, bool _repeat):
|
timer_core( function<void()> _callback, int64_t _time):
|
||||||
callback(_callback), init(rtime_us()), time(_time*1000), repeat(_repeat), stop(false) {
|
t_event({ _callback, rtime_ms(), _time, false, false }) {
|
||||||
}
|
|
||||||
|
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Stop timer
|
* Stop timer
|
||||||
*/
|
*/
|
||||||
void clear() {
|
void clear() {
|
||||||
lock_guard<mutex> hang(hangon);
|
t_event.stop = true;
|
||||||
stop = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -67,173 +182,36 @@ class timer_core {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Event loop for time events
|
|
||||||
*/
|
|
||||||
|
|
||||||
class rotor {
|
|
||||||
vector<shared_ptr<timer_core>> tcores;
|
|
||||||
mutex te_m;
|
|
||||||
bool rotating = true;
|
|
||||||
int64_t sampling;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loop method, started by the constructor in a separate runner
|
|
||||||
* It checks the events on the stack and sends the expired ones to the runner
|
|
||||||
*/
|
|
||||||
void loop() {
|
|
||||||
while (rotating) {
|
|
||||||
for (int i=0; i<tcores.size(); i++) {
|
|
||||||
|
|
||||||
if (tcores[i]->stop) {
|
|
||||||
remove(i);
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (expired(tcores[i])) {
|
|
||||||
_asyncon.put_task(tcores[i]->callback);
|
|
||||||
if (tcores[i]->repeat) {
|
|
||||||
tcores[i]->init = rtime_us();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
remove(i);
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this_thread::sleep_for(chrono::microseconds(sampling));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The method checks whether the time event has expired
|
|
||||||
*/
|
|
||||||
bool expired(shared_ptr<timer_core> tcore) {
|
|
||||||
return rtime_us() - tcore->init >= tcore->time;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The method deletes a non-repeating or stopped event from the stack
|
|
||||||
*/
|
|
||||||
void remove(const int& position) {
|
|
||||||
lock_guard<mutex> lock(te_m);
|
|
||||||
tcores.erase(tcores.begin()+position);
|
|
||||||
update_sampling();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the idle time of the loop, according to twice the frequency of available events
|
|
||||||
*/
|
|
||||||
void update_sampling() {
|
|
||||||
if (tcores.empty()) {
|
|
||||||
sampling = 100;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sampling = tcores[0]->time;
|
|
||||||
for (int i=0; i<tcores.size(); i++) {
|
|
||||||
if (sampling > tcores[i]->time) {
|
|
||||||
sampling = tcores[i]->time;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sampling /= tcores.size()*2;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for the rotor, starts the given loop by occupying one runner
|
|
||||||
*/
|
|
||||||
rotor() {
|
|
||||||
_asyncon.put_task( [&] () {
|
|
||||||
loop();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a time event to the stack
|
|
||||||
*/
|
|
||||||
void insert(shared_ptr<timer_core> tcore) {
|
|
||||||
lock_guard<mutex> lock(te_m);
|
|
||||||
tcores.push_back(tcore);
|
|
||||||
update_sampling();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the number of active events
|
|
||||||
*/
|
|
||||||
int active() {
|
|
||||||
return tcores.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stops all active events and stops the rotor
|
|
||||||
*/
|
|
||||||
~rotor() {
|
|
||||||
for (int i=0; i<tcores.size(); i++) {
|
|
||||||
tcores[i]->clear();
|
|
||||||
}
|
|
||||||
rotating = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* It is intended that there is only one global declaration
|
|
||||||
*/
|
|
||||||
static rotor _rotor;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Core class for pure async timer functions
|
|
||||||
*/
|
|
||||||
|
|
||||||
class _timer_intern {
|
|
||||||
shared_ptr<timer_core> tcore;
|
|
||||||
public:
|
|
||||||
|
|
||||||
_timer_intern(function<void()> _callback, int64_t _time, bool repeat) {
|
|
||||||
tcore = make_shared<timer_core>(_callback, _time, repeat);
|
|
||||||
_rotor.insert(tcore);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stop interval
|
|
||||||
*/
|
|
||||||
void clear() {
|
|
||||||
tcore->clear();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class interval for periodic execution of the callback in time in ms
|
* Class interval for periodic execution of the callback in time in ms
|
||||||
*/
|
*/
|
||||||
class interval : public _timer_intern {
|
class interval : public timer_core {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The constructor receives a callback function and an interval time
|
* The constructor receives a callback function and an interval time
|
||||||
*/
|
*/
|
||||||
interval( function<void()> _callback, int64_t _time):
|
interval( function<void()> _callback, int64_t _time): timer_core(_callback, _time) {
|
||||||
_timer_intern(_callback, _time, true) {
|
t_event.repeat = true;
|
||||||
|
_rotor.insert(&t_event);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class interval for delayed callback execution in ms
|
* Class interval for delayed callback execution in ms
|
||||||
*/
|
*/
|
||||||
class timeout : public _timer_intern {
|
class timeout : public timer_core {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The constructor receives a callback function and a delay time
|
* The constructor receives a callback function and a delay time
|
||||||
*/
|
*/
|
||||||
timeout( function<void()> _callback, int64_t delay):
|
timeout( function<void()> _callback, int64_t delay): timer_core(_callback, delay) {
|
||||||
_timer_intern(_callback, delay, false) {
|
t_event.repeat = false;
|
||||||
|
_rotor.insert(&t_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -12,9 +12,10 @@
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
namespace marcelb {
|
namespace marcelb {
|
||||||
namespace asynco {
|
|
||||||
|
|
||||||
#define HW_CONCURRENCY_MINIMAL 4
|
#ifdef ON_RUNNER
|
||||||
|
extern runner on_async;
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The runner class implements multithread, task stack and event loop for asynchronous execution of tasks
|
* The runner class implements multithread, task stack and event loop for asynchronous execution of tasks
|
||||||
@ -26,29 +27,12 @@ class runner {
|
|||||||
mutex q_io;
|
mutex q_io;
|
||||||
condition_variable cv;
|
condition_variable cv;
|
||||||
bool stop;
|
bool stop;
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The constructor starts as many threads as the system has cores,
|
* Increase number of runners
|
||||||
* and runs an event loop inside each one.
|
|
||||||
* Each event loop waits for tasks from the stack and executes them.
|
|
||||||
*/
|
*/
|
||||||
runner(unsigned int _num_of_runners = 0) : stop(false) {
|
void increase_runners(unsigned int increase) {
|
||||||
unsigned int num_of_runners = _num_of_runners;
|
for (size_t i = 0; i < increase; ++i) {
|
||||||
|
|
||||||
if (num_of_runners == 0) {
|
|
||||||
#ifdef NUM_OF_RUNNERS
|
|
||||||
num_of_runners = NUM_OF_RUNNERS;
|
|
||||||
#else
|
|
||||||
num_of_runners = thread::hardware_concurrency();
|
|
||||||
if (num_of_runners < HW_CONCURRENCY_MINIMAL) {
|
|
||||||
num_of_runners = HW_CONCURRENCY_MINIMAL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < num_of_runners; ++i) {
|
|
||||||
runners.emplace_back( thread([&] {
|
runners.emplace_back( thread([&] {
|
||||||
while (!stop) {
|
while (!stop) {
|
||||||
function<void()> task;
|
function<void()> task;
|
||||||
@ -67,6 +51,21 @@ class runner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The constructor starts as many threads as the system has cores,
|
||||||
|
* and runs an event loop inside each one.
|
||||||
|
* Each event loop waits for tasks from the stack and executes them.
|
||||||
|
*/
|
||||||
|
runner(size_t pool_size = thread::hardware_concurrency()) : stop(false) {
|
||||||
|
if (pool_size < 4) {
|
||||||
|
pool_size = 4;
|
||||||
|
}
|
||||||
|
increase_runners(pool_size);
|
||||||
|
// start_all_runners(pool_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -93,6 +92,22 @@ class runner {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change the number of runners
|
||||||
|
*/
|
||||||
|
void change_runners (unsigned int num_of_runners) {
|
||||||
|
if (num_of_runners == 0 || num_of_runners > 64) {
|
||||||
|
throw runtime_error("Not allowed runners size");
|
||||||
|
}
|
||||||
|
|
||||||
|
int difference = num_of_runners - count_threads();
|
||||||
|
if (difference < 0) { // reduce
|
||||||
|
throw runtime_error("Is not allowed to reduce runners");
|
||||||
|
} else if (difference > 0) { // increase
|
||||||
|
increase_runners(difference);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of tasks the runner has to perform
|
* Returns the number of tasks the runner has to perform
|
||||||
*/
|
*/
|
||||||
@ -124,13 +139,6 @@ class runner {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal global library variable
|
|
||||||
*/
|
|
||||||
static runner _asyncon;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
228
test/test.cpp
228
test/test.cpp
@ -1,19 +1,22 @@
|
|||||||
#define NUM_OF_RUNNERS 2
|
|
||||||
|
|
||||||
|
#include "../lib/runner.hpp"
|
||||||
#include "../lib/asynco.hpp"
|
#include "../lib/asynco.hpp"
|
||||||
#include "../lib/event.hpp"
|
#include "../lib/event.hpp"
|
||||||
#include "../lib/rotor.hpp"
|
#include "../lib/rotor.hpp"
|
||||||
// #include "../lib/filesystem.hpp"
|
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace marcelb::asynco;
|
using namespace marcelb;
|
||||||
using namespace events;
|
|
||||||
// using namespace asynco;
|
|
||||||
using namespace this_thread;
|
using namespace this_thread;
|
||||||
|
|
||||||
|
#ifndef ON_RUNNER
|
||||||
|
#define ON_RUNNER
|
||||||
|
runner on_async;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void sleep_to (int _time) {
|
void sleep_to (int _time) {
|
||||||
promise<void> _promise;
|
promise<void> _promise;
|
||||||
timeout t( [&]() {
|
timeout t( [&]() {
|
||||||
@ -58,35 +61,35 @@ class myOwnClass : public event<int> {
|
|||||||
|
|
||||||
|
|
||||||
int main () {
|
int main () {
|
||||||
|
on_async.change_runners(64);
|
||||||
|
|
||||||
auto start = rtime_ms();
|
auto start = rtime_ms();
|
||||||
|
|
||||||
// // --------------- TIME ASYNCHRONOUS FUNCTIONS --------------
|
// --------------- TIME ASYNCHRONOUS FUNCTIONS --------------
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Init interval and timeout; clear interval and timeout
|
* Init interval and timeout; clear interval and timeout
|
||||||
// */
|
*/
|
||||||
|
|
||||||
// interval( [&] () {
|
// ovo ne radi
|
||||||
// cout << "interval 1: " << rtime_ms() - start << endl;
|
|
||||||
// }, 50);
|
|
||||||
|
|
||||||
// interval( [&] () {
|
// vector<interval> interv;
|
||||||
// cout << "interval 1: " << rtime_ms() - start << endl;
|
// vector<timeout> tmout;
|
||||||
// }, 100);
|
|
||||||
|
|
||||||
// interval( [&] () {
|
// for (int i=0; i< 20; i++) {
|
||||||
// cout << "interval 2: " << rtime_ms() - start << endl;
|
// interv.push_back( interval( [i] () {
|
||||||
// }, 200);
|
// cout << "interval " << i << endl;
|
||||||
|
// }, 1000));
|
||||||
|
// tmout.push_back( timeout( [i] () {
|
||||||
|
// cout << "timeout " << i << endl;
|
||||||
|
// }, 1000*i));
|
||||||
|
// }
|
||||||
|
|
||||||
// interval( [&] () {
|
// ovo valja popravit
|
||||||
// cout << "interval 3: " << rtime_ms() - start << endl;
|
|
||||||
// }, 300);
|
|
||||||
|
|
||||||
|
// interval( [] () {
|
||||||
// interval( [&] () {
|
// cout << "interval " << endl;
|
||||||
// cout << "interval 4: " << rtime_ms() - start << endl;
|
// }, 1000);
|
||||||
// }, 400);
|
|
||||||
|
|
||||||
// interval inter1 ([&]() {
|
// interval inter1 ([&]() {
|
||||||
// cout << "interval prvi " << rtime_ms() - start << endl;
|
// cout << "interval prvi " << rtime_ms() - start << endl;
|
||||||
@ -100,42 +103,42 @@ int main () {
|
|||||||
// cout << "interval treći " << rtime_ms() - start << endl;
|
// cout << "interval treći " << rtime_ms() - start << endl;
|
||||||
// }, 3000);
|
// }, 3000);
|
||||||
|
|
||||||
// interval inter4 ([&]() {
|
|
||||||
// cout << "interval cetvrti " << rtime_ms() - start << endl;
|
|
||||||
// }, 1000);
|
|
||||||
|
|
||||||
// interval inter5 ([&]() {
|
|
||||||
// cout << "interval peti " << rtime_ms() - start << endl;
|
|
||||||
// }, 2000);
|
|
||||||
|
|
||||||
// interval inter6 ([&]() {
|
|
||||||
// cout << "interval sesti " << rtime_ms() - start << endl;
|
|
||||||
// }, 3000);
|
|
||||||
|
|
||||||
// timeout time1 ( [&] () {
|
// timeout time1 ( [&] () {
|
||||||
// cout << "Close interval 1 i 2 " << rtime_ms() - start << endl;
|
// cout << "Close interval 1 i 2 " << rtime_ms() - start << endl;
|
||||||
// // inter1.clear();
|
// inter1.clear();
|
||||||
// // cout << "inter1.stop " << inter1.stop << endl;
|
// inter2.clear();
|
||||||
// // inter2.clear();
|
// }, 10000);
|
||||||
// // cout << "inter2.stop " << inter2.stop << endl;
|
|
||||||
|
|
||||||
// }, 5000);
|
|
||||||
|
|
||||||
// timeout time2 ([&] () {
|
// timeout time2 ([&] () {
|
||||||
// cout << "Close interval 3 " << rtime_ms() - start << endl;
|
// cout << "Close interval 3 " << rtime_ms() - start << endl;
|
||||||
// // inter3.clear();
|
// inter3.clear();
|
||||||
// // time1.clear();
|
// time1.clear();
|
||||||
// }, 2000);
|
// }, 2000);
|
||||||
|
|
||||||
// // ------------------------ MAKE FUNCTIONS ASYNCHRONOUS -------------------------
|
// // ------------------------ MAKE FUNCTIONS ASYNCHRONOUS -------------------------
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Run an function asyncronic
|
// * Put task directly and get returned value - it is not recommended to use it
|
||||||
*/
|
// */
|
||||||
|
|
||||||
// atask( []() {
|
// auto res1 = on_async.put_task( [] () {
|
||||||
|
// cout << "Jebiga " <<endl;
|
||||||
|
// throw string ("jebiga!!");
|
||||||
|
// });
|
||||||
|
|
||||||
|
// try {
|
||||||
|
// res1.get();
|
||||||
|
// } catch (const string except) {
|
||||||
|
// cout << except << endl;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Run an function asyncronic
|
||||||
|
// */
|
||||||
|
|
||||||
|
// asynco( []() {
|
||||||
// sleep_for(2s); // only for simulate log duration function
|
// sleep_for(2s); // only for simulate log duration function
|
||||||
// cout << "atask 1" << endl;
|
// cout << "asynco" << endl;
|
||||||
// return 5;
|
// return 5;
|
||||||
// });
|
// });
|
||||||
|
|
||||||
@ -143,44 +146,39 @@ int main () {
|
|||||||
// * Call not lambda function
|
// * Call not lambda function
|
||||||
// */
|
// */
|
||||||
|
|
||||||
// atask (notLambdaFunction);
|
// asynco (notLambdaFunction);
|
||||||
|
|
||||||
|
|
||||||
// wait (
|
|
||||||
// atask (
|
|
||||||
// notLambdaFunction
|
|
||||||
// )
|
|
||||||
// );
|
|
||||||
|
|
||||||
// /**
|
// /**
|
||||||
// * Call class method
|
// * Call class method
|
||||||
// */
|
// */
|
||||||
|
|
||||||
// clm classes;
|
// clm classes;
|
||||||
// atask( [&classes] () {
|
// asynco( [&classes] () {
|
||||||
// classes.classMethode();
|
// classes.classMethode();
|
||||||
// });
|
// });
|
||||||
|
|
||||||
// sleep(5);
|
// // sleep(5);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// /**
|
// /**
|
||||||
// * Wait after runned as async
|
// * Wait after runned as async
|
||||||
// */
|
// */
|
||||||
|
|
||||||
// auto a = atask( []() {
|
// auto a = asynco( []() {
|
||||||
// sleep_for(2s); // only for simulate log duration function
|
// sleep_for(2s); // only for simulate log duration function
|
||||||
// cout << "atask 2" << endl;
|
// cout << "asynco" << endl;
|
||||||
// return 5;
|
// return 5;
|
||||||
// });
|
// });
|
||||||
|
|
||||||
// cout << wait(a) << endl;
|
// cout << wait(move(a)) << endl;
|
||||||
// cout << "print after atask 2" << endl;
|
|
||||||
|
|
||||||
// /**
|
// /**
|
||||||
// * Wait async function call and use i cout
|
// * Wait async function call and use i cout
|
||||||
// */
|
// */
|
||||||
|
|
||||||
// cout << wait(atask( [] () {
|
// cout << wait(asynco( [] () {
|
||||||
// sleep_for(chrono::seconds(1)); // only for simulate log duration function
|
// sleep_for(chrono::seconds(1)); // only for simulate log duration function
|
||||||
// cout << "wait end" << endl;
|
// cout << "wait end" << endl;
|
||||||
// return 4;
|
// return 4;
|
||||||
@ -211,89 +209,63 @@ int main () {
|
|||||||
// */
|
// */
|
||||||
|
|
||||||
|
|
||||||
// atask( [] {
|
// asynco( [] {
|
||||||
// cout << "idemo ..." << endl;
|
// cout << "idemo ..." << endl;
|
||||||
// atask( [] {
|
// asynco( [] {
|
||||||
// cout << "ugdnježdena async funkcija " << endl;
|
// cout << "ugdnježdena async funkcija " << endl;
|
||||||
// });
|
// });
|
||||||
// });
|
// });
|
||||||
|
|
||||||
// --------------- EVENTS -------------------
|
// // --------------- EVENTS -------------------
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* initialization of typed events
|
// * initialization of typed events
|
||||||
*/
|
// */
|
||||||
|
|
||||||
event<int, int> ev2int;
|
// event<int, int> ev2int;
|
||||||
event<int, string> evintString;
|
// event<int, string> evintString;
|
||||||
event<> evoid;
|
// event<> evoid;
|
||||||
|
|
||||||
ev2int.on("sum", [](int a, int b) {
|
// ev2int.on("sum", [](int a, int b) {
|
||||||
cout << "Sum " << a+b << endl;
|
// cout << "Sum " << a+b << endl;
|
||||||
});
|
// });
|
||||||
|
|
||||||
ev2int.on("sum", [](int a, int b) {
|
// evintString.on("substract", [](int a, string b) {
|
||||||
cout << "Sum done" << endl;
|
// cout << "Substract " << a-stoi(b) << endl;
|
||||||
});
|
// });
|
||||||
|
|
||||||
evintString.on("substract", [](int a, string b) {
|
// evoid.on("void", []() {
|
||||||
cout << "Substract " << a-stoi(b) << endl;
|
// cout << "Void emited" << endl;
|
||||||
});
|
// });
|
||||||
|
|
||||||
evoid.on("void", []() {
|
// // sleep(1);
|
||||||
cout << "Void emited" << endl;
|
|
||||||
});
|
|
||||||
|
|
||||||
string emited2 = "2";
|
// /**
|
||||||
|
// * Emit
|
||||||
|
// */
|
||||||
|
|
||||||
evoid.on("void", [&]() {
|
// ev2int.emit("sum", 5, 8);
|
||||||
cout << "Void emited " << emited2 << endl;
|
|
||||||
});
|
|
||||||
|
|
||||||
evoid.emit("void");
|
// sleep(1);
|
||||||
sleep(1);
|
// evintString.emit("substract", 3, to_string(2));
|
||||||
|
|
||||||
/**
|
// sleep(1);
|
||||||
* Emit
|
// evoid.emit("void");
|
||||||
*/
|
|
||||||
|
|
||||||
ev2int.emit("sum", 5, 8);
|
// /**
|
||||||
|
// * Own class
|
||||||
|
// */
|
||||||
|
|
||||||
sleep(1);
|
// myOwnClass myclass;
|
||||||
evintString.emit("substract", 3, to_string(2));
|
|
||||||
|
|
||||||
sleep(1);
|
// timeout t( [&] {
|
||||||
evoid.off("void");
|
// myclass.emit("constructed", 1);
|
||||||
evoid.emit("void");
|
// }, 200);
|
||||||
|
|
||||||
/**
|
// myclass.on("constructed", [] (int i) {
|
||||||
* Own class
|
// cout << "Constructed " << i << endl;
|
||||||
*/
|
// });
|
||||||
|
|
||||||
myOwnClass myclass;
|
|
||||||
|
|
||||||
timeout t( [&] {
|
|
||||||
myclass.emit("constructed", 1);
|
|
||||||
}, 200);
|
|
||||||
|
|
||||||
myclass.on("constructed", [] (int i) {
|
|
||||||
cout << "Constructed " << i << endl;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// auto status = fs::read("test1.txt");
|
|
||||||
|
|
||||||
|
|
||||||
// try {
|
|
||||||
// auto data = wait(status);
|
|
||||||
// cout << data;
|
|
||||||
// } catch (exception& err) {
|
|
||||||
// cout << err.what() << endl;
|
|
||||||
// }
|
|
||||||
|
|
||||||
cout << "Sleep" << endl;
|
|
||||||
sleep(100000); // only for testing
|
sleep(100000); // only for testing
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user