AsyncLoop (ThreadPool, task execute loop), interval, timeout, asynco, wait

dev-own-engine
marcelb 9 months ago
commit 03b11840f4
  1. 16
      .vscode/c_cpp_properties.json
  2. 27
      .vscode/settings.json
  3. 28
      .vscode/tasks.json
  4. 0
      README.md
  5. 93
      lib/asynco.hpp
  6. 40
      lib/event.hpp
  7. 91
      lib/loop.hpp
  8. 0
      src/pool.cpp
  9. BIN
      test/test
  10. 104
      test/test.cpp

@ -0,0 +1,16 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
"cStandard": "c17",
"cppStandard": "gnu++17",
"intelliSenseMode": "linux-gcc-x64"
}
],
"version": 4
}

@ -0,0 +1,27 @@
{
"files.associations": {
"iostream": "cpp",
"functional": "cpp",
"thread": "cpp",
"chrono": "cpp",
"ostream": "cpp",
"condition_variable": "cpp",
"array": "cpp",
"atomic": "cpp",
"cwchar": "cpp",
"deque": "cpp",
"unordered_map": "cpp",
"vector": "cpp",
"exception": "cpp",
"initializer_list": "cpp",
"iosfwd": "cpp",
"mutex": "cpp",
"new": "cpp",
"ratio": "cpp",
"stdexcept": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"future": "cpp"
}
}

28
.vscode/tasks.json vendored

@ -0,0 +1,28 @@
{
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: gcc build active file",
"command": "/usr/bin/g++",
"args": [
"-fdiagnostics-color=always",
"-g",
"${file}",
"-o",
"${fileDirname}/${fileBasenameNoExtension}"
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "Task generated by Debugger."
}
],
"version": "2.0.0"
}

@ -0,0 +1,93 @@
#ifndef _ASYNCO_
#define _ASYNCO_
#include "loop.hpp"
using namespace std;
namespace marcelb {
#ifndef ON_ASYNC
#define ON_ASYNC
AsyncLoop on_async;
#endif
class interval {
bool run = true;
function<void()> callback;
const time_t _duration;
public:
interval(function<void()> func, const time_t duration): callback(func), _duration(duration) {
#ifndef ON_ASYNC
throw string("Not on_async defined!");
#endif
auto task = [&] () {
while (run) {
this_thread::sleep_for(chrono::milliseconds(_duration));
if (run) {
callback();
}
}
};
on_async.put_task(task);
}
void clear() {
run = false;
}
~interval() {
clear();
}
};
class timeout {
bool run = true;
function<void()> callback;
const time_t _duration;
public:
timeout(function<void()> f, const time_t duration): callback(f), _duration(duration) {
#ifndef ON_ASYNC
throw string("Not on_async defined!");
#endif
auto task = [&] () {
this_thread::sleep_for(chrono::milliseconds(_duration));
if (run) {
callback();
}
};
on_async.put_task(task);
}
void clear() {
run = false;
}
~timeout() {
clear();
}
};
template<class F, class... Args>
auto asynco(F&& f, Args&&... args) -> future<typename result_of<F(Args...)>::type> {
using return_type = typename result_of<F(Args...)>::type;
future<return_type> res = on_async.put_task(bind(forward<F>(f), forward<Args>(args)...));
return res;
}
template<typename T>
T wait(future<T> r) {
return r.get();
}
}
#endif

@ -0,0 +1,40 @@
#ifndef _EVENT_
#define _EVENT_
#include <iostream>
#include <map>
#include <string>
#include <functional>
using namespace std;
namespace marcelb {
class event {
map<string, function<void(const tuple<>&)>> events;
public:
template <typename... Args>
void on(const string& key, function<void(Args...)> f) {
// events[key] = [f](Args... args) {
// f(args...);
// };
}
template <typename... Args>
void emit(const string& key, Args&&... args) {
if (events.find(key) == events.end()) {
cout << "No defined listener for event: " << key << endl;
return;
}
else {
for (auto& func : events[key]) {
func(forward<Args>(args)...);
}
}
}
};
}
#endif

