Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 10:10:01

0001 #ifndef BOOST_THREAD_PTHREAD_CONDITION_VARIABLE_FWD_HPP
0002 #define BOOST_THREAD_PTHREAD_CONDITION_VARIABLE_FWD_HPP
0003 // Distributed under the Boost Software License, Version 1.0. (See
0004 // accompanying file LICENSE_1_0.txt or copy at
0005 // http://www.boost.org/LICENSE_1_0.txt)
0006 // (C) Copyright 2007-8 Anthony Williams
0007 // (C) Copyright 2011-2012 Vicente J. Botet Escriba
0008 
0009 #include <boost/assert.hpp>
0010 #include <boost/throw_exception.hpp>
0011 #include <pthread.h>
0012 #include <boost/thread/cv_status.hpp>
0013 #include <boost/thread/mutex.hpp>
0014 #include <boost/thread/lock_types.hpp>
0015 #include <boost/thread/thread_time.hpp>
0016 #include <boost/thread/detail/platform_time.hpp>
0017 #include <boost/thread/pthread/pthread_helpers.hpp>
0018 
0019 #if defined BOOST_THREAD_USES_DATETIME
0020 #include <boost/thread/xtime.hpp>
0021 #endif
0022 
0023 #ifdef BOOST_THREAD_USES_CHRONO
0024 #include <boost/chrono/system_clocks.hpp>
0025 #include <boost/chrono/ceil.hpp>
0026 #endif
0027 #include <boost/thread/detail/delete.hpp>
0028 #include <boost/date_time/posix_time/posix_time_duration.hpp>
0029 
0030 #include <algorithm>
0031 
0032 #include <boost/config/abi_prefix.hpp>
0033 
0034 namespace boost
0035 {
0036     class condition_variable
0037     {
0038     private:
0039 //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0040         pthread_mutex_t internal_mutex;
0041 //#endif
0042         pthread_cond_t cond;
0043 
0044     public:
0045     //private: // used by boost::thread::try_join_until
0046 
0047         bool do_wait_until(
0048             unique_lock<mutex>& lock,
0049             detail::internal_platform_timepoint const &timeout);
0050 
0051     public:
0052       BOOST_THREAD_NO_COPYABLE(condition_variable)
0053         condition_variable()
0054         {
0055             int res;
0056 //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0057             // Even if it is not used, the internal_mutex exists (see
0058             // above) and must be initialized (etc) in case some
0059             // compilation units provide interruptions and others
0060             // don't.
0061             res=posix::pthread_mutex_init(&internal_mutex);
0062             if(res)
0063             {
0064                 boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in pthread_mutex_init"));
0065             }
0066 //#endif
0067             res = posix::pthread_cond_init(&cond);
0068             if (res)
0069             {
0070 //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0071                 // ditto
0072                 BOOST_VERIFY(!posix::pthread_mutex_destroy(&internal_mutex));
0073 //#endif
0074                 boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in pthread_cond_init"));
0075             }
0076         }
0077         ~condition_variable()
0078         {
0079 //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0080             // ditto
0081             BOOST_VERIFY(!posix::pthread_mutex_destroy(&internal_mutex));
0082 //#endif
0083             BOOST_VERIFY(!posix::pthread_cond_destroy(&cond));
0084         }
0085 
0086         void wait(unique_lock<mutex>& m);
0087 
0088         template<typename predicate_type>
0089         void wait(unique_lock<mutex>& m,predicate_type pred)
0090         {
0091             while (!pred())
0092             {
0093                 wait(m);
0094             }
0095         }
0096 
0097 #if defined BOOST_THREAD_USES_DATETIME
0098         bool timed_wait(
0099             unique_lock<mutex>& m,
0100             boost::system_time const& abs_time)
0101         {
0102 #if defined BOOST_THREAD_WAIT_BUG
0103             const detail::real_platform_timepoint ts(abs_time + BOOST_THREAD_WAIT_BUG);
0104 #else
0105             const detail::real_platform_timepoint ts(abs_time);
0106 #endif
0107 #if defined BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
0108             // The system time may jump while this function is waiting. To compensate for this and time
0109             // out near the correct time, we could call do_wait_until() in a loop with a short timeout
0110             // and recheck the time remaining each time through the loop. However, because we can't
0111             // check the predicate each time do_wait_until() completes, this introduces the possibility
0112             // of not exiting the function when a notification occurs, since do_wait_until() may report
0113             // that it timed out even though a notification was received. The best this function can do
0114             // is report correctly whether or not it reached the timeout time.
0115             const detail::platform_duration d(ts - detail::real_platform_clock::now());
0116             do_wait_until(m, detail::internal_platform_clock::now() + d);
0117             return ts > detail::real_platform_clock::now();
0118 #else
0119             return do_wait_until(m, ts);
0120 #endif
0121         }
0122         bool timed_wait(
0123             unique_lock<mutex>& m,
0124             ::boost::xtime const& abs_time)
0125         {
0126             return timed_wait(m,system_time(abs_time));
0127         }
0128 
0129         template<typename duration_type>
0130         bool timed_wait(
0131             unique_lock<mutex>& m,
0132             duration_type const& wait_duration)
0133         {
0134             if (wait_duration.is_pos_infinity())
0135             {
0136                 wait(m);
0137                 return true;
0138             }
0139             if (wait_duration.is_special())
0140             {
0141                 return true;
0142             }
0143             detail::platform_duration d(wait_duration);
0144 #if defined(BOOST_THREAD_HAS_MONO_CLOCK) && !defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO)
0145             // The system time may jump while this function is waiting. To compensate for this and time
0146             // out near the correct time, we could call do_wait_until() in a loop with a short timeout
0147             // and recheck the time remaining each time through the loop. However, because we can't
0148             // check the predicate each time do_wait_until() completes, this introduces the possibility
0149             // of not exiting the function when a notification occurs, since do_wait_until() may report
0150             // that it timed out even though a notification was received. The best this function can do
0151             // is report correctly whether or not it reached the timeout time.
0152             const detail::mono_platform_timepoint ts(detail::mono_platform_clock::now() + d);
0153             do_wait_until(m, detail::internal_platform_clock::now() + d);
0154             return ts > detail::mono_platform_clock::now();
0155 #else
0156             return do_wait_until(m, detail::internal_platform_clock::now() + d);
0157 #endif
0158         }
0159 
0160         template<typename predicate_type>
0161         bool timed_wait(
0162             unique_lock<mutex>& m,
0163             boost::system_time const& abs_time,predicate_type pred)
0164         {
0165 #if defined BOOST_THREAD_WAIT_BUG
0166             const detail::real_platform_timepoint ts(abs_time + BOOST_THREAD_WAIT_BUG);
0167 #else
0168             const detail::real_platform_timepoint ts(abs_time);
0169 #endif
0170             while (!pred())
0171             {
0172 #if defined BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
0173                 // The system time may jump while this function is waiting. To compensate for this
0174                 // and time out near the correct time, we call do_wait_until() in a loop with a
0175                 // short timeout and recheck the time remaining each time through the loop.
0176                 detail::platform_duration d(ts - detail::real_platform_clock::now());
0177                 if (d <= detail::platform_duration::zero()) break; // timeout occurred
0178                 d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
0179                 do_wait_until(m, detail::internal_platform_clock::now() + d);
0180 #else
0181                 if (!do_wait_until(m, ts)) break; // timeout occurred
0182 #endif
0183             }
0184             return pred();
0185         }
0186 
0187         template<typename predicate_type>
0188         bool timed_wait(
0189             unique_lock<mutex>& m,
0190             ::boost::xtime const& abs_time,predicate_type pred)
0191         {
0192             return timed_wait(m,system_time(abs_time),pred);
0193         }
0194 
0195         template<typename duration_type,typename predicate_type>
0196         bool timed_wait(
0197             unique_lock<mutex>& m,
0198             duration_type const& wait_duration,predicate_type pred)
0199         {
0200             if (wait_duration.is_pos_infinity())
0201             {
0202                 while (!pred())
0203                 {
0204                     wait(m);
0205                 }
0206                 return true;
0207             }
0208             if (wait_duration.is_special())
0209             {
0210                 return pred();
0211             }
0212             detail::platform_duration d(wait_duration);
0213 #if defined(BOOST_THREAD_HAS_MONO_CLOCK) && !defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO)
0214             // The system time may jump while this function is waiting. To compensate for this
0215             // and time out near the correct time, we call do_wait_until() in a loop with a
0216             // short timeout and recheck the time remaining each time through the loop.
0217             const detail::mono_platform_timepoint ts(detail::mono_platform_clock::now() + d);
0218             while (!pred())
0219             {
0220                 if (d <= detail::platform_duration::zero()) break; // timeout occurred
0221                 d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
0222                 do_wait_until(m, detail::internal_platform_clock::now() + d);
0223                 d = ts - detail::mono_platform_clock::now();
0224             }
0225 #else
0226             const detail::internal_platform_timepoint ts(detail::internal_platform_clock::now() + d);
0227             while (!pred())
0228             {
0229                 if (!do_wait_until(m, ts)) break; // timeout occurred
0230             }
0231 #endif
0232             return pred();
0233         }
0234 #endif
0235 
0236 #ifdef BOOST_THREAD_USES_CHRONO
0237 
0238         template <class Duration>
0239         cv_status
0240         wait_until(
0241                 unique_lock<mutex>& lock,
0242                 const chrono::time_point<detail::internal_chrono_clock, Duration>& t)
0243         {
0244             const detail::internal_platform_timepoint ts(t);
0245             if (do_wait_until(lock, ts)) return cv_status::no_timeout;
0246             else return cv_status::timeout;
0247         }
0248 
0249         template <class Clock, class Duration>
0250         cv_status
0251         wait_until(
0252                 unique_lock<mutex>& lock,
0253                 const chrono::time_point<Clock, Duration>& t)
0254         {
0255             // The system time may jump while this function is waiting. To compensate for this and time
0256             // out near the correct time, we could call do_wait_until() in a loop with a short timeout
0257             // and recheck the time remaining each time through the loop. However, because we can't
0258             // check the predicate each time do_wait_until() completes, this introduces the possibility
0259             // of not exiting the function when a notification occurs, since do_wait_until() may report
0260             // that it timed out even though a notification was received. The best this function can do
0261             // is report correctly whether or not it reached the timeout time.
0262             typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
0263             common_duration d(t - Clock::now());
0264             do_wait_until(lock, detail::internal_chrono_clock::now() + d);
0265             if (t > Clock::now()) return cv_status::no_timeout;
0266             else return cv_status::timeout;
0267         }
0268 
0269         template <class Rep, class Period>
0270         cv_status
0271         wait_for(
0272                 unique_lock<mutex>& lock,
0273                 const chrono::duration<Rep, Period>& d)
0274         {
0275             return wait_until(lock, chrono::steady_clock::now() + d);
0276         }
0277 
0278         template <class Duration, class Predicate>
0279         bool
0280         wait_until(
0281                 unique_lock<mutex>& lock,
0282                 const chrono::time_point<detail::internal_chrono_clock, Duration>& t,
0283                 Predicate pred)
0284         {
0285             const detail::internal_platform_timepoint ts(t);
0286             while (!pred())
0287             {
0288                 if (!do_wait_until(lock, ts)) break; // timeout occurred
0289             }
0290             return pred();
0291         }
0292 
0293         template <class Clock, class Duration, class Predicate>
0294         bool
0295         wait_until(
0296                 unique_lock<mutex>& lock,
0297                 const chrono::time_point<Clock, Duration>& t,
0298                 Predicate pred)
0299         {
0300             // The system time may jump while this function is waiting. To compensate for this
0301             // and time out near the correct time, we call do_wait_until() in a loop with a
0302             // short timeout and recheck the time remaining each time through the loop.
0303             typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
0304             while (!pred())
0305             {
0306                 common_duration d(t - Clock::now());
0307                 if (d <= common_duration::zero()) break; // timeout occurred
0308                 d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
0309                 do_wait_until(lock, detail::internal_platform_clock::now() + detail::platform_duration(d));
0310             }
0311             return pred();
0312         }
0313 
0314         template <class Rep, class Period, class Predicate>
0315         bool
0316         wait_for(
0317                 unique_lock<mutex>& lock,
0318                 const chrono::duration<Rep, Period>& d,
0319                 Predicate pred)
0320         {
0321             return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
0322         }
0323 #endif
0324 
0325 #define BOOST_THREAD_DEFINES_CONDITION_VARIABLE_NATIVE_HANDLE
0326         typedef pthread_cond_t* native_handle_type;
0327         native_handle_type native_handle()
0328         {
0329             return &cond;
0330         }
0331 
0332         void notify_one() BOOST_NOEXCEPT;
0333         void notify_all() BOOST_NOEXCEPT;
0334     };
0335 
0336     BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
0337 }
0338 
0339 #include <boost/config/abi_suffix.hpp>
0340 
0341 #endif