@@ -108,79 +108,55 @@ void PThreadEvent::ResetEvents(const uint32_t mask) {
108108// Wait until 'timeout_abstime' for any events that are set in
109109// 'mask'. If 'timeout_abstime' is NULL, then wait forever.
110110uint32_t
111- PThreadEvent::WaitForSetEvents (const uint32_t mask,
112- const struct timespec *timeout_abstime) const {
111+ PThreadEvent::WaitForEventsImpl (const uint32_t mask,
112+ const struct timespec *timeout_abstime,
113+ std::function<bool ()> predicate) const {
113114 // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x, %p)", this,
114115 // __FUNCTION__, mask, timeout_abstime);
116+
115117 int err = 0 ;
118+
116119 // pthread_cond_timedwait() or pthread_cond_wait() will atomically
117120 // unlock the mutex and wait for the condition to be set. When either
118121 // function returns, they will re-lock the mutex. We use an auto lock/unlock
119122 // class (PThreadMutex::Locker) to allow us to return at any point in this
120123 // function and not have to worry about unlocking the mutex.
121124 PTHREAD_MUTEX_LOCKER (locker, m_mutex);
122- do {
123- // Check our predicate (event bits) in case any are already set
124- if (mask & m_bits) {
125- uint32_t bits_set = mask & m_bits;
126- // Our PThreadMutex::Locker will automatically unlock our mutex
127- return bits_set;
128- }
125+
126+ // Check the predicate and the error code. The functions below do not return
127+ // EINTR so that's not something we need to handle.
128+ while (!predicate () && err == 0 ) {
129129 if (timeout_abstime) {
130130 // Wait for condition to get broadcast, or for a timeout. If we get
131- // a timeout we will drop out of the do loop and return false which
132- // is what we want.
131+ // a timeout we will drop out of the loop on the next iteration and we
132+ // will recompute the mask in case of a race between the condition and the
133+ // timeout.
133134 err = ::pthread_cond_timedwait (m_set_condition.Condition (),
134135 m_mutex.Mutex (), timeout_abstime);
135- // Retest our predicate in case of a race condition right at the end
136- // of the timeout.
137- if (err == ETIMEDOUT) {
138- uint32_t bits_set = mask & m_bits;
139- return bits_set;
140- }
141136 } else {
142- // Wait for condition to get broadcast. The only error this function
143- // should return is if
137+ // Wait for condition to get broadcast.
144138 err = ::pthread_cond_wait (m_set_condition.Condition (), m_mutex.Mutex ());
145139 }
146- } while (err == 0 );
147- return 0 ;
140+ }
141+
142+ // Either the predicate passed, we hit the specified timeout (ETIMEDOUT) or we
143+ // encountered an unrecoverable error (EINVAL, EPERM). Regardless of how we
144+ // got here, recompute and return the mask indicating which bits (if any) are
145+ // set.
146+ return GetBitsMasked (mask);
147+ }
148+
149+ uint32_t
150+ PThreadEvent::WaitForSetEvents (const uint32_t mask,
151+ const struct timespec *timeout_abstime) const {
152+ auto predicate = [&]() -> uint32_t { return GetBitsMasked (mask) != 0 ; };
153+ return WaitForEventsImpl (mask, timeout_abstime, predicate);
148154}
149155
150- // Wait until 'timeout_abstime' for any events in 'mask' to reset.
151- // If 'timeout_abstime' is NULL, then wait forever.
152156uint32_t PThreadEvent::WaitForEventsToReset (
153157 const uint32_t mask, const struct timespec *timeout_abstime) const {
154- // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x, %p)", this,
155- // __FUNCTION__, mask, timeout_abstime);
156- int err = 0 ;
157- // pthread_cond_timedwait() or pthread_cond_wait() will atomically
158- // unlock the mutex and wait for the condition to be set. When either
159- // function returns, they will re-lock the mutex. We use an auto lock/unlock
160- // class (PThreadMutex::Locker) to allow us to return at any point in this
161- // function and not have to worry about unlocking the mutex.
162- PTHREAD_MUTEX_LOCKER (locker, m_mutex);
163- do {
164- // Check our predicate (event bits) each time through this do loop
165- if ((mask & m_bits) == 0 ) {
166- // All the bits requested have been reset, return zero indicating
167- // which bits from the mask were still set (none of them)
168- return 0 ;
169- }
170- if (timeout_abstime) {
171- // Wait for condition to get broadcast, or for a timeout. If we get
172- // a timeout we will drop out of the do loop and return false which
173- // is what we want.
174- err = ::pthread_cond_timedwait (m_reset_condition.Condition (),
175- m_mutex.Mutex (), timeout_abstime);
176- } else {
177- // Wait for condition to get broadcast. The only error this function
178- // should return is if
179- err = ::pthread_cond_wait (m_reset_condition.Condition (), m_mutex.Mutex ());
180- }
181- } while (err == 0 );
182- // Return a mask indicating which bits (if any) were still set
183- return mask & m_bits;
158+ auto predicate = [&]() -> uint32_t { return GetBitsMasked (mask) == 0 ; };
159+ return WaitForEventsImpl (mask, timeout_abstime, predicate);
184160}
185161
186162uint32_t
0 commit comments