-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathjulia_multithreading.cpp
123 lines (99 loc) · 2.67 KB
/
julia_multithreading.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <deque>
#include <future>
#include <iostream>
#include <mutex>
#include <thread>
#include <vector>
#define JULIA_ENABLE_THREADING
#include <julia.h>
class Worker {
bool running = true;
std::thread t;
std::mutex mtx;
std::condition_variable cond;
std::deque<std::function<void()>> tasks;
public:
Worker() : t{&Worker::threadFunc, this} {}
~Worker() {
{
auto lock = std::unique_lock(mtx);
running = false;
}
cond.notify_one();
t.join();
}
template <typename F> auto spawn(const F& f) -> std::packaged_task<decltype(f())()> {
std::packaged_task<decltype(f())()> task(f);
{
auto lock = std::unique_lock(mtx);
tasks.push_back([&task] { task(); });
}
cond.notify_one();
return task;
}
template <typename F> auto run(const F& f) -> decltype(f()) { return spawn(f).get_future().get(); }
private:
void threadFunc() {
while (true) {
std::function<void()> task;
{
auto lock = std::unique_lock(mtx);
while (tasks.empty() && running) {
cond.wait(lock);
}
if (!running) {
break;
}
task = std::move(tasks.front());
tasks.pop_front();
}
task();
}
}
};
class julia {
Worker worker;
private:
static julia& instance() {
static julia instance;
return instance;
}
julia() {
worker.run([] {
jl_init();
jl_eval_string("println(\"JULIA START\")");
});
}
~julia() {
worker.run([] {
jl_eval_string("println(\"JULIA END\")");
jl_atexit_hook(0);
});
}
public:
template <typename F> static auto spawn(const F& f) -> std::packaged_task<decltype(f())()> {
return instance().worker.spawn(f);
}
template <typename F> static auto run(const F& f) -> decltype(f()) { return instance().worker.run(f); }
static void run(const char* s) {
return instance().worker.run([&] { jl_eval_string(s); });
}
};
int other_thread() {
julia::run("println(\"other thread\")");
return 0;
}
int main(int argc, char* argv[]) {
std::cout << "Program start" << std::endl;
{
julia::run([] { jl_eval_string("println(\"main thread - 1\")"); });
std::thread t(other_thread);
julia::run("println(\"main thread - 2\")");
t.join();
}
std::cout << "Program end" << std::endl;
return 0;
}