Commit 88399079 by Chris Fairles

chrono: If _GLIBCXX_USE_MONOTONIC_CLOCK is defined...

2008-09-23  Chris Fairles <cfairles@gcc.gnu.org>

        * include/std/chrono: If _GLIBCXX_USE_MONOTONIC_CLOCK is defined, don't
        typedef monotonic_clock to system_clock and instead declare new class.
        * src/chrono.cc: Conditionally define monotonic_clock::now().
        * include/std/condition_variable (wait_until): Throw exception if
        __gthread_cond_timedwait returns with error other than timed_out. Use
        system_clock as known clock type (__clock_t) and add overloads for known
        and unknown clocks. In the unknown case, sync to the known clock.
        Implement overload taking a predicate.
        (wait_for): Implement overload taking a predicate.
        * config/abi/pre/gnu.ver: Add exports for monotonic_clock.
        * testsuite/30_threads/condition_variable_any/cons/assign_neg.cc: Modify
        line numbers.
        * testsuite/30_threads/condition_variable_any/cons/copy_neg.cc:
        Likewise.
        * testsuite/30_threads/condition_variable/cons/assign_neg.cc: Likewise.
        * testsuite/30_threads/condition_variable/cons/copy_neg.cc: Likewise.
        * testsuite/30_threads/condition_variable/member/1.cc: New.
        * testsuite/30_threads/condition_variable/member/2.cc: Likewise.

