callback
Prerequisites:
增加callback
在condition_variable的程式碼中加上callback的程式碼
主要程式碼如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class SafeQueue {
//成員變數為函式,函式類型為void(const string& msg)
function<void(const string& msg)> m_callback;
public:
//成員函式模板
//參數1函式,參數2物件(可能沒有物件所以用可變參數Args...)
template<typename Func, typename... Args>
void callback(Func&& func, Args&&... args) {
//args是物件,若呼叫的函式是物件成員函式,第二個參數就是物件
//若是函式,就不需要傳入第2個參數(因為可能沒有第2個參數,所以用可變參數Args...)
m_callback = bind(forward<Func>(func), forward<Args>(args)..., std::placeholders::_1);
}
.... 以下程式碼略過
//若有設定回呼函式
if(m_callback)
//執行回呼函式,並把回呼函式的參數傳入
m_callback(msg);
.... 以下程式碼略過
完整程式碼
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
class SafeQueue {
mutex m_mtx;//執行緒
condition_variable m_cond;//條件
queue<string> m_que;
//成員變數為函式,函式類型為void(const string& msg)
function<void(const string& msg)> m_callback;
public:
//成員函式模板
//參數1函式,參數2物件(可能沒有物件所以用可變參數Args...)
template<typename Func, typename... Args>
void callback(Func&& func, Args&&... args) {
//args是物件,若呼叫的函式是物件成員函式,第二個參數就是物件
//若是函式,就不需要傳入第2個參數(因為可能沒有第2個參數,所以用可變參數Args...)
m_callback = bind(forward<Func>(func), forward<Args>(args)..., std::placeholders::_1);
}
void push(string& msg) {
//加鎖,scope的範圍為函式內
lock_guard<mutex> lock(m_mtx);
m_que.push(msg);//放入訊息
m_cond.notify_one();//通知執行緒來接收訊息
}
void pop(){
//無限迴圈等待有訊息通知
while(true) {
//每個執行緒有獨立的msg變數
string msg;
//加鎖
//因為m_cond.wait()參數只支援unique_lock
unique_lock<mutex> lock(m_mtx);
// queue是空的才等待
while(m_que.empty()) {
//queue沒資料就等待
m_cond.wait(lock);
}
//被通知接收資料
//若queue有資料了,才做下面的事情
msg = m_que.front();//拿出第一個元素
m_que.pop();//移除元素
//解鎖
lock.unlock();
//若有設定回呼函式
if(m_callback)
//執行回呼函式,並把回呼函式的參數傳入
m_callback(msg);
//如果msg是end就不要再等待接收訊息
if(msg == "END") break;
}
}
};
callback是成員函式
1
2
3
Student student;
//參數為物件成員函式,第二個參數是物件
safeQue.callback(&Student::print, student);
完整程式碼
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
void print(const string& msg) {
cout << " Msg = " << msg << endl;
}
class SafeQueue {
mutex m_mtx;//執行緒
condition_variable m_cond;//條件
queue<string> m_que;
function<void(const string& msg)> m_callback;
public:
template<typename Func, typename... Args>
void callback(Func&& func, Args&&... args) {
m_callback = bind(forward<Func>(func), forward<Args>(args)..., std::placeholders::_1);
}
void push(string& msg) {
//加鎖,scope的範圍為函式內
lock_guard<mutex> lock(m_mtx);
m_que.push(msg);//放入訊息
m_cond.notify_one();//通知執行緒來接收訊息
}
void pop(){
//無限迴圈等待有訊息通知
while(true) {
//每個執行緒有獨立的msg變數
string msg;
//加鎖
//因為m_cond.wait()參數只支援unique_lock
unique_lock<mutex> lock(m_mtx);
// queue是空的才等待
while(m_que.empty()) {
//queue沒資料就等待
m_cond.wait(lock);
}
//被通知接收資料
//若queue有資料了,才做下面的事情
msg = m_que.front();//拿出第一個元素
m_que.pop();//移除元素
//解鎖
lock.unlock();
if(m_callback) m_callback(msg);
//如果msg是end就不要再等待接收訊息
if(msg == "END") break;
}
}
};
int main() {
//建立物件
SafeQueue safeQue;
//建立物件
Student student;
//參數為物件成員函式,第二個參數是物件
safeQue.callback(&Student::print, student);
//建立3個執行緒
thread t1(&SafeQueue::pop, &safeQue);
thread t2(&SafeQueue::pop, &safeQue);
thread t3(&SafeQueue::pop, &safeQue);
//產生100個訊息
for(int i = 0; i < 100; i++) {
string temp_msg = "msg" + to_string(i);
safeQue.push(temp_msg);
}
//產生結束訊息,跳離無限迴圈,不要再等待接收訊息
for(int i = 0; i < 3; i++) {
string end_msg = "END";
safeQue.push(end_msg);
}
//執行緒記憶體釋放
t1.join();
t2.join();
t3.join();
return 0;
}
Msg = msg0
Msg = Msg = msg2
Msg = Msg = msg4
msg1
Msg = Msg = msg3msg6msg5
Msg = msg7 Msg = msg9
Msg =
.
.
.
以下截掉
callback參數為函式
以下新增print()函式 callback函式設為print
safeQue.callback(print);
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
void print(const string& msg) {
cout << " Msg = " << msg << endl;
}
class SafeQueue {
.
.
.
以下截掉(跟前一個程式碼一模一樣)
}
int main() {
//建立物件
SafeQueue safeQue;
//設定回呼函式
safeQue.callback(print);
//建立3個執行緒
thread t1(&SafeQueue::pop, &safeQue);
thread t2(&SafeQueue::pop, &safeQue);
thread t3(&SafeQueue::pop, &safeQue);
//產生100個訊息
for(int i = 0; i < 100; i++) {
string temp_msg = "msg" + to_string(i);
safeQue.push(temp_msg);
}
//產生結束訊息,跳離無限迴圈,不要再等待接收訊息
for(int i = 0; i < 3; i++) {
string end_msg = "END";
safeQue.push(end_msg);
}
//執行緒記憶體釋放
t1.join();
t2.join();
t3.join();
return 0;
}