派生自 development/c++

zhangjixing
2019-01-18 9f08028f23d9e5cbfa159bec1e07d63b141a6809
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
#ifndef MYSEM_H_XZL_201808141050
#define MYSEM_H_XZL_201808141050
 
#include <chrono>
#include <mutex>
#include <condition_variable>
 
enum {
    SEMPHORE_FAIL = (-1),
    SEMPHORE_SUCCESS = 0,
    SEMPHORE_TIME_OUT = 1
};
 
class Semphore {
public:
    Semphore(const int sigs = 0) : m_signals(sigs), m_blocked(0) {}
 
    ~Semphore() {}
 
private:
    Semphore(const Semphore &) = delete;
 
    Semphore(Semphore &&) = delete;
 
    Semphore operator=(const Semphore &) = delete;
 
private:
    std::mutex m_mtx;
    std::condition_variable m_cv;
    int m_signals;
    int m_blocked;
 
public:
    int wait(const int time_out_ms = (-1)) {
        std::unique_lock<std::mutex> ul(m_mtx);
        if (m_signals > 0) {
            --m_signals;
            return SEMPHORE_SUCCESS;
        } else {
            ++m_blocked;
        }
 
        if (time_out_ms >= 0) {
            std::chrono::milliseconds wait_time_ms(time_out_ms);
            auto result = m_cv.wait_for(ul, wait_time_ms, [&] { return m_signals > 0; });
            --m_blocked;
            if (result) {
                --m_signals;
                return SEMPHORE_SUCCESS;
            } else {
                return SEMPHORE_TIME_OUT;
            }
        } else {
            m_cv.wait(ul, [&] { return m_signals > 0; });
            --m_blocked;
            --m_signals;
            return SEMPHORE_SUCCESS;
        }
    }
 
    inline void signal(const int count = 1) {
        std::lock_guard<std::mutex> lg(m_mtx);
        m_signals += count;
        if (m_blocked > 0) {
            m_cv.notify_one();
        }
    }
};
 
#endif