Ticket #6377: clocktest.cpp

File clocktest.cpp, 5.0 KB (added by Johan Borkhuis <johan@…>, 11 years ago)

Demo application showing the problem

Line 
1
2// Application to show a possible problem of Boost condition variables in
3// combination with a POSIX timer and signals
4
5#include <unistd.h>
6#include <getopt.h>
7
8#include <signal.h>
9#include "boost/thread/condition_variable.hpp"
10#include "boost/date_time/posix_time/posix_time.hpp"
11#include <boost/interprocess/sync/interprocess_semaphore.hpp>
12
13struct sigaction timerSigAction;
14struct sigaction oldSigAction;
15timer_t timer;
16int timerCount = 0;
17
18#define SIGNAL_IN_USE (SIGRTMIN)
19
20/* handler installed to handle signals generated by the timer */
21static void timerHandler(int signo)
22{
23 if (signo != SIGNAL_IN_USE)
24 {
25 return;
26 }
27 timerCount++;
28 return;
29}
30
31/* restores signal handlers and removes timer */
32static void stopTimer()
33{
34 timer_delete(timer);
35 sigaction(SIGNAL_IN_USE, &oldSigAction, NULL);
36}
37
38/* timer initializer */
39static void startTimer()
40{
41 struct sigevent signalEvent;
42 struct itimerspec timerSpec;
43 sigset_t blockedSignals;
44
45 sigemptyset(&blockedSignals);
46 timerSigAction.sa_handler = timerHandler;
47 timerSigAction.sa_flags = SA_RESTART;
48 timerSigAction.sa_mask = blockedSignals;
49 if (sigaction(SIGNAL_IN_USE, &timerSigAction, &oldSigAction))
50 {
51 return;
52 }
53
54 signalEvent.sigev_notify = SIGEV_SIGNAL;
55 signalEvent.sigev_signo = SIGNAL_IN_USE;
56
57 if (timer_create(CLOCK_REALTIME, &signalEvent, &timer))
58 {
59 stopTimer(); // restore signal handler
60 return;
61 }
62
63 timerSpec = (struct itimerspec){ {(time_t)0, 50000000L}, {(time_t)0, 50000000L} };
64 if (timer_settime(timer, 0, &timerSpec, NULL))
65 {
66 stopTimer(); // clean up timer and restore signal handler
67 return;
68 }
69}
70
71void BoostConditionVar()
72{
73 boost::mutex m;
74 boost::unique_lock<boost::mutex> lk(m);
75 boost::condition_variable cond;
76 cond.timed_wait(lk, boost::posix_time::millisec(1000));
77}
78
79void OwnConditionVar()
80{
81 pthread_mutex_t m_mutex;
82 pthread_cond_t m_cond;
83
84 pthread_mutexattr_t mutexattr;
85 pthread_mutexattr_init(&mutexattr);
86 pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
87 pthread_mutex_init(&m_mutex, &mutexattr);
88 pthread_mutexattr_destroy(&mutexattr);
89
90 pthread_condattr_t condattr;
91 pthread_condattr_init(&condattr);
92 pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC);
93 pthread_cond_init(&m_cond, &condattr);
94 pthread_condattr_destroy(&condattr);
95
96 struct timespec t1;
97 clock_gettime(CLOCK_MONOTONIC, &t1);
98 t1.tv_sec += 1;
99 pthread_mutex_lock(&m_mutex);
100 pthread_cond_timedwait(&m_cond, &m_mutex, &t1);
101
102 pthread_mutex_destroy(&m_mutex);
103 pthread_cond_destroy(&m_cond);
104}
105
106int kbhit()
107{
108 struct timeval tv;
109 fd_set fds;
110 tv.tv_sec = 0;
111 tv.tv_usec = 0;
112 FD_ZERO(&fds);
113 FD_SET(STDIN_FILENO, &fds); //STDIN_FILENO is 0
114 select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
115 return FD_ISSET(STDIN_FILENO, &fds);
116}
117
118int main(int argc, char *argv[])
119{
120 bool useSignals = false;
121 bool useBoost = false;
122 static struct option long_options[] =
123 {
124 {"signals", no_argument, 0, 's'},
125 {"boost", no_argument, 0, 'b'},
126 {0, 0, 0, 0 }
127 };
128
129 int option_index = 0;
130 int opt;
131 while ((opt = getopt_long(argc, argv, "sb", long_options, &option_index)) != -1)
132 {
133 switch (opt) {
134 case 's':
135 fprintf(stderr, "Generating POSIX signals\n");
136 useSignals = 1;
137 break;
138 case 'b':
139 fprintf(stderr, "Using Boost condition variables\n");
140 useBoost = 1;
141 break;
142 default: /* '?' */
143 fprintf(stderr, "Usage: %s [-b] [-s] \n", argv[0]);
144 fprintf(stderr, "-b --boost: use boost condition variable\n");
145 fprintf(stderr, "-s --signals: generate POSIX signals\n");
146 exit(EXIT_FAILURE);
147 }
148 }
149
150 if(useSignals)
151 {
152 startTimer();
153 }
154
155 printf("Press ENTER to stop\n");
156
157 sem_t sem;
158 if (sem_init(&sem, 0, 1) == -1) {
159 if(useSignals)
160 {
161 stopTimer();
162 }
163 perror("sem_init");
164 exit(EXIT_FAILURE);
165 }
166
167 struct timespec t1;
168 struct timespec t2;
169
170 while(kbhit() == false)
171 {
172 if (useBoost)
173 {
174 BoostConditionVar();
175 }
176 else
177 {
178 OwnConditionVar();
179 }
180 boost::posix_time::ptime now = boost::posix_time::second_clock::local_time();
181 std::string output = to_simple_string(now);
182 int retval1 = clock_gettime(CLOCK_REALTIME, &t1);
183 int retval2 = clock_gettime(CLOCK_MONOTONIC, &t2);
184 printf("%s %d %d.%9.9d %d %d.%9.9d %d\n", output.c_str(), retval1,
185 t1.tv_sec, t1.tv_nsec, retval2, t2.tv_sec, t2.tv_nsec,
186 timerCount);
187 }
188
189 if(useSignals)
190 {
191 stopTimer();
192 }
193}