@ -0,0 +1,91 @@
#ifndef _LOOP_
#define _LOOP_
#include <thread>
#include <vector>
#include <queue>
#include <functional>
#include <mutex>
#include <condition_variable>
#include <future>
using namespace std;
namespace marcelb {
#ifdef ON_ASYNC
extern AsyncLoop on_async;
#endif
class AsyncLoop {
private:
vector<thread> workers;
queue<function<void()>> tasks;
mutex q_io;
condition_variable cv;
bool stop;
public:
AsyncLoop(size_t pool_size = thread::hardware_concurrency()) : stop(false) {
for (size_t i = 0; i < pool_size; ++i) {
workers.emplace_back([this] {
while (true) {
function<void()> task;
{
unique_lock<mutex> lock(q_io);
cv.wait(lock, [this] { return stop || !tasks.empty(); });
if (stop && tasks.empty())
return;
task = move(tasks.front());
tasks.pop();
}
task();
}
});
}
}
template<class F, class... Args>
auto put_task(F&& f, Args&&... args)
-> future<typename result_of<F(Args...)>::type> {
using return_type = typename result_of<F(Args...)>::type;
auto task = make_shared<packaged_task<return_type()>>(bind(forward<F>(f), forward<Args>(args)...));
future<return_type> res = task->get_future();
{
unique_lock<mutex> lock(q_io);
if (stop) {
throw runtime_error("Pool is stoped!");
}
tasks.emplace([task]() { (*task)(); });
}
cv.notify_one();
return res;
}
unsigned int count_tasks() {
return tasks.size();
}
unsigned int count_threads() {
return workers.size();
}
~AsyncLoop() {
{
unique_lock<mutex> lock(q_io);
stop = true;
}
cv.notify_all();
for (thread& worker : workers)
worker.join();
}
};
}
#endif

Binary file not shown.

@ -0,0 +1,104 @@
#include "../lib/loop.hpp"
#include "../lib/asynco.hpp"
// #include "../lib/event.hpp"
#include <iostream>
#include <unistd.h>
using namespace std;
using namespace marcelb;
using namespace this_thread;
#ifndef ON_ASYNC
#define ON_ASYNC
AsyncLoop on_async;
#endif
int main () {
auto start = chrono::high_resolution_clock::now();
interval inter1 ([&]() {
cout << "interval prvi " << chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start).count() << endl;
}, 1000);
cout << "Blokira stoka" << endl;
interval inter2 ([&]() {
cout << "interval drugi " << chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start).count() << endl;
}, 2000);
interval inter3 ([&]() {
cout << "interval treći " << chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start).count() << endl;
}, 3000);
timeout time1 ( [&] () {
cout << "Close interval 1 i 2 " << chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start).count() << endl;
inter1.clear();
inter2.clear();
}, 10000);
timeout time2 ([&] () {
cout << "Close interval 3 " << chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start).count() << endl;
inter3.clear();
}, 20000);
// for (int i = 0; i < 8; ++i) {
// pool.put_task( [&] (int id) {
// this_thread::sleep_for(chrono::seconds(1));
// cout << a*i << endl;
// }, i);
// }
// auto res1 = pool.put_task( [] () {
// cout << "Jebiga " <<endl;
// throw string ("jebiga!!");
// });
// try {
// res1.get();
// } catch (const string except) {
// cout << except << endl;
// }
// auto res = pool.put_task( []() {
// this_thread::sleep_for(chrono::seconds(1));
// return 4;
// });
// cout << wait(asynco( [] () {
// sleep_for(chrono::seconds(1));
// cout << "RETURN" << endl;
// return 4;
// })) << endl;
// asynco( []() {
// sleep_for(2s);
// cout << "RETURN 2" << endl;
// return 5;
// });
// cout << wait(pool.put_task( []() {
// this_thread::sleep_for(chrono::seconds(1));
// return 7;
// }));
// cout << wait(run1) << endl;
// event dog;
// dog.on("roge", [](int a, int b) {
// cout << "Rogeee" << a << b << endl;
// });
// sleep(5);
// dog.emit("roge", 5, 8);
sleep(1000);
return 0;
}
Loading…
Cancel
Save