-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathActiveObject_01.cpp
More file actions
114 lines (78 loc) · 2.74 KB
/
ActiveObject_01.cpp
File metadata and controls
114 lines (78 loc) · 2.74 KB
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
// ===========================================================================
// ActiveObject_01.cpp // Active Object Pattern
// ===========================================================================
#include "../Logger/Logger.h"
#include <chrono>
#include <future>
#include <mutex>
#include <thread>
#include <tuple>
// ===========================================================================
//
// This Example demonstrates the 'Active Object Pattern'
// pattern as compact as possible.
// The 'activation list' queue consist of a single element.
// The scheduler runs a single task, but:
// A result value is returned from the 'Active Object' to the client.
// ===========================================================================
namespace ActivatorObject01
{
class AddOperation
{
public:
AddOperation(int a, int b) : m_a{ a }, m_b{ b } {}
auto operator() () {
Logger::log(std::cout, "adding ", m_a, " and ", m_b, " ... ");
auto result{ std::make_tuple(m_a, m_b, m_a + m_b) };
return result;
}
private:
int m_a;
int m_b;
};
class ActiveObject
{
private:
std::packaged_task<std::tuple<int, int, int>()> m_activationElement;
std::mutex m_mutex;
public:
std::future<std::tuple<int, int, int>> enqueueTask(int a, int b) {
AddOperation operation{ a, b };
std::packaged_task<std::tuple<int, int, int>()> task{ operation };
auto future = task.get_future();
{
std::lock_guard<std::mutex> guard{ m_mutex };
m_activationElement = std::move(task);
}
return future;
}
void run() {
std::jthread jt { [this] () { runSingleTask(); } };
}
private:
void runSingleTask() {
std::lock_guard<std::mutex> guard(m_mutex);
if (m_activationElement.valid()) {
m_activationElement();
}
}
};
}
void test_active_object_01()
{
using namespace ActivatorObject01;
Logger::log(std::cout, "Active Object - Simple Approach");
ActiveObject activeObject;
auto future{ activeObject.enqueueTask(3, 5) };
// start the active object
activeObject.run();
// continue working in the client thread
std::this_thread::sleep_for(std::chrono::seconds(1));
// get the result from the future
auto [first, second, sum] = future.get();
Logger::log(std::cout, first, " + ", second, " = ", sum);
Logger::log(std::cout, "Done.");
}
// ===========================================================================
// End-of-File
// ===========================================================================