// <condition_variable> -*- C++ -*-
-// Copyright (C) 2008 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
-// Free Software Foundation; either version 2, or (at your option)
+// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
-// You should have received a copy of the GNU General Public License
-// along with this library; see the file COPYING. If not, write to
-// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-// Boston, MA 02110-1301, USA.
-
-// As a special exception, you may use this file as part of a free software
-// library without restriction. Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License. This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-
-/** @file condition_variable
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file include/condition_variable
* This is a Standard C++ Library header.
*/
#pragma GCC system_header
#ifndef __GXX_EXPERIMENTAL_CXX0X__
-# include <c++0x_warning.h>
+# include <bits/c++0x_warning.h>
#else
+#include <chrono>
#include <mutex> // unique_lock
-namespace std
-{
- // XXX
- class system_time;
+#if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ /**
+ * @defgroup condition_variables Condition Variables
+ * @ingroup concurrency
+ *
+ * Classes for condition_variable support.
+ * @{
+ */
+
+ /// cv_status
+ enum class cv_status { no_timeout, timeout };
+
/// condition_variable
class condition_variable
{
+ typedef chrono::system_clock __clock_t;
+ typedef __gthread_cond_t __native_type;
+ __native_type _M_cond;
+
public:
+ typedef __native_type* native_handle_type;
-#if __GTHREAD_HAS_COND
- typedef __gthread_cond_t native_handle_type;
-#else
- typedef int native_handle_type;
-#endif
+ condition_variable() throw ();
+ ~condition_variable() throw ();
- condition_variable();
- ~condition_variable();
+ condition_variable(const condition_variable&) = delete;
+ condition_variable& operator=(const condition_variable&) = delete;
- void
+ void
notify_one();
- void
+ void
notify_all();
- void
+ void
wait(unique_lock<mutex>& __lock);
template<typename _Predicate>
- void
+ void
wait(unique_lock<mutex>& __lock, _Predicate __p)
{
while (!__p())
wait(__lock);
}
-
+
template<typename _Duration>
- bool
- timed_wait(unique_lock<mutex>& __lock, const _Duration& __rtime);
+ cv_status
+ wait_until(unique_lock<mutex>& __lock,
+ const chrono::time_point<__clock_t, _Duration>& __atime)
+ { return __wait_until_impl(__lock, __atime); }
+
+ template<typename _Clock, typename _Duration>
+ cv_status
+ wait_until(unique_lock<mutex>& __lock,
+ const chrono::time_point<_Clock, _Duration>& __atime)
+ {
+ // DR 887 - Sync unknown clock to known clock.
+ const typename _Clock::time_point __c_entry = _Clock::now();
+ const __clock_t::time_point __s_entry = __clock_t::now();
+ const chrono::nanoseconds __delta = __atime - __c_entry;
+ const __clock_t::time_point __s_atime = __s_entry + __delta;
+
+ return __wait_until_impl(__lock, __s_atime);
+ }
- bool
- timed_wait(unique_lock<mutex>& __lock, const system_time& __atime);
+ template<typename _Clock, typename _Duration, typename _Predicate>
+ bool
+ wait_until(unique_lock<mutex>& __lock,
+ const chrono::time_point<_Clock, _Duration>& __atime,
+ _Predicate __p)
+ {
+ while (!__p())
+ if (wait_until(__lock, __atime) == cv_status::timeout)
+ return __p();
+ return true;
+ }
- template<typename _Predicate>
- bool
- timed_wait(unique_lock<mutex>& __lock, const system_time& __atime,
- _Predicate pred);
+ template<typename _Rep, typename _Period>
+ cv_status
+ wait_for(unique_lock<mutex>& __lock,
+ const chrono::duration<_Rep, _Period>& __rtime)
+ { return wait_until(__lock, __clock_t::now() + __rtime); }
- template<typename _Duration, typename _Predicate>
- bool
- timed_wait(unique_lock<mutex>& __lock, const _Duration& __rtime,
- _Predicate pred);
+ template<typename _Rep, typename _Period, typename _Predicate>
+ bool
+ wait_for(unique_lock<mutex>& __lock,
+ const chrono::duration<_Rep, _Period>& __rtime,
+ _Predicate __p)
+ { return wait_until(__lock, __clock_t::now() + __rtime, std::move(__p)); }
- native_handle_type
- native_handle() { return _M_cond; }
+ native_handle_type
+ native_handle()
+ { return &_M_cond; }
private:
- native_handle_type _M_cond;
- condition_variable(const condition_variable&);
- condition_variable& operator=(const condition_variable&);
+ template<typename _Clock, typename _Duration>
+ cv_status
+ __wait_until_impl(unique_lock<mutex>& __lock,
+ const chrono::time_point<_Clock, _Duration>& __atime)
+ {
+ chrono::time_point<__clock_t, chrono::seconds> __s =
+ chrono::time_point_cast<chrono::seconds>(__atime);
+
+ chrono::nanoseconds __ns =
+ chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
+
+ __gthread_time_t __ts =
+ {
+ static_cast<std::time_t>(__s.time_since_epoch().count()),
+ static_cast<long>(__ns.count())
+ };
+
+ __gthread_cond_timedwait(&_M_cond, __lock.mutex()->native_handle(),
+ &__ts);
+
+ return (_Clock::now() < __atime
+ ? cv_status::no_timeout : cv_status::timeout);
+ }
};
/// condition_variable_any
- // Like above, only mutex may not have try_lock.
+ // Like above, but mutex is not required to have try_lock.
class condition_variable_any
{
+ typedef chrono::system_clock __clock_t;
+ condition_variable _M_cond;
+ mutex _M_mutex;
+
public:
-#if __GTHREAD_HAS_COND
- typedef __gthread_cond_t native_handle_type;
-#else
- typedef int native_handle_type;
-#endif
+ typedef condition_variable::native_handle_type native_handle_type;
- condition_variable_any();
- ~condition_variable_any();
+ condition_variable_any() throw ();
+ ~condition_variable_any() throw ();
- void
- notify_one();
+ condition_variable_any(const condition_variable_any&) = delete;
+ condition_variable_any& operator=(const condition_variable_any&) = delete;
- void
- notify_all();
+ void
+ notify_one()
+ {
+ lock_guard<mutex> __lock(_M_mutex);
+ _M_cond.notify_one();
+ }
- template<typename _Lock>
- void
- wait(_Lock& __lock);
-
- template<typename _Lock, typename _Predicate>
- void
- wait(_Lock& __lock, _Predicate __p);
+ void
+ notify_all()
+ {
+ lock_guard<mutex> __lock(_M_mutex);
+ _M_cond.notify_all();
+ }
template<typename _Lock>
- bool
- timed_wait(_Lock& __lock, const system_time& __atime);
-
- template<typename _Lock, typename _Duration>
- bool
- timed_wait(_Lock& __lock, const _Duration& __rtime);
+ void
+ wait(_Lock& __lock)
+ {
+ unique_lock<mutex> __my_lock(_M_mutex);
+ __lock.unlock();
+ _M_cond.wait(__my_lock);
+ __lock.lock();
+ }
+
template<typename _Lock, typename _Predicate>
- bool
- timed_wait(_Lock& __lock, const system_time& __atime, _Predicate __p);
+ void
+ wait(_Lock& __lock, _Predicate __p)
+ {
+ while (!__p())
+ wait(__lock);
+ }
- template<typename _Lock, typename _Duration, typename _Predicate>
- bool
- timed_wait(_Lock& __lock, const _Duration& __rtime, _Predicate __p);
+ template<typename _Lock, typename _Clock, typename _Duration>
+ cv_status
+ wait_until(_Lock& __lock,
+ const chrono::time_point<_Clock, _Duration>& __atime)
+ {
+ unique_lock<mutex> __my_lock(_M_mutex);
+ __lock.unlock();
+ cv_status __status = _M_cond.wait_until(__my_lock, __atime);
+ __lock.lock();
+ return __status;
+ }
- native_handle_type
- native_handle() { return _M_cond; }
+ template<typename _Lock, typename _Clock,
+ typename _Duration, typename _Predicate>
+ bool
+ wait_until(_Lock& __lock,
+ const chrono::time_point<_Clock, _Duration>& __atime,
+ _Predicate __p)
+ {
+ while (!__p())
+ if (wait_until(__lock, __atime) == cv_status::timeout)
+ return __p();
+ return true;
+ }
- private:
- native_handle_type _M_cond;
- condition_variable_any(const condition_variable_any&);
- condition_variable_any& operator=(const condition_variable_any&);
+ template<typename _Lock, typename _Rep, typename _Period>
+ cv_status
+ wait_for(_Lock& __lock, const chrono::duration<_Rep, _Period>& __rtime)
+ { return wait_until(__lock, __clock_t::now() + __rtime); }
+
+ template<typename _Lock, typename _Rep,
+ typename _Period, typename _Predicate>
+ bool
+ wait_for(_Lock& __lock,
+ const chrono::duration<_Rep, _Period>& __rtime, _Predicate __p)
+ { return wait_until(__lock, __clock_t::now() + __rtime, std::move(__p)); }
+
+ native_handle_type
+ native_handle()
+ { return _M_cond.native_handle(); }
};
-}
+ // @} group condition_variables
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+
+#endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1
#endif // __GXX_EXPERIMENTAL_CXX0X__