1 // Copyright Maciej Sobczak 2008-2019.
2 // This file is part of YAMI4.
3 //
4 // YAMI4 is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // YAMI4 is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with YAMI4.  If not, see <http://www.gnu.org/licenses/>.
16 
17 #include "flag.h"
18 #include <yami4-core/fatal_errors.h>
19 #include <sys/timeb.h>
20 
21 using namespace yami;
22 using namespace details;
23 
flag()24 details::flag::flag()
25 {
26     event_ = CreateEvent(NULL, TRUE, FALSE, NULL);
27     if (event_ == NULL)
28     {
29         fatal_failure(__FILE__, __LINE__);
30     }
31 }
32 
~flag()33 details::flag::~flag()
34 {
35     CloseHandle(event_);
36 }
37 
notify()38 void details::flag::notify()
39 {
40     // note: this object acts as a latch,
41     // which means that once notified it stays in this state until suppressed
42 
43     BOOL cc = SetEvent(event_);
44     if (cc == FALSE)
45     {
46         fatal_failure(__FILE__, __LINE__);
47     }
48 }
49 
suppress()50 void details::flag::suppress()
51 {
52     // note: this object acts as a latch,
53     // which means that once suppressed it stays in this state until notified
54 
55     BOOL cc = ResetEvent(event_);
56     if (cc == FALSE)
57     {
58         fatal_failure(__FILE__, __LINE__);
59     }
60 }
61 
wait()62 void details::flag::wait()
63 {
64     DWORD cc = WaitForSingleObject(event_, INFINITE);
65     if (cc != WAIT_OBJECT_0)
66     {
67         fatal_failure(__FILE__, __LINE__);
68     }
69 }
70 
wait(std::size_t relative_timeout)71 bool details::flag::wait(std::size_t relative_timeout)
72 {
73     DWORD cc = WaitForSingleObject(event_, relative_timeout);
74     if (cc != WAIT_OBJECT_0 && cc != WAIT_TIMEOUT)
75     {
76         fatal_failure(__FILE__, __LINE__);
77     }
78 
79     return cc == WAIT_OBJECT_0;
80 }
81 
wait_absolute(unsigned long long timeout)82 bool details::flag::wait_absolute(unsigned long long timeout)
83 {
84     _timeb now;
85 
86     _ftime(&now);
87 
88     const long long now_millisecs =
89         static_cast<long long>(now.time) * 1000 + now.millitm / 1000;
90 
91     std::size_t relative_timeout;
92     if (timeout > now_millisecs)
93     {
94         // assume that the difference fits in size_t
95         relative_timeout = timeout - now_millisecs;
96     }
97     else
98     {
99         relative_timeout = 0;
100     }
101 
102     return wait(relative_timeout);
103 }
104