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 |