summaryrefslogtreecommitdiffstats
path: root/K2LABI/Common/SystemUtilities/SEvent.h
blob: b95c6ee7ae85151b8c618d96ae2eda2b5c0ef9c6 (plain)
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#ifndef S_EVENT_H
#define S_EVENT_H

#include "k2l-type.h"
#include <pthread.h>
#include <errno.h>
#include <stdio.h>

//-----------------------------------------------------------------------------
enum
{
    ERR_EVENT_BASE            = -56700,
    ERR_EVENT_ALREADY_CREATED = ERR_EVENT_BASE - 1,
    ERR_EVENT_INIT            = ERR_EVENT_BASE - 2,
    ERR_EVENT_TIMEOUT         = ERR_EVENT_BASE - 4,
};

//-----------------------------------------------------------------------------
class CEvent
{
public:
    CEvent(bool bCreate = false);
    ~CEvent();

    int create();
    int close();
    int wait(); // infinite
    int waitMsec   (long lMsecs);
    int waitSeconds(long lSeconds);
    int signal();
    int reset();

private:
    bool m_created;
    pthread_mutex_t m_mutex;
};

//-----------------------------------------------------------------------------
inline CEvent::CEvent(bool bCreate) : m_created(bCreate)
{
    if (bCreate)
        create();
}

//-----------------------------------------------------------------------------
inline CEvent::~CEvent()
{
    close();
}

//-----------------------------------------------------------------------------
inline int CEvent::create()
{
    if (m_created)
        return ERR_EVENT_ALREADY_CREATED;
    
    int err = pthread_mutex_init(&m_mutex, NULL);
    
    //Lock the mutex, so the next locking attempt will block
    if (!err)
    {
        err = pthread_mutex_lock (&m_mutex);
    }
    if (!err)
    {
        m_created = true;
    }
    else
    {
        fprintf(stderr, "Failed to create CEvent, last err: %d\n", err);
    }
    
    return err;
}

//-----------------------------------------------------------------------------
inline int CEvent::close()
{
    if (!m_created)
        return ERR_EVENT_INIT;

    
    return pthread_mutex_destroy (&m_mutex);
}

//-----------------------------------------------------------------------------
inline int CEvent::wait() // infinite
{
    return pthread_mutex_lock (&m_mutex);
}

//-----------------------------------------------------------------------------
inline int CEvent::waitMsec(long lMsecs)
{
    if (!m_created)
        return ERR_EVENT_INIT;
    
    // See: http://www.ibm.com/developerworks/linux/library/l-ipc2lin3/index.html
    struct timespec delay;  // structure for providing timeout
    long timeout = 0;
    int err = 0;
    while (timeout < lMsecs )
    {
        delay.tv_sec = 0;
        delay.tv_nsec = 1000000;  // 1 milli sec delay
        err = pthread_mutex_trylock(&m_mutex);
        if (!err)
        {
            break;
        }
        else {
            // check whether somebody else has the mutex
            if (err == EBUSY ) {
                // Yes, Resource already in use so sleep
                nanosleep(&delay, NULL);
                ++timeout;
            }
            else
            {
                fprintf(stderr, "Unexpected return value from pthread_mutex_trylock: %d \n", err);
            }
        }
    }
return err;
}

//-----------------------------------------------------------------------------
inline int CEvent::waitSeconds(long lSeconds)
{
    DWORD dwMsecs = DWORD(lSeconds) * 1000;
    return waitMsec(dwMsecs);
}

//-----------------------------------------------------------------------------
inline int CEvent::signal()
{
    if (!m_created)
        return ERR_EVENT_INIT;

    return pthread_mutex_unlock(&m_mutex);
}

//-----------------------------------------------------------------------------
inline int CEvent::reset()
{
    if (!m_created)
        return ERR_EVENT_INIT;

    return pthread_mutex_unlock(&m_mutex);
}

#endif  // S_EVENT_H