From-SVN: r140603
parent 1304d581
2008-09-23 Chris Fairles <cfairles@gcc.gnu.org>
* include/std/chrono: If _GLIBCXX_USE_MONOTONIC_CLOCK is defined, don't
typedef monotonic_clock to system_clock and instead declare new class.
* src/chrono.cc: Conditionally define monotonic_clock::now().
* include/std/condition_variable (wait_until): Throw exception if
__gthread_cond_timedwait returns with error other than timed_out. Use
system_clock as known clock type (__clock_t) and add overloads for known
and unknown clocks. In the unknown case, sync to the known clock.
Implement overload taking a predicate.
(wait_for): Implement overload taking a predicate.
* config/abi/pre/gnu.ver: Add exports for monotonic_clock.
* testsuite/30_threads/condition_variable_any/cons/assign_neg.cc: Modify
line numbers.
* testsuite/30_threads/condition_variable_any/cons/copy_neg.cc:
Likewise.
* testsuite/30_threads/condition_variable/cons/assign_neg.cc: Likewise.
* testsuite/30_threads/condition_variable/cons/copy_neg.cc: Likewise.
* testsuite/30_threads/condition_variable/member/1.cc: New.
* testsuite/30_threads/condition_variable/member/2.cc: Likewise.
2008-09-23 Paolo Carlini <paolo.carlini@oracle.com> 2008-09-23 Paolo Carlini <paolo.carlini@oracle.com>
PR libstdc++/37624 PR libstdc++/37624
......
...@@ -952,6 +952,8 @@ GLIBCXX_3.4.11 { ...@@ -952,6 +952,8 @@ GLIBCXX_3.4.11 {
# chrono # chrono
_ZNSt6chrono12system_clock12is_monotonicE; _ZNSt6chrono12system_clock12is_monotonicE;
_ZNSt6chrono12system_clock3nowEv; _ZNSt6chrono12system_clock3nowEv;
_ZNSt6chrono15monotonic_clock12is_monotonicE;
_ZNSt6chrono15monotonic_clock3nowEv;
# string/wstring initializer_list overloads # string/wstring initializer_list overloads
_ZNSs6appendESt16initializer_listIcE; _ZNSs6appendESt16initializer_listIcE;
......
...@@ -578,8 +578,7 @@ namespace std ...@@ -578,8 +578,7 @@ namespace std
/// system_clock /// system_clock
struct system_clock struct system_clock
{ {
#if defined(_GLIBCXX_USE_CLOCK_MONOTONIC) || \ #ifdef _GLIBCXX_USE_CLOCK_REALTIME
defined(_GLIBCXX_USE_CLOCK_REALTIME)
typedef chrono::nanoseconds duration; typedef chrono::nanoseconds duration;
#elif defined(_GLIBCXX_USE_GETTIMEOFDAY) #elif defined(_GLIBCXX_USE_GETTIMEOFDAY)
typedef chrono::microseconds duration; typedef chrono::microseconds duration;
...@@ -591,11 +590,7 @@ namespace std ...@@ -591,11 +590,7 @@ namespace std
typedef duration::period period; typedef duration::period period;
typedef chrono::time_point<system_clock, duration> time_point; typedef chrono::time_point<system_clock, duration> time_point;
#ifdef _GLIBCXX_USE_CLOCK_MONOTONIC
static const bool is_monotonic = true;
#else
static const bool is_monotonic = false; static const bool is_monotonic = false;
#endif
static time_point static time_point
now(); now();
...@@ -625,8 +620,24 @@ namespace std ...@@ -625,8 +620,24 @@ namespace std
*/ */
}; };
#ifdef _GLIBCXX_USE_CLOCK_MONOTONIC
struct monotonic_clock
{
typedef chrono::nanoseconds duration;
typedef duration::rep rep;
typedef duration::period period;
typedef chrono::time_point<monotonic_clock, duration> time_point;
static const bool is_monotonic = true;
static time_point
now();
};
#else
typedef system_clock monotonic_clock;
#endif
typedef system_clock high_resolution_clock; typedef system_clock high_resolution_clock;
typedef system_clock monotonic_clock;
} }
} }
......
...@@ -50,6 +50,8 @@ namespace std ...@@ -50,6 +50,8 @@ namespace std
/// condition_variable /// condition_variable
class condition_variable class condition_variable
{ {
typedef chrono::system_clock __clock_t;
public: public:
typedef __gthread_cond_t* native_handle_type; typedef __gthread_cond_t* native_handle_type;
...@@ -76,44 +78,51 @@ namespace std ...@@ -76,44 +78,51 @@ namespace std
wait(__lock); wait(__lock);
} }
template<typename _Clock, typename _Duration> template<typename _Duration>
bool bool
wait_until(unique_lock<mutex>& __lock, 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
wait_until(unique_lock<mutex>& __lock,
const chrono::time_point<_Clock, _Duration>& __atime) const chrono::time_point<_Clock, _Duration>& __atime)
{ {
chrono::time_point<_Clock, chrono::seconds> __s = // DR 887 - Sync unknown clock to known clock.
chrono::time_point_cast<chrono::seconds>(__atime); 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;
chrono::nanoseconds __ns = return __wait_until_impl(__lock, __s_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_t::now() < __atime;
} }
template<typename _Clock, typename _Duration, typename _Predicate> template<typename _Clock, typename _Duration, typename _Predicate>
bool bool
wait_until(unique_lock<mutex>& __lock, wait_until(unique_lock<mutex>& __lock,
const chrono::time_point<_Clock, _Duration>& __atime, const chrono::time_point<_Clock, _Duration>& __atime,
_Predicate __p); _Predicate __p)
{
while(!__p())
if(!wait_until(__lock, __atime))
return __p();
return true;
}
template<typename _Rep, typename _Period> template<typename _Rep, typename _Period>
bool bool
wait_for(unique_lock<mutex>& __lock, wait_for(unique_lock<mutex>& __lock,
const chrono::duration<_Rep, _Period>& __rtime) const chrono::duration<_Rep, _Period>& __rtime)
{ return __wait_for_impl(__rtime); } { return wait_until(__lock, __clock_t::now() + __rtime); }
template<typename _Rep, typename _Period, typename _Predicate> template<typename _Rep, typename _Period, typename _Predicate>
bool bool
wait_for(unique_lock<mutex>& __lock, wait_for(unique_lock<mutex>& __lock,
const chrono::duration<_Rep, _Period>& __rtime, const chrono::duration<_Rep, _Period>& __rtime,
_Predicate __p); _Predicate __p)
{ return wait_until(__lock, __clock_t::now() + __rtime, std::move(__p)); }
native_handle_type native_handle_type
native_handle() native_handle()
...@@ -123,35 +132,28 @@ namespace std ...@@ -123,35 +132,28 @@ namespace std
__gthread_cond_t _M_cond; __gthread_cond_t _M_cond;
mutex _M_internal_mutex; mutex _M_internal_mutex;
#ifdef _GLIBCXX_USE_CLOCK_MONOTONIC template<typename _Clock, typename _Duration>
typedef chrono::monotonic_clock __clock_t; bool
#else __wait_until_impl(unique_lock<mutex>& __lock,
typedef chrono::high_resolution_clock __clock_t; const chrono::time_point<_Clock, _Duration>& __atime)
#endif {
chrono::time_point<__clock_t, chrono::seconds> __s =
template<typename _Rep, typename _Period> chrono::time_point_cast<chrono::seconds>(__atime);
typename enable_if<
ratio_less_equal<__clock_t::period, _Period>::value, bool>::type
__wait_for_impl(unique_lock<mutex>& __lock,
const chrono::duration<_Rep, _Period>& __rtime)
{
__clock_t::time_point __atime = __clock_t::now()
+ chrono::duration_cast<__clock_t::duration>(__rtime);
return wait_until(__lock, __atime); chrono::nanoseconds __ns =
} chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
template<typename _Rep, typename _Period> __gthread_time_t __ts =
typename enable_if< {
!ratio_less_equal<__clock_t::period, _Period>::value, bool>::type static_cast<std::time_t>(__s.time_since_epoch().count()),
__wait_for_impl(unique_lock<mutex>& __lock, static_cast<long>(__ns.count())
const chrono::duration<_Rep, _Period>& __rtime) };
{
__clock_t::time_point __atime = __clock_t::now()
+ ++chrono::duration_cast<__clock_t::duration>(__rtime);
return wait_until(__lock, __atime); __gthread_cond_timedwait(&_M_cond, __lock.mutex()->native_handle(),
} &__ts);
return _Clock::now() < __atime;
}
}; };
/// condition_variable_any /// condition_variable_any
......
...@@ -47,29 +47,37 @@ namespace std ...@@ -47,29 +47,37 @@ namespace std
system_clock::time_point system_clock::time_point
system_clock::now() system_clock::now()
{ {
#ifdef _GLIBCXX_USE_CLOCK_MONOTONIC #ifdef _GLIBCXX_USE_CLOCK_REALTIME
timespec tp; timespec tp;
// -EINVAL, -EFAULT // -EINVAL, -EFAULT
clock_gettime(CLOCK_MONOTONIC, &tp); clock_gettime(CLOCK_REALTIME, &tp);
return time_point(duration(chrono::seconds(tp.tv_sec) return time_point(duration(chrono::seconds(tp.tv_sec)
+ chrono::nanoseconds(tp.tv_nsec))); + chrono::nanoseconds(tp.tv_nsec)));
#elif defined(_GLIBCXX_USE_CLOCK_REALTIME)
timespec tp;
// -EINVAL, -EFAULT
clock_gettime(CLOCK_REALTIME, &tp);
return time_point(duration(chrono::seconds(tp.tv_sec)
+ chrono::nanoseconds(tp.tv_nsec)));
#elif defined(_GLIBCXX_USE_GETTIMEOFDAY) #elif defined(_GLIBCXX_USE_GETTIMEOFDAY)
timeval tv; timeval tv;
// EINVAL, EFAULT // EINVAL, EFAULT
gettimeofday(&tv, NULL); gettimeofday(&tv, NULL);
return time_point(duration(chrono::seconds(tv.tv_sec) return time_point(duration(chrono::seconds(tv.tv_sec)
+ chrono::microseconds(tv.tv_usec))); + chrono::microseconds(tv.tv_usec)));
#else #else
std::time_t __sec = std::time(0); std::time_t __sec = std::time(0);
return system_clock::from_time_t(__sec); return system_clock::from_time_t(__sec);
#endif #endif
} }
#ifdef _GLIBCXX_USE_CLOCK_MONOTONIC
const bool monotonic_clock::is_monotonic;
monotonic_clock::time_point
monotonic_clock::now()
{
timespec tp;
// -EINVAL, -EFAULT
clock_gettime(CLOCK_MONOTONIC, &tp);
return time_point(duration(chrono::seconds(tp.tv_sec)
+ chrono::nanoseconds(tp.tv_nsec)));
}
#endif
} }
} }
......
// mutex -*- C++ -*- // condition_variable -*- C++ -*-
// Copyright (C) 2008 Free Software Foundation, Inc. // Copyright (C) 2008 Free Software Foundation, Inc.
// //
......
...@@ -41,4 +41,4 @@ void test01() ...@@ -41,4 +41,4 @@ void test01()
} }
// { dg-error "used here" "" { target *-*-* } 40 } // { dg-error "used here" "" { target *-*-* } 40 }
// { dg-error "deleted function" "" { target *-*-* } 60 } // { dg-error "deleted function" "" { target *-*-* } 62 }
...@@ -40,4 +40,4 @@ void test01() ...@@ -40,4 +40,4 @@ void test01()
} }
// { dg-error "used here" "" { target *-*-* } 39 } // { dg-error "used here" "" { target *-*-* } 39 }
// { dg-error "deleted function" "" { target *-*-* } 59 } // { dg-error "deleted function" "" { target *-*-* } 61 }
// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* alpha*-*-osf* mips-sgi-irix6* } }
// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* alpha*-*-osf* mips-sgi-irix6* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
// { dg-require-gthreads "" }
// Copyright (C) 2008 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)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// 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.
#include <chrono>
#include <condition_variable>
#include <system_error>
#include <testsuite_hooks.h>
int main()
{
bool test __attribute__((unused)) = true;
try
{
std::chrono::microseconds ms(500);
std::condition_variable c1;
std::mutex m;
std::unique_lock<std::mutex> l(m);
auto then = std::chrono::system_clock::now();
bool result = c1.wait_for(l, ms);
VERIFY( !result );
VERIFY( (std::chrono::system_clock::now() - then) >= ms );
VERIFY( l.owns_lock() );
}
catch (const std::system_error& e)
{
VERIFY( false );
}
catch (...)
{
VERIFY( false );
}
return 0;
}
// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* alpha*-*-osf* mips-sgi-irix6* } }
// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* alpha*-*-osf* mips-sgi-irix6* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
// { dg-require-gthreads "" }
// Copyright (C) 2008 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)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// 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.
#include <chrono>
#include <condition_variable>
#include <system_error>
#include <testsuite_hooks.h>
int main()
{
bool test __attribute__((unused)) = true;
try
{
std::chrono::microseconds ms(500);
std::condition_variable c1;
std::mutex m;
std::unique_lock<std::mutex> l(m);
auto then = std::chrono::monotonic_clock::now();
bool result = c1.wait_until(l, then + ms);
VERIFY( !result );
VERIFY( (std::chrono::monotonic_clock::now() - then) >= ms );
VERIFY( l.owns_lock() );
}
catch (const std::system_error& e)
{
VERIFY( false );
}
catch (...)
{
VERIFY( false );
}
return 0;
}
...@@ -41,4 +41,4 @@ void test01() ...@@ -41,4 +41,4 @@ void test01()
} }
// { dg-error "used here" "" { target *-*-* } 40 } // { dg-error "used here" "" { target *-*-* } 40 }
// { dg-error "deleted function" "" { target *-*-* } 168 } // { dg-error "deleted function" "" { target *-*-* } 170 }
...@@ -40,4 +40,4 @@ void test01() ...@@ -40,4 +40,4 @@ void test01()
} }
// { dg-error "used here" "" { target *-*-* } 39 } // { dg-error "used here" "" { target *-*-* } 39 }
// { dg-error "deleted function" "" { target *-*-* } 167 } // { dg-error "deleted function" "" { target *-*-* } 169 }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment