@@ -64,92 +64,70 @@ namespace bq {
6464 free (platform_data_);
6565 platform_data_ = nullptr ;
6666 }
67- static constexpr uint64_t one_billion = 1000000000ULL ;
68-
69- void condition_variable::wait (bq::platform::mutex& lock)
67+
68+ static uint64_t get_current_ns (bool use_monotonic)
7069 {
71- int32_t result = pthread_cond_wait (&platform_data_->cond_handle , (pthread_mutex_t *)(lock.get_platform_handle ()));
72- if (result != 0 ) {
73- bq::util::log_device_console (log_level::error, " pthread_cond_wait failed: %d" , result);
74- }
75- }
76-
77- static inline void add_timespec_ns (const struct timespec & base, uint64_t add_ns, struct timespec * out)
78- {
79- uint64_t ns = static_cast <uint64_t >(base.tv_nsec ) + add_ns;
80- out->tv_sec = static_cast <decltype (out->tv_sec )>(static_cast <int64_t >(base.tv_sec ) + static_cast <int64_t >(ns / one_billion));
81- out->tv_nsec = static_cast <decltype (out->tv_nsec )>(ns % one_billion);
82- }
83-
84- static uint64_t get_current_ns (bool prefer_monotonic)
85- {
86- struct timespec ts {};
70+ struct timespec ts;
8771#if defined(BQ_POSIX_MONOTONIC_SUPPORTED)
88- if (prefer_monotonic ) {
72+ if (use_monotonic ) {
8973 if (clock_gettime (CLOCK_MONOTONIC, &ts) == 0 ) {
90- return static_cast <uint64_t >(ts.tv_sec ) * one_billion + static_cast <uint64_t >(ts.tv_nsec );
74+ return static_cast <uint64_t >(ts.tv_sec ) * 1000000000ULL + static_cast <uint64_t >(ts.tv_nsec );
9175 }
9276 }
9377#endif
94- (void )prefer_monotonic;
9578 if (clock_gettime (CLOCK_REALTIME, &ts) == 0 ) {
96- return static_cast <uint64_t >(ts.tv_sec ) * one_billion + static_cast <uint64_t >(ts.tv_nsec );
79+ return static_cast <uint64_t >(ts.tv_sec ) * 1000000000ULL + static_cast <uint64_t >(ts.tv_nsec );
9780 }
9881 return bq::platform::high_performance_epoch_ms () * 1000000ULL ;
9982 }
10083
84+ void condition_variable::wait (bq::platform::mutex& lock)
85+ {
86+ int32_t result = pthread_cond_wait (&platform_data_->cond_handle , (pthread_mutex_t *)(lock.get_platform_handle ()));
87+ if (result != 0 ) {
88+ bq::util::log_device_console (log_level::error, " pthread_cond_wait failed: %d" , result);
89+ }
90+ }
91+
10192 bool condition_variable::wait_for (bq::platform::mutex& lock, uint64_t wait_time_ms)
10293 {
10394 const uint64_t wait_ns_total = wait_time_ms * 1000000ULL ;
104- const uint64_t quantum_ns = 50ULL * 1000000ULL ; // 50ms
95+ const uint64_t quantum_ns = 50ULL * 1000000ULL ; // 50ms slice
10596 const bool use_monotonic = platform_data_->use_monotonic_clock ;
10697
10798 uint64_t start_ns = get_current_ns (use_monotonic);
10899 uint64_t deadline_ns = start_ns + wait_ns_total;
100+ uint64_t next_slice_ns = start_ns + quantum_ns;
109101
110- for (;; ) {
102+ while ( true ) {
111103 uint64_t now_ns = get_current_ns (use_monotonic);
112-
113- if (now_ns >= deadline_ns)
104+ if (now_ns >= deadline_ns) {
114105 return false ;
106+ }
115107
116- uint64_t remain_ns = deadline_ns - now_ns;
117- if (remain_ns > quantum_ns)
118- remain_ns = quantum_ns;
108+ if (now_ns >= next_slice_ns) {
109+ uint64_t elapsed = now_ns - start_ns;
110+ uint64_t next_slice_idx = (elapsed / quantum_ns) + 1 ;
111+ next_slice_ns = start_ns + next_slice_idx * quantum_ns;
112+ }
119113
120- struct timespec outtime {} ;
114+ uint64_t target_ns = (deadline_ns < next_slice_ns) ? deadline_ns : next_slice_ns ;
121115
122- #if defined(BQ_POSIX_MONOTONIC_SUPPORTED)
123- if (use_monotonic) {
124- struct timespec now_mono {};
125- if (clock_gettime (CLOCK_MONOTONIC, &now_mono) != 0 ) {
126- now_mono.tv_sec = static_cast <decltype (now_mono.tv_sec )>(now_ns / one_billion);
127- now_mono.tv_nsec = static_cast <decltype (now_mono.tv_nsec )>(now_ns % one_billion);
128- }
129- add_timespec_ns (now_mono, remain_ns, &outtime);
130- } else
131- #endif
132- {
133- struct timespec now_rt {};
134- if (clock_gettime (CLOCK_REALTIME, &now_rt) != 0 ) {
135- struct timeval tv {};
136- gettimeofday (&tv, nullptr );
137- now_rt.tv_sec = static_cast <decltype (now_rt.tv_sec )>(tv.tv_sec );
138- now_rt.tv_nsec = static_cast <decltype (now_rt.tv_nsec )>(tv.tv_usec * 1000L );
139- }
140- add_timespec_ns (now_rt, remain_ns, &outtime);
141- }
116+ struct timespec ts;
117+ ts.tv_sec = static_cast <time_t >(target_ns / 1000000000ULL );
118+ ts.tv_nsec = static_cast <long >(target_ns % 1000000000ULL );
142119
143120 int32_t result = pthread_cond_timedwait (&platform_data_->cond_handle ,
144121 (pthread_mutex_t *)(lock.get_platform_handle ()),
145- &outtime);
122+ &ts);
123+
146124 if (result == 0 )
147125 return true ;
148- if (result == ETIMEDOUT)
149- continue ;
150-
151- bq::util::log_device_console (log_level::error, " pthread_cond_timedwait failed: %d " , result) ;
152- return true ;
126+
127+ if (result != ETIMEDOUT) {
128+ bq::util::log_device_console (log_level::error, " pthread_cond_timedwait failed: %d " , result);
129+ return true ;
130+ }
153131 }
154132 }
155133
0 commit comments