-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy paththreadsafe_list.h
100 lines (81 loc) · 2.79 KB
/
threadsafe_list.h
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
//
// Created by yryang on 2021/10/19.
//
#ifndef CPPTEST_THREADSAFE_LIST_H
#define CPPTEST_THREADSAFE_LIST_H
#include <iostream>
namespace threadsafe_list{
template <typename T>
class threadsafe_list {
private:
struct node{
std::mutex mtx;
std::shared_ptr<T> data;
std::unique_ptr<node> next;
node(): next(){
}
node(T const& value): data(std::make_shared<T>(value)){}
}; // end of struct node
node head_; //dummpy head
public:
threadsafe_list(){}
~threadsafe_list(){
remove_if<bool (node const&)>([](node const&){return true;});
}
void push_front(T const& value){
std::unique_ptr<node> new_node(new node(value));
std::lock_guard<std::mutex> lockGuard(head_.mtx);
new_node->next = std::move(head_.next);
head_.next = std::move(new_node);
}
template<typename Function>
void for_each(Function f){
node* current = &head_;
std::unique_lock<std::mutex> lk(current->mtx);
while (node* const next = current->next.get()){
std::unique_lock<std::mutex> next_lk(next->mtx);
lk.unlock();
f(*next->data);
current = next;
lk = std::move(next_lk);
}
}
template<typename Predicate>
std::shared_ptr<T> find_first_if(Predicate p){
node* current = &head_;
std::unique_lock<std::mutex> lk(current->mtx);
while (node* const next = current->next.get()){
std::unique_lock<std::mutex> next_lk(next->mtx);
lk.unlock();
if(p(*next->data)){
return next->data;
}
current = next;
lk = std::move(next_lk);
}
return std::shared_ptr<T>();
}
template<typename Predicate>
void remove_if(Predicate p){
node* current = &head_;
std::unique_lock<std::mutex> lk(current->mtx);
while (node* const next = current->next.get()){
std::unique_lock<std::mutex> next_lk(next->mtx);
if(p(*next->data)){
std::unique_ptr<node> old_next = std::move(current->next);
current->next = std::move(next->next);
next_lk.unlock();
}else{
lk.unlock();
current = next;
lk = std::move(next_lk);
}
}
}
bool empty(){
std::lock_guard<std::mutex> lockGuard(head_.mtx);
return head_.next == nullptr;
}
};
}
#endif //CPPTEST_THREADSAFE_LIST_H