semaphore作為condition

Prerequisites:

延續先前semaphore與mutex的範例,這頁是semaphore作為condition的範例,使用circular queue作為範例

檔名:push_test.cpp

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
#include <iostream>
#include "semaph.h"
#include "cir_queue.h"
#include <sys/shm.h>
#include <cstring>
using namespace std;
struct SharedData {
  char data[100];
};
int main() {
  using ElemType = int;
  // 注意轉型
  int shmid = shmget(0x0001, sizeof(CircularQueue<int, 6>), 0640|IPC_CREAT);
  if (shmid == -1) {
    cout << "記憶體不足或權限不足,無法建立空間。" << endl;
    return -1;
  }
  cout << "shmid = " << shmid << endl;
  // 注意轉型
  CircularQueue<int, 6>* cir_que = (CircularQueue<int, 6>*)shmat(shmid, nullptr, 0);
  if (cir_que == (void*)-1) {
    cout << "shmat() failed" << endl;
    return -1;
  }
  // 使用共用記憶體,不會呼叫CircularQueue的建構子,所以要手動呼叫Init()
  cir_que->Init();
  // 建立mutex
  Semaph mutex;
  mutex.init(0x0001);
  // 建立condition
  Semaph condition;
  condition.init(0x0002, 0, 0);
  // lock加鎖
  mutex.wait();
  // push的流程
  ElemType tmp_val;
  tmp_val = 11;
  cir_que->push(tmp_val);
  tmp_val = 12;
  cir_que->push(tmp_val);
  tmp_val = 13;
  cir_que->push(tmp_val);
  // unlock解鎖
  mutex.post();
  // 計數功能
  condition.post(3);  // 參數3代表生產3個資料
  cir_que->print();
  shmdt(cir_que);
}

檔名:pop_test.cpp

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
#include <iostream>
#include "semaph.h"
#include "cir_queue.h"
#include <sys/shm.h>
#include <cstring>
using namespace std;
struct SharedData {
  char data[100];
};
int main() {
  using ElemType = int;
  // 注意轉型
  int shmid = shmget(0x0001, sizeof(CircularQueue<int, 6>), 0640|IPC_CREAT);
  if (shmid == -1) {
    cout << "記憶體不足或權限不足,無法建立空間。" << endl;
    return -1;
  }
  cout << "shmid = " << shmid << endl;
  // 注意轉型
  CircularQueue<int, 6>* cir_que = (CircularQueue<int, 6>*)shmat(shmid, nullptr, 0);
  if (cir_que == (void*)-1) {
    cout << "shmat() failed" << endl;
    return -1;
  }
  // 使用共用記憶體,不會呼叫CircularQueue的建構子,所以要手動呼叫Init()
  cir_que->Init();
  // 建立mutex
  Semaph mutex;
  mutex.init(0x0001);
  // 建立condition
  Semaph condition;
  condition.init(0x0002, 0, 0);
  // 存放pop出來的資料
  ElemType tmp_val;
  while (true) {
    // lock加鎖
    mutex.wait();
    while (cir_que->empty()) {  // 若佇列為空,無限迴圈
      mutex.post();  // unlock解鎖
      condition.wait();  // 等待有資料,沒資料就一直卡在這
      // 若有資料就會執行以下這行,並離開cir_que->empty的迴圈
      mutex.wait();  // lock加鎖
    }
    // pop資料
    tmp_val = cir_que->front();
    cout << "tmp_val = " << tmp_val << endl;
    cir_que->pop();
    // unlock解鎖
    mutex.post();
    cout << "val = " << tmp_val << endl;
    // 假設處理資料要花10秒鐘
    sleep(10);
  }
  shmdt(cir_que);
}

編譯指令

g++ -o push_test push_test.cpp semaph.cpp
g++ -o pop_test pop_test.cpp semaph.cpp

打開二個終端機視窗

一個執行push

./push_test

一個執行pop

./pop_test

執行結果

push

$ ./push_test
shmid = 5
Queue is full.
Queue is full.
Queue is full.
11,12,13,11,12,13,

$ ./push_test
shmid = 5
11,12,13,

pop

$ ./pop_test
shmid = 5
tmp_val = 11
val = 11
tmp_val = 12
val = 12
tmp_val = 13
val = 13
tmp_val = 11
val = 11
tmp_val = 12
val = 12
tmp_val = 13
val = 13
tmp_val = 11
val = 11
tmp_val = 12
val = 12
tmp_val = 13
val = 13
^C

results matching ""

    No results matching ""