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
This commit is contained in:
Chris Fairles 2008-09-23 17:34:29 +00:00
parent 1304d5813d
commit 8839907955
12 changed files with 254 additions and 76 deletions

View File

@ -1,3 +1,24 @@
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>
PR libstdc++/37624

View File

@ -952,6 +952,8 @@ GLIBCXX_3.4.11 {
# chrono
_ZNSt6chrono12system_clock12is_monotonicE;
_ZNSt6chrono12system_clock3nowEv;
_ZNSt6chrono15monotonic_clock12is_monotonicE;
_ZNSt6chrono15monotonic_clock3nowEv;
# string/wstring initializer_list overloads
_ZNSs6appendESt16initializer_listIcE;

View File

@ -578,8 +578,7 @@ namespace std
/// system_clock
struct system_clock
{
#if defined(_GLIBCXX_USE_CLOCK_MONOTONIC) || \
defined(_GLIBCXX_USE_CLOCK_REALTIME)
#ifdef _GLIBCXX_USE_CLOCK_REALTIME
typedef chrono::nanoseconds duration;
#elif defined(_GLIBCXX_USE_GETTIMEOFDAY)
typedef chrono::microseconds duration;
@ -591,11 +590,7 @@ namespace std
typedef duration::period period;
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;
#endif
static time_point
now();
@ -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 monotonic_clock;
}
}

View File

@ -50,6 +50,8 @@ namespace std
/// condition_variable
class condition_variable
{
typedef chrono::system_clock __clock_t;
public:
typedef __gthread_cond_t* native_handle_type;
@ -76,44 +78,51 @@ namespace std
wait(__lock);
}
template<typename _Clock, typename _Duration>
template<typename _Duration>
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)
{
chrono::time_point<_Clock, chrono::seconds> __s =
chrono::time_point_cast<chrono::seconds>(__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;
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_t::now() < __atime;
return __wait_until_impl(__lock, __s_atime);
}
template<typename _Clock, typename _Duration, typename _Predicate>
bool
wait_until(unique_lock<mutex>& __lock,
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>
bool
wait_for(unique_lock<mutex>& __lock,
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>
bool
wait_for(unique_lock<mutex>& __lock,
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()
@ -123,35 +132,28 @@ namespace std
__gthread_cond_t _M_cond;
mutex _M_internal_mutex;
#ifdef _GLIBCXX_USE_CLOCK_MONOTONIC
typedef chrono::monotonic_clock __clock_t;
#else
typedef chrono::high_resolution_clock __clock_t;
#endif
template<typename _Rep, typename _Period>
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);
template<typename _Clock, typename _Duration>
bool
__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);
return wait_until(__lock, __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;
}
template<typename _Rep, typename _Period>
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);
}
};
/// condition_variable_any

View File

@ -47,29 +47,37 @@ namespace std
system_clock::time_point
system_clock::now()
{
#ifdef _GLIBCXX_USE_CLOCK_MONOTONIC
timespec tp;
// -EINVAL, -EFAULT
clock_gettime(CLOCK_MONOTONIC, &tp);
return time_point(duration(chrono::seconds(tp.tv_sec)
+ 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)));
#ifdef _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)
timeval tv;
// EINVAL, EFAULT
gettimeofday(&tv, NULL);
return time_point(duration(chrono::seconds(tv.tv_sec)
+ chrono::microseconds(tv.tv_usec)));
timeval tv;
// EINVAL, EFAULT
gettimeofday(&tv, NULL);
return time_point(duration(chrono::seconds(tv.tv_sec)
+ chrono::microseconds(tv.tv_usec)));
#else
std::time_t __sec = std::time(0);
return system_clock::from_time_t(__sec);
std::time_t __sec = std::time(0);
return system_clock::from_time_t(__sec);
#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
}
}

View File

@ -1,4 +1,4 @@
// mutex -*- C++ -*-
// condition_variable -*- C++ -*-
// Copyright (C) 2008 Free Software Foundation, Inc.
//

View File

@ -41,4 +41,4 @@ void test01()
}
// { dg-error "used here" "" { target *-*-* } 40 }
// { dg-error "deleted function" "" { target *-*-* } 60 }
// { dg-error "deleted function" "" { target *-*-* } 62 }

View File

@ -40,4 +40,4 @@ void test01()
}
// { dg-error "used here" "" { target *-*-* } 39 }
// { dg-error "deleted function" "" { target *-*-* } 59 }
// { dg-error "deleted function" "" { target *-*-* } 61 }

View File

@ -0,0 +1,67 @@
// { 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;
}

View File

@ -0,0 +1,67 @@
// { 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;
}

View File

@ -41,4 +41,4 @@ void test01()
}
// { dg-error "used here" "" { target *-*-* } 40 }
// { dg-error "deleted function" "" { target *-*-* } 168 }
// { dg-error "deleted function" "" { target *-*-* } 170 }

View File

@ -40,4 +40,4 @@ void test01()
}
// { dg-error "used here" "" { target *-*-* } 39 }
// { dg-error "deleted function" "" { target *-*-* } 167 }
// { dg-error "deleted function" "" { target *-*-* } 169 }