List of commits:
Subject Hash Author Date (UTC)
v2 e41a73cccb511cb3c21c9c46733e57c8c0b62c57 Ubuntu 2020-06-28 14:26:22
fix compile time error fbc1c35e2389d9fffebe94808385ded809b4061a mucbuc 2019-11-03 00:30:41
cleanup template stuff 4ebc0945d2e8cf2c7a1f75d3dab125b83f76078d mucbuc 2019-11-02 21:09:51
more cleanup bfbe00170ae67ea7e8e1cb23e4e352b18188b5a9 mucbuc 2019-11-02 21:01:10
delete explicit template stuff 1a43665b79bb3df8e28cb7be2d460cbec6cd6a0f mucbuc 2019-11-02 20:55:26
use parameter pack aaff690514d7543a66c285cf9214ebad55c6876e mucbuc 2019-11-02 20:49:43
builds d8412e21c450b8da35dc1f248cb713859bb40c26 mucbuc 2019-11-02 20:26:54
ignore test tmp 0c68fe48a97a80098e224875f1f7aa948a7c6a59 Ubuntu 2018-10-07 09:50:49
plusify 5521f5f65b89bdb2a848d3e497b1c591fe39c15e Ubuntu 2018-10-06 12:18:21
Uni test (#2) 9b73df9337debfea1a000811645609bdd2d8a5ea Mark Busenitz 2018-06-25 10:46:04
license 8e6ee3e912b6273862fbecc34777ef8268ddd5dd mbusenitz 2017-11-21 04:38:04
doc hook (#1) 2d744d1ce1deb15ed20f1d5819de7e2d9230e2c7 Mark Busenitz 2017-03-25 20:27:28
package.json a4c059735b1201b5749b10f758fcfe3561d9ead6 mbusenitz 2017-03-21 04:20:38
Update README.md 2218a3a0dd2103de11dff6b15e670ad3874f4266 Mark Busenitz 2017-03-21 04:19:16
rm asserter.jsons 92c29fd451d0cfe128ea1ab18e82e379efdeb7af mbusenitz 2016-01-28 08:15:52
fix json b6ca8aebcfcde3acdc919e92004129d155755b8b mbusenitz 2015-10-22 04:37:08
jsonstuff 960242ccde70c18aa0fb1e72575fb84fde61040e mbusenitz 2015-10-22 04:34:42
json 4c6b6c5b3b00222e50562c8ace7ce67506a7ef98 mbusenitz 2015-10-16 04:25:06
fix build 82dcaff9abc9c68298522d47c7c175d855b6ffa2 mbusenitz 2015-09-26 10:39:35
rm test/plank 75bed7f551f1ca0f18ea34a3ab478ae6749bfad9 mbusenitz 2015-09-26 10:37:40
Commit e41a73cccb511cb3c21c9c46733e57c8c0b62c57 - v2
Author: Ubuntu
Author date (UTC): 2020-06-28 14:26
Committer name: Ubuntu
Committer date (UTC): 2020-06-28 14:26
Parent(s): fbc1c35e2389d9fffebe94808385ded809b4061a
Signing key:
Tree: a35f7540768cb072384ba6f32ab8e0f701adebae
File Lines added Lines deleted
OTHER.md 9 0
README.md 69 3
def.json 4 5
package.json 4 1
src/agent.h 0 42
src/agent.hxx 0 86
src/batch.h 0 63
src/batch.hxx 0 104
src/dynamofwd.h 5 6
src/impl/batch.h 44 0
src/impl/batch.hxx 69 0
src/interface.h 29 0
test/example.json 2 3
test/lib/circuit/.gitignore 4 0
test/lib/circuit/EXAMPLE.md 29 0
test/lib/circuit/README.md 52 0
test/lib/circuit/circuit.json 11 0
test/lib/circuit/package.json 16 0
test/lib/circuit/src/factory.h 22 0
test/lib/circuit/src/impl/circuit_host.h 46 0
test/lib/circuit/src/impl/circuit_host.hxx 111 0
test/lib/circuit/src/impl/queue.h 63 0
test/lib/circuit/src/impl/stack.h 63 0
test/lib/circuit/src/index.h 17 0
test/lib/circuit/src/interface.h 18 0
test/lib/circuit/test/example.json 8 0
test/lib/circuit/test/src/example.cpp 18 0
test/lib/circuit/test/src/main.cpp 32 0
test/lib/circuit/test/test.json 8 0
test/src/batch.h 43 25
test/src/example.cpp 17 0
test/src/main.cpp 5 4
File OTHER.md added (mode: 100644) (index 0000000..e9471d9)
1 template = `### Dependencies
2
3 Dynamo uses Circuit for thread syncronization
4
5 ### Plan
6
7 Instead of copy and insert elements inside of invok, push the elements one by one as they get traversed (obviosly don't add elements that are dead)...
8
9 ![doc header](https://s3-us-west-2.amazonaws.com/mod-resources/mod-header.svg)`;
File README.md changed (mode: 100644) (index e7702ef..90e68bd)
1 ## dynamo
2
3 ![doc header](https://s3-us-west-2.amazonaws.com/mod-resources/mod-header.svg)
1 # dynamo
2
3 Dispatch work to agents.
4
5 ## Interface
6 ```
7 #pragma once
8
9 #include <functional>
10 #include <memory>
11
12 namespace om636 {
13 namespace control {
14
15 template <typename... T>
16 class Batch {
17 public:
18 typedef std::function<void(T...)> function_type;
19 typedef std::shared_ptr<function_type> agent_type;
20 typedef agent_type listener_type;
21
22 virtual ~Batch() = default;
23 virtual agent_type hook(function_type) = 0;
24 virtual agent_type hook_once(function_type) = 0;
25 virtual void invoke(T...) = 0;
26 };
27
28 template <typename... T>
29 std::shared_ptr<Batch<T...>> make_queue();
30
31 template <typename... T>
32 std::shared_ptr<Batch<T...>> make_stack();
33
34 } // control
35 } // om636
36
37 ```
38
39 ## Example
40 ```
41 #include <tmp/src/test.h>
42
43 #include <lib/dynamo/src/impl/batch.h>
44 #include <lib/dynamo/src/interface.h>
45
46 int main()
47 {
48 auto b = om636::control::make_queue<int>();
49
50 int sum{ 0 };
51
52 auto q = b->hook([&](int i) { sum += i; });
53 auto p = b->hook([&](int i) { sum *= i; });
54 b->invoke(5);
55 ASSERT(sum == 25);
56 return 0;
57 }
58
59 ```
60
61 ### Dependencies
62
63 Dynamo uses Circuit for thread syncronization
64
65 ### Plan
66
67 Instead of copy and insert elements inside of invok, push the elements one by one as they get traversed (obviosly don't add elements that are dead)...
68
69 ![doc header](https://s3-us-west-2.amazonaws.com/mod-resources/mod-header.svg)
File def.json changed (mode: 100644) (index 12fb868..2500050)
1 1 { {
2 2 "sources": [ "sources": [
3 "src/agent.h",
4 "src/agent.hxx",
5 "src/batch.h",
6 "src/batch.hxx",
7 "src/dynamofwd.h"
3 "src/dynamofwd.h",
4 "src/interface.h",
5 "src/impl/batch.h",
6 "src/impl/batch.hxx"
8 7 ] ]
9 8 } }
File package.json changed (mode: 100644) (index 2312c3b..76f81ed)
1 1 { "version":"0.0.0", { "version":"0.0.0",
2 "description":"Dispatch work to agents.",
2 3 "name":"dynamo", "name":"dynamo",
3 4 "scripts": { "scripts": {
4 "test": "crimp test/test.json -g"
5 "test": "crimp test/test.json -g",
6 "generateDocs":"doc-tool package_header src_interface test_example ./OTHER.md > README.md",
7 "format": "clang-format -i --style=Webkit src/*.h src/impl/*.h src/impl/*.hxx test/src/*.cpp"
5 8 } }
6 9 } }
File src/agent.h deleted (index 93b907b..0000000)
1 #ifndef AGENT_H__0OiXEmL5tPcgUywQFDMW6Gv1J8Hdzo
2 #define AGENT_H__0OiXEmL5tPcgUywQFDMW6Gv1J8Hdzo
3
4 namespace om636 {
5 namespace control {
6
7 template <typename T>
8 struct Agent {
9 typedef T callback_type;
10 Agent(callback_type);
11
12 Agent(const Agent&) = delete;
13 Agent& operator=(const Agent&) = delete;
14
15 void invoke();
16
17 template <class V>
18 void invoke(V);
19
20 template <typename V, typename W>
21 void invoke(V, W);
22
23 void kill_invoke();
24
25 template <class V>
26 void kill_invoke(V);
27
28 template <typename V, typename W>
29 void kill_invoke(V, W);
30
31 void kill();
32 bool is_dead();
33
34 private:
35 callback_type m_callback;
36 };
37
38 } //control
39 } // om636
40
41 #include "agent.hxx"
42 #endif // AGENT_H__0OiXEmL5tPcgUywQFDMW6Gv1J8Hdzo
File src/agent.hxx deleted (index 5f3dde8..0000000)
1 namespace om636 {
2 namespace control {
3
4 /////////////////////////////////////////////////////////////////////////////////////
5 // Agent
6 /////////////////////////////////////////////////////////////////////////////////////
7 template <typename T>
8 Agent<T>::Agent(callback_type callback)
9 : m_callback(callback)
10 {
11 }
12
13 /////////////////////////////////////////////////////////////////////////////////////
14 template <typename T>
15 void Agent<T>::invoke()
16 {
17 ASSERT(!is_dead());
18 m_callback();
19 }
20
21 /////////////////////////////////////////////////////////////////////////////////////
22 template <typename T>
23 template <typename V>
24 void Agent<T>::invoke(V v)
25 {
26 ASSERT(!is_dead());
27 m_callback(v);
28 }
29
30 /////////////////////////////////////////////////////////////////////////////////////
31 template <typename T>
32 template <typename V, typename W>
33 void Agent<T>::invoke(V v, W w)
34 {
35 ASSERT(!is_dead());
36 m_callback(v, w);
37 }
38
39 /////////////////////////////////////////////////////////////////////////////////////
40 template <typename T>
41 void Agent<T>::kill_invoke()
42 {
43 ASSERT(!is_dead());
44 callback_type temp(m_callback);
45 kill();
46 temp();
47 }
48
49 /////////////////////////////////////////////////////////////////////////////////////
50 template <typename T>
51 template <typename V>
52 void Agent<T>::kill_invoke(V v)
53 {
54 ASSERT(!is_dead());
55 callback_type temp(m_callback);
56 kill();
57 temp(v);
58 }
59
60 /////////////////////////////////////////////////////////////////////////////////////
61 template <typename T>
62 template <typename V, typename W>
63 void Agent<T>::kill_invoke(V v, W w)
64 {
65 ASSERT(!is_dead());
66 callback_type temp(m_callback);
67 kill();
68 temp(v, w);
69 }
70
71 /////////////////////////////////////////////////////////////////////////////////////
72 template <typename T>
73 void Agent<T>::kill()
74 {
75 m_callback = callback_type();
76 }
77
78 /////////////////////////////////////////////////////////////////////////////////////
79 template <typename T>
80 bool Agent<T>::is_dead()
81 {
82 return !m_callback;
83 }
84
85 } //control
86 } // om636
File src/batch.h deleted (index 648807c..0000000)
1 #ifndef BATCH_H__iFZqmDoIwhGaYO3df4xe5LCQXrbBvj
2 #define BATCH_H__iFZqmDoIwhGaYO3df4xe5LCQXrbBvj
3
4 #include <algorithm>
5 #include <map>
6 #include <memory>
7 #include <vector>
8
9 #include "agent.h"
10
11 namespace om636 {
12 namespace control {
13 template <typename T>
14 class Batch {
15 public:
16 typedef T callback_type;
17 typedef Agent<callback_type> agent_type;
18 typedef std::weak_ptr<agent_type> pointer_type;
19 typedef std::shared_ptr<agent_type> listener_type;
20 typedef std::vector<pointer_type> batch_type;
21
22 Batch() = default;
23 virtual ~Batch() = default;
24 Batch(const Batch&) = delete;
25 Batch& operator=(const Batch&) = delete;
26
27 listener_type hook(callback_type);
28 void unhook();
29
30 template <class ... V>
31 void traverse(V ...);
32
33 template <class ... V>
34 void traverse_destructive(V ...);
35
36 batch_type& elements();
37 const batch_type& elements() const;
38
39 void merge_added_elements();
40
41 private:
42 batch_type m_elements;
43 batch_type m_elements_add;
44 };
45
46 namespace utils {
47
48 template <typename T, typename ... V>
49 void process_and_kill(T&, V...);
50
51 template <typename T, typename ... V>
52 void process(T&, V...);
53
54 template <typename T>
55 void kill_all(T&);
56 }
57
58 } //control
59 } // om636
60
61 #include "batch.hxx"
62
63 #endif
File src/batch.hxx deleted (index 49fe368..0000000)
1 namespace om636 {
2 namespace control {
3 /////////////////////////////////////////////////////////////////////////////////////
4 template <typename T>
5 auto Batch<T>::hook(callback_type c) -> listener_type
6 {
7 listener_type agent(std::make_shared<agent_type>(c));
8 m_elements_add.push_back(agent);
9 return agent;
10 }
11
12 /////////////////////////////////////////////////////////////////////////////////////
13 template <typename T>
14 void Batch<T>::unhook()
15 {
16 utils::kill_all(elements());
17 utils::kill_all(m_elements_add);
18 }
19
20 /////////////////////////////////////////////////////////////////////////////////////
21 template <typename T>
22 template <class ... V>
23 void Batch<T>::traverse(V ... arg)
24 {
25 merge_added_elements();
26
27 utils::process(elements(), arg ... );
28 }
29
30 /////////////////////////////////////////////////////////////////////////////////////
31 template <typename T>
32 template <class ... V>
33 void Batch<T>::traverse_destructive(V ... arg)
34 {
35 merge_added_elements();
36
37 utils::process_and_kill(elements(), arg ...);
38 }
39
40 /////////////////////////////////////////////////////////////////////////////////////
41 template <typename T>
42 auto Batch<T>::elements() -> batch_type&
43 {
44 return m_elements;
45 }
46
47 /////////////////////////////////////////////////////////////////////////////////////
48 template <typename T>
49 auto Batch<T>::elements() const -> const batch_type&
50 {
51 return m_elements;
52 }
53
54 /////////////////////////////////////////////////////////////////////////////////////
55 template <typename T>
56 void Batch<T>::merge_added_elements()
57 {
58 elements().insert(elements().end(), m_elements_add.begin(), m_elements_add.end());
59 m_elements_add.clear();
60 }
61
62 namespace utils {
63 /////////////////////////////////////////////////////////////////////////////////////
64 template <typename T, typename ... V>
65 void process(T& elements, V ... v)
66 {
67 T copy(elements);
68 for_each(copy.begin(), copy.end(), [&](typename T::value_type p) {
69 auto s(p.lock());
70 if (s && !s->is_dead())
71 s->invoke(v ...);
72 //else
73 //elements.erase(p);
74 });
75 }
76
77 /////////////////////////////////////////////////////////////////////////////////////
78 template <typename T, typename ... V>
79 void process_and_kill(T& elements, V ... v)
80 {
81 T copy(elements);
82 for_each(copy.begin(), copy.end(), [&](typename T::value_type p) {
83 auto s(p.lock());
84 if (s && !s->is_dead())
85 s->kill_invoke(v ...);
86 });
87 elements.clear();
88 }
89
90 /////////////////////////////////////////////////////////////////////////////////////
91 template <typename T>
92 void kill_all(T& elements)
93 {
94 for_each(elements.begin(), elements.end(), [](typename T::value_type p) {
95 auto s(p.lock());
96 if (s) {
97 s->kill();
98 }
99 });
100 elements.clear();
101 }
102 } // utils
103 } // control
104 } // om636
File src/dynamofwd.h changed (mode: 100644) (index 6666fd9..402d909)
1 #pragma once
2
1 3 namespace om636 { namespace om636 {
2 4 namespace control { namespace control {
3 template <typename>
5 template <typename...>
4 6 struct Agent; struct Agent;
5 7
6 template <typename>
7 struct Listener;
8
9 template <typename, typename>
8 template <typename...>
10 9 struct Batch; struct Batch;
11 10 } }
12 }
11 }
File src/impl/batch.h added (mode: 100644) (index 0000000..fe6e79f)
1 #pragma once
2
3 #include <algorithm>
4 #include <memory>
5 #include <vector>
6
7 #include <lib/circuit/src/impl/circuit_host.h>
8 #include <lib/circuit/src/impl/queue.h>
9 #include <lib/circuit/src/impl/stack.h>
10
11 #include "../interface.h"
12
13 namespace om636 {
14 namespace control {
15
16 template <template <typename> typename P, typename... T>
17 class BatchImpl : public Batch<T...> {
18 public:
19 typedef Batch<T...> base_type;
20 using typename base_type::agent_type;
21 using typename base_type::function_type;
22
23 ~BatchImpl() override = default;
24 agent_type hook(function_type) override;
25 agent_type hook_once(function_type) override;
26 void invoke(T...) override;
27
28 typedef std::weak_ptr<typename agent_type::element_type> pointer_type;
29 typedef std::tuple<pointer_type, bool> tuple_type;
30 typedef circuit::CircuitHost<tuple_type, P> batch_type;
31 batch_type& impl_ref();
32 const batch_type& impl_ref() const;
33
34 private:
35 template <typename U>
36 void invoke(U, T...);
37
38 batch_type m_impl;
39 };
40
41 } //control
42 } // om636
43
44 #include "batch.hxx"
File src/impl/batch.hxx added (mode: 100644) (index 0000000..877b294)
1 namespace om636 {
2 namespace control {
3 /////////////////////////////////////////////////////////////////////////////////////
4 template <template <typename> typename P, typename... T>
5 auto BatchImpl<P, T...>::hook(function_type callback) -> agent_type
6 {
7 using namespace std;
8 auto agent(make_shared<function_type>(callback));
9 impl_ref().push(make_tuple<pointer_type, bool>(agent, true));
10 return agent;
11 }
12
13 /////////////////////////////////////////////////////////////////////////////////////
14 template <template <typename> typename P, typename... T>
15 auto BatchImpl<P, T...>::hook_once(function_type callback) -> agent_type
16 {
17 using namespace std;
18 auto agent(make_shared<function_type>(callback));
19 impl_ref().push(make_tuple<pointer_type, bool>(agent, false));
20 return agent;
21 }
22
23 /////////////////////////////////////////////////////////////////////////////////////
24 template <template <typename> typename P, typename... T>
25 void BatchImpl<P, T...>::invoke(T... arg)
26 {
27 using namespace std;
28 batch_type traverse;
29 traverse.swap(impl_ref());
30 tuple_type agent;
31 while (traverse.check_pop(agent)) {
32 agent_type s(get<0>(agent).lock());
33 if (s) {
34 (*s)(arg...);
35 }
36 s = get<0>(agent).lock();
37 if (s && get<1>(agent)) {
38 impl_ref().push(move(agent));
39 }
40 }
41 }
42
43 /////////////////////////////////////////////////////////////////////////////////////
44 template <template <typename> typename P, typename... T>
45 auto BatchImpl<P, T...>::impl_ref() -> batch_type&
46 {
47 return m_impl;
48 }
49
50 /////////////////////////////////////////////////////////////////////////////////////
51 template <template <typename> typename P, typename... T>
52 auto BatchImpl<P, T...>::impl_ref() const -> const batch_type&
53 {
54 return m_impl;
55 }
56
57 template <typename... T>
58 std::shared_ptr<Batch<T...>> make_queue()
59 {
60 return std::make_shared<BatchImpl<om636::circuit::QueuePolicy, T...>>();
61 }
62
63 template <typename... T>
64 std::shared_ptr<Batch<T...>> make_stack()
65 {
66 return std::make_shared<BatchImpl<om636::circuit::StackPolicy, T...>>();
67 }
68 } // control
69 } // om636
File src/interface.h added (mode: 100644) (index 0000000..5f71593)
1 #pragma once
2
3 #include <functional>
4 #include <memory>
5
6 namespace om636 {
7 namespace control {
8
9 template <typename... T>
10 class Batch {
11 public:
12 typedef std::function<void(T...)> function_type;
13 typedef std::shared_ptr<function_type> agent_type;
14 typedef agent_type listener_type;
15
16 virtual ~Batch() = default;
17 virtual agent_type hook(function_type) = 0;
18 virtual agent_type hook_once(function_type) = 0;
19 virtual void invoke(T...) = 0;
20 };
21
22 template <typename... T>
23 std::shared_ptr<Batch<T...>> make_queue();
24
25 template <typename... T>
26 std::shared_ptr<Batch<T...>> make_stack();
27
28 } // control
29 } // om636
File test/example.json copied from file test/test.json (similarity 63%) (mode: 100644) (index b632f06..7bb83e4)
3 3 "lib/dynamo/def.json" "lib/dynamo/def.json"
4 4 ], ],
5 5 "sources": [ "sources": [
6 "src/main.cpp",
7 "src/batch.h"
6 "src/example.cpp"
8 7 ] ]
9 }
8 }
File test/lib/circuit/.gitignore added (mode: 100644) (index 0000000..9b920a4)
1 .DS_Store
2 node_modules/
3 test/tmp
4 test/lib
File test/lib/circuit/EXAMPLE.md added (mode: 100644) (index 0000000..0505168)
1 const fs = require('fs'),
2 path = require('path'),
3 tbt = "```";
4
5 template = `
6 ## Example
7 ${tbt}
8 #include <tmp/src/test.h>
9
10 #include <lib/circuit/src/index.h>
11
12 using namespace std;
13 using namespace om636::circuit;
14
15 int main()
16 {
17 CircuitStack<int> s;
18
19 s.push(88);
20 s.push(77);
21
22 int i;
23 s.wait_pop(i);
24 if (s.check_pop(i)) {
25
26 }
27 }
28 ${tbt}
29 `;
File test/lib/circuit/README.md added (mode: 100644) (index 0000000..7b85e05)
1 # circuit
2
3 Syncronize container operations for single objects
4
5 ## Interface
6 ```
7 #pragma once
8
9 namespace om636 {
10 namespace circuit {
11
12 template <class T>
13 struct Circuit {
14 typedef T value_type;
15
16 virtual ~Circuit() = default;
17 virtual void push(value_type&&) = 0;
18 virtual bool check_pop(value_type&) = 0;
19 virtual void wait_pop(value_type&) = 0;
20 virtual Circuit* clone() const = 0;
21 };
22
23 } // circuit
24 } // om636
25
26 ```
27
28
29 ## Example
30 ```
31 #include <tmp/src/test.h>
32
33 #include <lib/circuit/src/index.h>
34
35 using namespace std;
36 using namespace om636::circuit;
37
38 int main()
39 {
40 CircuitStack<int> s;
41
42 s.push(88);
43 s.push(77);
44
45 int i;
46 s.wait_pop(i);
47 if (s.check_pop(i)) {
48
49 }
50 }
51 ```
52
File test/lib/circuit/circuit.json added (mode: 100644) (index 0000000..cf28781)
1 {
2 "name": "circuit",
3 "sources": [
4 "src/factory.h",
5 "src/interface.h",
6 "src/impl/stack.h",
7 "src/impl/queue.h",
8 "src/impl/curcuit_host.h",
9 "src/impl/curcuit_host.hxx"
10 ]
11 }
File test/lib/circuit/package.json added (mode: 100644) (index 0000000..5a7c3ec)
1 {
2 "name": "circuit",
3 "version": "1.0.0",
4 "description": "Syncronize container operations for single objects",
5 "main": "index.js",
6 "directories": {
7 "test": "test"
8 },
9 "scripts": {
10 "test": "crimp -g test/test.json",
11 "format": "clang-format -i --style=Webkit src/*.h src/impl/*.h src/impl/*.hxx test/src/*.cpp",
12 "generateDoc": "doc-tool package_header src_interface ./EXAMPLE.md > README.md"
13 },
14 "author": "",
15 "license": "ISC"
16 }
File test/lib/circuit/src/factory.h added (mode: 100644) (index 0000000..de27669)
1 #pragma once
2
3 #include "impl/circuit_host.h"
4 #include "impl/queue.h"
5 #include "impl/stack.h"
6
7 namespace om636 {
8 namespace circuit {
9
10 template <typename T>
11 std::shared_ptr<Circuit<T>> make_stack()
12 {
13 return std::make_shared<CircuitHost<T, StackPolicy>>();
14 }
15
16 template <typename T>
17 std::shared_ptr<Circuit<T>> make_queue()
18 {
19 return std::make_shared<CircuitHost<T, QueuePolicy>>();
20 }
21 } // circuit
22 } // om636
File test/lib/circuit/src/impl/circuit_host.h added (mode: 100644) (index 0000000..375f033)
1 #pragma once
2
3 #include <condition_variable>
4 #include <mutex>
5 #include <thread>
6
7 #include "../interface.h"
8
9 namespace om636 {
10 namespace circuit {
11
12 template <typename T, template <typename> class U>
13 struct CircuitHost
14 : Circuit<T>,
15 U<T> {
16 typedef Circuit<T> base_type;
17 using typename base_type::value_type;
18
19 CircuitHost() = default;
20 CircuitHost(const CircuitHost&);
21 CircuitHost(CircuitHost&&);
22 CircuitHost& operator=(CircuitHost);
23
24 void swap(CircuitHost&);
25 bool empty() const;
26 bool is_locked() const;
27
28 ~CircuitHost() override = default;
29 void push(value_type&&) override;
30 bool check_pop(value_type&) override;
31 void wait_pop(value_type&) override;
32 CircuitHost* clone() const override;
33
34 private:
35 typedef U<T> policy_type;
36 typedef std::lock_guard<std::mutex> lock_type;
37 typedef std::mutex mutex_type;
38
39 mutable mutex_type m_mutex;
40 std::condition_variable m_condition;
41 };
42
43 } // circuit
44 } // om636
45
46 #include "circuit_host.hxx"
File test/lib/circuit/src/impl/circuit_host.hxx added (mode: 100644) (index 0000000..fdf9742)
1 namespace om636 {
2 namespace circuit {
3
4 /////////////////////////////////////////////////////////////////////////////////////////////
5 template <typename T, template <typename> class U>
6 CircuitHost<T, U>::CircuitHost(const CircuitHost& rhs)
7 {
8 typedef std::unique_lock<mutex_type> lock_type;
9
10 lock_type left_lock(m_mutex, std::defer_lock);
11 lock_type right_lock(rhs.m_mutex, std::defer_lock);
12 std::lock(left_lock, right_lock);
13
14 policy_type::on_copy(*this, rhs);
15 }
16
17 /////////////////////////////////////////////////////////////////////////////////////////////
18 template <typename T, template <typename> class U>
19 CircuitHost<T, U>::CircuitHost(CircuitHost&& rhs)
20 {
21 lock_type lock(m_mutex);
22 policy_type::on_init(*this, rhs);
23 }
24
25 /////////////////////////////////////////////////////////////////////////////////////////////
26 template <typename T, template <typename> class U>
27 CircuitHost<T, U>& CircuitHost<T, U>::operator=(CircuitHost rhs)
28 {
29 swap(rhs);
30 return *this;
31 }
32
33 /////////////////////////////////////////////////////////////////////////////////////////////
34 template <typename T, template <typename> class U>
35 void CircuitHost<T, U>::swap(CircuitHost& rhs)
36 {
37 if (this == &rhs)
38 return;
39
40 typedef std::unique_lock<mutex_type> lock_type;
41
42 lock_type left_lock(m_mutex, std::defer_lock);
43 lock_type right_lock(rhs.m_mutex, std::defer_lock);
44 std::lock(left_lock, right_lock);
45
46 policy_type::on_swap(*this, rhs);
47 }
48
49 /////////////////////////////////////////////////////////////////////////////////////////////
50 template <typename T, template <typename> class U>
51 bool CircuitHost<T, U>::empty() const
52 {
53 lock_type lock(m_mutex);
54 return policy_type::on_empty(*this);
55 }
56
57 /////////////////////////////////////////////////////////////////////////////////////////////
58 template <typename T, template <typename> class U>
59 bool CircuitHost<T, U>::is_locked() const
60 {
61 bool result(false);
62 std::thread([this, &result]() {
63 result = m_mutex.try_lock();
64 if (result) {
65 m_mutex.unlock();
66 }
67 }).join();
68 return !result;
69 }
70
71 /////////////////////////////////////////////////////////////////////////////////////////////
72 template <typename T, template <typename> class U>
73 void CircuitHost<T, U>::push(value_type&& v)
74 {
75 lock_type lock(m_mutex);
76
77 policy_type::on_push(*this, std::move(v));
78 m_condition.notify_one();
79 }
80
81 /////////////////////////////////////////////////////////////////////////////////////////////
82 template <typename T, template <typename> class U>
83 bool CircuitHost<T, U>::check_pop(value_type& value)
84 {
85 lock_type lock(m_mutex);
86
87 if (policy_type::on_empty(*this))
88 return false;
89
90 policy_type::on_pop(*this, value);
91 return true;
92 }
93
94 /////////////////////////////////////////////////////////////////////////////////////////////
95 template <typename T, template <typename> class U>
96 void CircuitHost<T, U>::wait_pop(value_type& value)
97 {
98 std::unique_lock<std::mutex> lock(m_mutex);
99 m_condition.wait(lock, [this] { return !policy_type::on_empty(*this); });
100 policy_type::on_pop(*this, value);
101 }
102
103 /////////////////////////////////////////////////////////////////////////////////////////////
104 template <typename T, template <typename> class U>
105 auto CircuitHost<T, U>::clone() const -> CircuitHost*
106 {
107 return new CircuitHost(*this);
108 }
109
110 } // circuit
111 } // om636
File test/lib/circuit/src/impl/queue.h added (mode: 100644) (index 0000000..b4aaa20)
1 #pragma once
2
3 #include <queue>
4
5 namespace om636 {
6 namespace circuit {
7
8 template <typename T>
9 struct QueuePolicy {
10 typedef T value_type;
11
12 template <class U>
13 static void on_init(U& lhs, U&& rhs)
14 {
15 ASSERT(lhs.is_locked());
16 ASSERT(rhs.is_locked());
17 lhs.m_queue = std::move(rhs.m_queue);
18 }
19
20 template <class U>
21 static void on_copy(U& lhs, const U& rhs)
22 {
23 ASSERT(lhs.is_locked());
24 ASSERT(rhs.is_locked());
25 lhs.m_queue = rhs.m_queue;
26 }
27
28 template <class U>
29 static void on_swap(U& lhs, U& rhs)
30 {
31 ASSERT(lhs.is_locked());
32 ASSERT(rhs.is_locked());
33 lhs.m_queue.swap(rhs.m_queue);
34 }
35
36 template <class U>
37 static void on_pop(U& lhs, value_type& v)
38 {
39 ASSERT(lhs.is_locked());
40 v = std::move(lhs.m_queue.front());
41 lhs.m_queue.pop();
42 }
43
44 template <class U>
45 static void on_push(U& lhs, value_type&& v)
46 {
47 ASSERT(lhs.is_locked());
48 lhs.m_queue.push(std::move(v));
49 }
50
51 template <class U>
52 static bool on_empty(U& h)
53 {
54 ASSERT(h.is_locked());
55 return h.m_queue.empty();
56 }
57
58 private:
59 std::queue<value_type> m_queue;
60 };
61
62 } // circuit
63 } // om636
File test/lib/circuit/src/impl/stack.h added (mode: 100644) (index 0000000..20c2f4c)
1 #pragma once
2
3 #include <stack>
4
5 namespace om636 {
6 namespace circuit {
7
8 template <typename T>
9 struct StackPolicy {
10 typedef T value_type;
11
12 template <class U>
13 static void on_copy(U& lhs, const U& rhs)
14 {
15 ASSERT(lhs.is_locked());
16 ASSERT(rhs.is_locked());
17 lhs.m_stack = rhs.m_stack;
18 }
19
20 template <class U>
21 static void on_init(U& lhs, U&& rhs)
22 {
23 ASSERT(lhs.is_locked());
24 ASSERT(rhs.is_locked());
25 lhs.m_stack = std::move(rhs.m_stack);
26 }
27
28 template <class U>
29 static void on_swap(U& lhs, U& rhs)
30 {
31 ASSERT(lhs.is_locked());
32 ASSERT(rhs.is_locked());
33 lhs.m_stack.swap(rhs.m_stack);
34 }
35
36 template <class U>
37 static void on_pop(U& lhs, value_type& v)
38 {
39 ASSERT(lhs.is_locked());
40 v = std::move(lhs.m_stack.top());
41 lhs.m_stack.pop();
42 }
43
44 template <class U>
45 static void on_push(U& lhs, value_type&& v)
46 {
47 ASSERT(lhs.is_locked());
48 lhs.m_stack.push(std::move(v));
49 }
50
51 template <class U>
52 static bool on_empty(U& h)
53 {
54 ASSERT(h.is_locked());
55 return h.m_stack.empty();
56 }
57
58 private:
59 std::stack<value_type> m_stack;
60 };
61
62 } // circuit
63 } // om636
File test/lib/circuit/src/index.h added (mode: 100644) (index 0000000..aac2bba)
1 #pragma once
2
3 #include "impl/circuit_host.h"
4 #include "impl/queue.h"
5 #include "impl/stack.h"
6
7 namespace om636 {
8 namespace circuit {
9
10 template <typename T>
11 using CircuitStack = CircuitHost<T, StackPolicy>;
12
13 template <typename T>
14 using CircuitQueue = CircuitHost<T, QueuePolicy>;
15
16 } // circuit
17 } // om636
File test/lib/circuit/src/interface.h added (mode: 100644) (index 0000000..8b562d1)
1 #pragma once
2
3 namespace om636 {
4 namespace circuit {
5
6 template <class T>
7 struct Circuit {
8 typedef T value_type;
9
10 virtual ~Circuit() = default;
11 virtual void push(value_type&&) = 0;
12 virtual bool check_pop(value_type&) = 0;
13 virtual void wait_pop(value_type&) = 0;
14 virtual Circuit* clone() const = 0;
15 };
16
17 } // circuit
18 } // om636
File test/lib/circuit/test/example.json added (mode: 100644) (index 0000000..810ed56)
1 {
2 "import":[
3 "lib/circuit/circuit.json"
4 ],
5 "sources": [
6 "src/example.cpp"
7 ]
8 }
File test/lib/circuit/test/src/example.cpp added (mode: 100644) (index 0000000..52afea0)
1 #include <tmp/src/test.h>
2
3 #include <lib/circuit/src/index.h>
4
5 using namespace std;
6 using namespace om636::circuit;
7
8 int main()
9 {
10 CircuitStack<int> s;
11
12 s.push(88);
13 s.push(77);
14
15 s.wait_pop(i);
16 if (s.check_pop(i)) {
17 }
18 }
File test/lib/circuit/test/src/main.cpp added (mode: 100644) (index 0000000..df6a636)
1 #include <memory>
2 #include <vector>
3
4 #include <tmp/src/test.h>
5
6 #include <lib/circuit/src/index.h>
7
8 template <class T>
9 void test_wait_pop(T s)
10 {
11 auto tmp = std::thread([=]() {
12 int i(0);
13 s->wait_pop(i);
14 ASSERT(i == 99);
15 });
16
17 s->push(99);
18 tmp.join();
19 }
20
21 int main()
22 {
23 using namespace om636::circuit;
24
25 test_wait_pop(std::make_shared<CircuitStack<int>>());
26 test_wait_pop(std::make_shared<CircuitQueue<int>>());
27
28 CircuitQueue<int> a, b;
29 a.swap(b);
30
31 return 0;
32 }
File test/lib/circuit/test/test.json added (mode: 100644) (index 0000000..278ac7a)
1 {
2 "import":[
3 "lib/circuit/circuit.json"
4 ],
5 "sources": [
6 "src/main.cpp"
7 ]
8 }
File test/src/batch.h changed (mode: 100644) (index d597c61..47cff77)
1 #include <lib/circuit/src/impl/queue.h>
2
3 using namespace om636::control;
1 4 using namespace om636; using namespace om636;
2 5 using namespace std; using namespace std;
6 using namespace om636::circuit;
3 7
4 typedef std::function<void()> callback_type;
5 typedef control::Batch<callback_type> batch_type;
6
7 void check_traverse_with_arg()
8 void check_unhook_while_traverse()
8 9 { {
9 typedef function<void(int)> callback_type;
10 typedef control::Batch<callback_type> batch_type;
10 BatchImpl<QueuePolicy> batch;
11 unsigned passed(0);
11 12
12 unsigned test_passed(0);
13 typename BatchImpl<QueuePolicy>::listener_type temp(batch.hook([&]() {
14 ++passed;
15 temp.reset();
16 }));
17
18 batch.invoke();
19 batch.invoke();
20
21 ASSERT(passed == 1)
22 (passed);
23 }
24
25 void dead_agent_removal()
26 {
27 typedef BatchImpl<QueuePolicy, int> batch_type;
13 28 batch_type batch; batch_type batch;
29 batch.hook([](int) {});
30 batch.invoke(9);
31
32 ASSERT(batch.impl_ref().empty() && "dead agent removal");
33 }
14 34
35 void check_traverse_with_arg()
36 {
37 BatchImpl<QueuePolicy, int> batch;
38 int v = 0;
15 39 auto p(batch.hook([&](int i) { auto p(batch.hook([&](int i) {
16 ASSERT(i == 99);
17 ++test_passed;
40 v = i;
18 41 })); }));
19 42
20 batch.traverse(99);
43 batch.invoke(99);
21 44
22 ASSERT(test_passed == 1);
23 FOOTER;
45 ASSERT(v == 99);
24 46 } }
25 47
26 48 void check_traverse_with_args() void check_traverse_with_args()
27 49 { {
28 typedef function<void(int, int)> callback_type;
29 typedef control::Batch<callback_type> batch_type;
50 typedef BatchImpl<QueuePolicy, int, int> batch_type;
30 51
31 52 unsigned test_passed(0); unsigned test_passed(0);
32 53 batch_type batch; batch_type batch;
 
... ... void check_traverse_with_args()
37 58 ++test_passed; ++test_passed;
38 59 })); }));
39 60
40 batch.traverse(99, 3);
61 batch.invoke(99, 3);
41 62
42 63 ASSERT(test_passed == 1); ASSERT(test_passed == 1);
43 FOOTER;
44 64 } }
45 65
46 66 void check_traverse_while_traverse() void check_traverse_while_traverse()
47 67 { {
48 batch_type batch;
68 BatchImpl<QueuePolicy> batch;
49 69 unsigned passed(0); unsigned passed(0);
50 70
51 71 auto p(batch.hook([&]() { auto p(batch.hook([&]() {
52 72 ++passed; ++passed;
53 batch.traverse();
73 batch.invoke();
54 74 })); }));
55 75
56 batch.traverse();
76 batch.invoke();
57 77
58 78 ASSERT(passed == 1); ASSERT(passed == 1);
59 FOOTER;
60 79 } }
61 80
62 81 void check_traverse() void check_traverse()
63 82 { {
64 batch_type batch;
83 BatchImpl<QueuePolicy> batch;
65 84 unsigned passed(0); unsigned passed(0);
66 85
67 86 auto temp(batch.hook([&]() { auto temp(batch.hook([&]() {
68 87 ++passed; ++passed;
69 88 })); }));
70 89
71 batch.traverse();
72 batch.traverse();
90 batch.invoke();
91 batch.invoke();
73 92
74 93 ASSERT(passed == 2); ASSERT(passed == 2);
75 FOOTER;
76 }
94 }
File test/src/example.cpp added (mode: 100644) (index 0000000..71bf8dd)
1 #include <tmp/src/test.h>
2
3 #include <lib/dynamo/src/impl/batch.h>
4 #include <lib/dynamo/src/interface.h>
5
6 int main()
7 {
8 auto b = om636::control::make_queue<int>();
9
10 int sum{ 0 };
11
12 auto q = b->hook([&](int i) { sum += i; });
13 auto p = b->hook([&](int i) { sum *= i; });
14 b->invoke(5);
15 ASSERT(sum == 25);
16 return 0;
17 }
File test/src/main.cpp changed (mode: 100644) (index 6e4b832..59f5bb6)
3 3
4 4 #include <tmp/src/test.h> #include <tmp/src/test.h>
5 5
6 #include <lib/dynamo/src/batch.h>
6 #include <lib/dynamo/src/impl/batch.h>
7 7
8 8 #include "batch.h" #include "batch.h"
9 9
10 10 int main(int argc, const char* argv[]) int main(int argc, const char* argv[])
11 11 { {
12 12 check_traverse(); check_traverse();
13 //check_traverse_while_traverse();
13 check_unhook_while_traverse();
14 check_traverse_while_traverse();
14 15 check_traverse_with_arg(); check_traverse_with_arg();
15 16 check_traverse_with_args(); check_traverse_with_args();
16
17 dead_agent_removal();
17 18 return 0; return 0;
18 }
19 }
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/mucbuc/dynamo

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/mucbuc/dynamo

Clone this repository using git:
git clone git://git.rocketgit.com/user/mucbuc/dynamo

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main