mucbuc / circuit (public) (License: GPLv3) (since 2020-06-28) (hash sha1)
Synchronize container operations for single objects
List of commits:
Subject Hash Author Date (UTC)
init 01daaea5899ac77acb8ec0c15583573d78eb9f31 mucbuc 2020-01-12 03:10:36
Commit 01daaea5899ac77acb8ec0c15583573d78eb9f31 - init
Author: mucbuc
Author date (UTC): 2020-01-12 03:10
Committer name: mucbuc
Committer date (UTC): 2020-01-12 03:10
Parent(s):
Signing key:
Tree: c3bd1f7314d36ffccd1088845ea6256c54cc7a01
File Lines added Lines deleted
.gitignore 3 0
circuit.json 11 0
package.json 14 0
src/factory.h 23 0
src/impl/circuit_host.h 44 0
src/impl/circuit_host.hxx 87 0
src/impl/queue.h 55 0
src/impl/stack.h 55 0
src/interface.h 20 0
test/src/main.cpp 30 0
test/test.json 8 0
File .gitignore added (mode: 100644) (index 0000000..6f7455b)
1 .DS_Store
2 test/tmp
3 test/lib
File 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 package.json added (mode: 100644) (index 0000000..2dffab3)
1 {
2 "name": "circuit",
3 "version": "1.0.0",
4 "description": "",
5 "main": "index.js",
6 "directories": {
7 "test": "test"
8 },
9 "scripts": {
10 "test": "crimp -g test/test.json"
11 },
12 "author": "",
13 "license": "ISC"
14 }
File src/factory.h added (mode: 100644) (index 0000000..027ee94)
1 #pragma once
2
3 #include "impl/circuit_host.h"
4 #include "impl/stack.h"
5 #include "impl/queue.h"
6
7 namespace om636 {
8 namespace twice_size {
9
10 template<typename T>
11 Circuit<T> * make_stack()
12 {
13 return new CircuitHost<T, StackPolicy>();
14 }
15
16 template<typename T>
17 Circuit<T> * make_queue()
18 {
19 return new CircuitHost<T, QueuePolicy>();
20 }
21 } // twice_size
22 } // om636
23
File src/impl/circuit_host.h added (mode: 100644) (index 0000000..f466d65)
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 twice_size {
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(CircuitHost&&);
21 CircuitHost& operator=(CircuitHost);
22
23 void swap(CircuitHost&);
24 bool empty() const;
25 bool is_locked() const;
26
27 ~CircuitHost() override = default;
28 void push(value_type&&) override;
29 bool check_pop(value_type&) override;
30 void wait_pop(value_type&) override;
31
32 private:
33 typedef U<T> policy_type;
34 typedef std::lock_guard<std::mutex> lock_type;
35 typedef std::mutex mutex_type;
36
37 mutable mutex_type m_mutex;
38 std::condition_variable m_condition;
39 };
40
41 } // twice_size
42 } // om636
43
44 #include "circuit_host.hxx"
File src/impl/circuit_host.hxx added (mode: 100644) (index 0000000..a7f2410)
1 namespace om636 {
2 namespace twice_size {
3
4 /////////////////////////////////////////////////////////////////////////////////////////////
5 template <typename T, template <typename> class U>
6 CircuitHost<T, U>::CircuitHost(CircuitHost&& rhs)
7 {
8 lock_type lock(m_mutex);
9 policy_type::on_init(*this, rhs);
10 }
11
12 /////////////////////////////////////////////////////////////////////////////////////////////
13 template <typename T, template <typename> class U>
14 CircuitHost<T, U>& CircuitHost<T, U>::operator=(CircuitHost rhs)
15 {
16 swap(rhs);
17 return *this;
18 }
19
20 /////////////////////////////////////////////////////////////////////////////////////////////
21 template <typename T, template <typename> class U>
22 void CircuitHost<T, U>::swap(CircuitHost& rhs)
23 {
24 if (this == &rhs)
25 return;
26
27 typedef std::unique_lock<mutex_type> lock_type;
28
29 lock_type left_lock(m_mutex, std::defer_lock);
30 lock_type right_lock(rhs.m_mutex, std::defer_lock);
31 std::lock(left_lock, right_lock);
32
33 policy_type::on_swap(*this, rhs);
34 }
35
36 /////////////////////////////////////////////////////////////////////////////////////////////
37 template <typename T, template <typename> class U>
38 bool CircuitHost<T, U>::empty() const
39 {
40 lock_type lock(m_mutex);
41 return policy_type::on_empty(*this);
42 }
43
44 /////////////////////////////////////////////////////////////////////////////////////////////
45 template <typename T, template <typename> class U>
46 bool CircuitHost<T, U>::is_locked() const
47 {
48 bool result( false );
49 std::thread([this, & result]() {
50 result = m_mutex.try_lock();
51 }).join();
52 return !result;
53 }
54
55 /////////////////////////////////////////////////////////////////////////////////////////////
56 template <typename T, template <typename> class U>
57 void CircuitHost<T, U>::push(value_type&& v)
58 {
59 lock_type lock(m_mutex);
60
61 policy_type::on_push(*this, std::move(v));
62 m_condition.notify_one();
63 }
64
65 /////////////////////////////////////////////////////////////////////////////////////////////
66 template <typename T, template <typename> class U>
67 bool CircuitHost<T, U>::check_pop(value_type& value)
68 {
69 lock_type lock(m_mutex);
70
71 if (policy_type::on_empty(*this))
72 return false;
73
74 policy_type::on_pop(*this, value);
75 return true;
76 }
77
78 /////////////////////////////////////////////////////////////////////////////////////////////
79 template <typename T, template <typename> class U>
80 void CircuitHost<T, U>::wait_pop(value_type& value)
81 {
82 std::unique_lock<std::mutex> lock(m_mutex);
83 m_condition.wait(lock, [this] { return !policy_type::on_empty(*this); });
84 policy_type::on_pop(*this, value);
85 }
86 } // twice_size
87 } // om636
File src/impl/queue.h added (mode: 100644) (index 0000000..d06dac5)
1 #pragma once
2
3 #include <queue>
4
5 namespace om636 {
6 namespace twice_size {
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_swap(U& lhs, U& rhs)
22 {
23 ASSERT(lhs.is_locked());
24 ASSERT(rhs.is_locked());
25 lhs.m_queue.swap(rhs);
26 }
27
28 template <class U>
29 static void on_pop(U& lhs, value_type& v)
30 {
31 ASSERT(lhs.is_locked());
32 v = std::move(lhs.m_queue.front());
33 lhs.m_queue.pop();
34 }
35
36 template <class U>
37 static void on_push(U& lhs, value_type&& v)
38 {
39 ASSERT(lhs.is_locked());
40 lhs.m_queue.push(std::move(v));
41 }
42
43 template <class U>
44 static bool on_empty(U& h)
45 {
46 ASSERT(h.is_locked());
47 return h.m_queue.empty();
48 }
49
50 private:
51 std::queue<value_type> m_queue;
52 };
53
54 } // twice_size
55 } // om636
File src/impl/stack.h added (mode: 100644) (index 0000000..c59cdee)
1 #pragma once
2
3 #include <stack>
4
5 namespace om636 {
6 namespace twice_size {
7
8 template <typename T>
9 struct StackPolicy {
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_stack = std::move(rhs.m_stack);
18 }
19
20 template <class U>
21 static void on_swap(U& lhs, U& rhs)
22 {
23 ASSERT(lhs.is_locked());
24 ASSERT(rhs.is_locked());
25 lhs.m_stack.swap(rhs);
26 }
27
28 template <class U>
29 static void on_pop(U& lhs, value_type& v)
30 {
31 ASSERT(lhs.is_locked());
32 v = std::move(lhs.m_stack.top());
33 lhs.m_stack.pop();
34 }
35
36 template <class U>
37 static void on_push(U& lhs, value_type&& v)
38 {
39 ASSERT(lhs.is_locked());
40 lhs.m_stack.push(std::move(v));
41 }
42
43 template <class U>
44 static bool on_empty(U& h)
45 {
46 ASSERT(h.is_locked());
47 return h.m_stack.empty();
48 }
49
50 private:
51 std::stack<value_type> m_stack;
52 };
53
54 } // twice_size
55 } // om636
File src/interface.h added (mode: 100644) (index 0000000..96c1687)
1 #ifndef TWICE_SIZE_INTERFACE_H_0494LLJLKJ23
2 #define TWICE_SIZE_INTERFACE_H_0494LLJLKJ23
3
4 namespace om636 {
5 namespace twice_size {
6
7 template <class T>
8 struct Circuit {
9 typedef T value_type;
10
11 virtual ~Circuit() = default;
12 virtual void push(value_type&&) = 0;
13 virtual bool check_pop(value_type&) = 0;
14 virtual void wait_pop(value_type&) = 0;
15 };
16
17 } // twice_size
18 } // om636
19
20 #endif // TWICE_SIZE_INTERFACE_H_0494LLJLKJ23
File test/src/main.cpp added (mode: 100644) (index 0000000..b082b21)
1 #include <memory>
2 #include <vector>
3
4 #include <tmp/src/test.h>
5
6 #include <lib/circuit/src/factory.h>
7
8 template <class T>
9 void test_wait_pop(T s)
10 {
11
12 auto tmp = std::thread([=]() {
13 int i(0);
14 s->wait_pop(i);
15 ASSERT(i == 99);
16 });
17
18 s->push(99);
19 tmp.join();
20 }
21
22 int main()
23 {
24 using namespace om636::twice_size;
25
26 test_wait_pop(std::shared_ptr<Circuit<int>>(make_stack<int>()));
27 test_wait_pop(std::shared_ptr<Circuit<int>>(make_queue<int>()));
28
29 return 0;
30 }
File 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 }
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/circuit

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

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

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