// <condition_variable> -*- C++ -*-
-// Copyright (C) 2008, 2009 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>
#if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
-namespace std
+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
{
public:
typedef __native_type* native_handle_type;
- condition_variable();
- ~condition_variable();
+ condition_variable() throw ();
+ ~condition_variable() throw ();
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
+ 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>
- bool
+ cv_status
wait_until(unique_lock<mutex>& __lock,
const chrono::time_point<_Clock, _Duration>& __atime)
{
// DR 887 - Sync unknown clock to known clock.
- typename _Clock::time_point __c_entry = _Clock::now();
- __clock_t::time_point __s_entry = __clock_t::now();
- chrono::nanoseconds __delta = __atime - __c_entry;
- __clock_t::time_point __s_atime = __s_entry + __delta;
+ 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);
}
_Predicate __p)
{
while (!__p())
- if (!wait_until(__lock, __atime))
+ if (wait_until(__lock, __atime) == cv_status::timeout)
return __p();
-
return true;
}
template<typename _Rep, typename _Period>
- bool
+ cv_status
wait_for(unique_lock<mutex>& __lock,
const chrono::duration<_Rep, _Period>& __rtime)
{ return wait_until(__lock, __clock_t::now() + __rtime); }
_Predicate __p)
{ return wait_until(__lock, __clock_t::now() + __rtime, std::move(__p)); }
- native_handle_type
- native_handle()
+ native_handle_type
+ native_handle()
{ return &_M_cond; }
private:
template<typename _Clock, typename _Duration>
- bool
+ 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::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;
+ 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 __gthread_cond_t __native_type;
- __native_type _M_cond;
+ typedef chrono::system_clock __clock_t;
+ condition_variable _M_cond;
+ mutex _M_mutex;
public:
- typedef __native_type* native_handle_type;
+ typedef condition_variable::native_handle_type native_handle_type;
+
+ condition_variable_any() throw ();
+ ~condition_variable_any() throw ();
- condition_variable_any();
- ~condition_variable_any();
-
condition_variable_any(const condition_variable_any&) = delete;
condition_variable_any& operator=(const condition_variable_any&) = delete;
- void
- notify_one();
+ void
+ notify_one()
+ {
+ lock_guard<mutex> __lock(_M_mutex);
+ _M_cond.notify_one();
+ }
- void
- notify_all();
+ void
+ notify_all()
+ {
+ lock_guard<mutex> __lock(_M_mutex);
+ _M_cond.notify_all();
+ }
template<typename _Lock>
- void
- wait(_Lock& __lock);
+ 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>
- void
- wait(_Lock& __lock, _Predicate __p);
+ void
+ wait(_Lock& __lock, _Predicate __p)
+ {
+ while (!__p())
+ wait(__lock);
+ }
template<typename _Lock, typename _Clock, typename _Duration>
- bool
+ cv_status
wait_until(_Lock& __lock,
- const chrono::time_point<_Clock, _Duration>& __atime);
+ 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;
+ }
- template<typename _Lock, typename _Clock,
+ template<typename _Lock, typename _Clock,
typename _Duration, typename _Predicate>
- bool
+ bool
wait_until(_Lock& __lock,
const chrono::time_point<_Clock, _Duration>& __atime,
- _Predicate __p);
-
+ _Predicate __p)
+ {
+ while (!__p())
+ if (wait_until(__lock, __atime) == cv_status::timeout)
+ return __p();
+ return true;
+ }
+
template<typename _Lock, typename _Rep, typename _Period>
- bool
- wait_for(_Lock& __lock, const chrono::duration<_Rep, _Period>& __rtime);
+ 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);
+ 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_type
native_handle()
- { return &_M_cond; }
+ { return _M_cond.native_handle(); }
};
-}
+
+ // @} group condition_variables
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
#endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1