// <thread> -*- C++ -*-
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 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 thread
+// 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/thread
* 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 <memory>
#include <mutex>
#include <condition_variable>
-#include <cstddef>
#include <bits/functexcept.h>
+#include <bits/functional_hash.h>
#include <bits/gthr.h>
#if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
-namespace std
+namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ /**
+ * @defgroup threads Threads
+ * @ingroup concurrency
+ *
+ * Classes for thread support.
+ * @{
+ */
+
/// thread
class thread
{
public:
- typedef __gthread_t native_handle_type;
+ typedef __gthread_t native_handle_type;
struct _Impl_base;
typedef shared_ptr<_Impl_base> __shared_base_type;
/// thread::id
class id
{
- native_handle_type _M_thread;
+ native_handle_type _M_thread;
public:
id() : _M_thread() { }
private:
friend class thread;
+ friend class hash<thread::id>;
friend bool
operator==(thread::id __x, thread::id __y)
template<class _CharT, class _Traits>
friend basic_ostream<_CharT, _Traits>&
- operator<<(basic_ostream<_CharT, _Traits>&& __out, thread::id __id);
+ operator<<(basic_ostream<_CharT, _Traits>& __out, thread::id __id);
};
+ // Simple base type that the templatized, derived class containing
+ // an arbitrary functor can be converted to and called.
struct _Impl_base
{
- id _M_id;
- __shared_base_type _M_this_ptr;
+ __shared_base_type _M_this_ptr;
- _Impl_base() = default;
+ virtual ~_Impl_base();
- virtual ~_Impl_base() = default;
-
- virtual void
- _M_run() = 0;
+ virtual void _M_run() = 0;
};
template<typename _Callable>
- class _Impl : public _Impl_base
+ struct _Impl : public _Impl_base
{
- _Callable _M_func;
+ _Callable _M_func;
- public:
_Impl(_Callable&& __f) : _M_func(std::forward<_Callable>(__f))
{ }
- void
+ void
_M_run() { _M_func(); }
};
private:
- // NB: Store the base type here.
- __shared_base_type _M_data;
+ id _M_id;
public:
thread() = default;
+ thread(thread&) = delete;
thread(const thread&) = delete;
thread(thread&& __t)
{ swap(__t); }
- template<typename _Callable>
- explicit thread(_Callable __f)
- : _M_data(_M_make_shared_data<_Callable>(__f))
- { _M_start_thread(); }
-
template<typename _Callable, typename... _Args>
+ explicit
thread(_Callable&& __f, _Args&&... __args)
- : _M_data(_M_make_shared_data(std::bind(__f, __args...)))
- { _M_start_thread(); }
+ {
+ _M_start_thread(_M_make_routine(std::bind<void>(
+ std::forward<_Callable>(__f),
+ std::forward<_Args>(__args)...)));
+ }
~thread()
{
if (joinable())
- detach();
+ std::terminate();
}
thread& operator=(const thread&) = delete;
thread& operator=(thread&& __t)
{
if (joinable())
- detach();
+ std::terminate();
swap(__t);
return *this;
}
void
- swap(thread&& __t)
- { std::swap(_M_data, __t._M_data); }
+ swap(thread& __t)
+ { std::swap(_M_id, __t._M_id); }
bool
joinable() const
- { return _M_data; }
+ { return !(_M_id == id()); }
void
join();
thread::id
get_id() const
- {
- if (_M_data)
- return thread::id(_M_data->_M_id._M_thread);
- else
- return thread::id();
- }
+ { return _M_id; }
/** @pre thread is joinable
*/
native_handle_type
native_handle()
- { return _M_data->_M_id._M_thread; }
+ { return _M_id._M_thread; }
// Returns a value that hints at the number of hardware thread contexts.
static unsigned int
{ return 0; }
private:
+ void
+ _M_start_thread(__shared_base_type);
+
template<typename _Callable>
shared_ptr<_Impl<_Callable>>
- _M_make_shared_data(_Callable&& __f)
+ _M_make_routine(_Callable&& __f)
{
// Create and allocate full data structure, not base.
return make_shared<_Impl<_Callable>>(std::forward<_Callable>(__f));
}
-
- void _M_start_thread();
};
inline void
swap(thread& __x, thread& __y)
{ __x.swap(__y); }
- inline void
- swap(thread&& __x, thread& __y)
- { __x.swap(__y); }
-
- inline void
- swap(thread& __x, thread&& __y)
- { __x.swap(__y); }
-
inline bool
operator!=(thread::id __x, thread::id __y)
{ return !(__x == __y); }
operator>=(thread::id __x, thread::id __y)
{ return !(__x < __y); }
+ // DR 889.
+ /// std::hash specialization for thread::id.
+ template<>
+ struct hash<thread::id>
+ : public __hash_base<size_t, thread::id>
+ {
+ size_t
+ operator()(const thread::id& __id) const
+ { return std::_Hash_impl::hash(__id._M_thread); }
+ };
+
template<class _CharT, class _Traits>
inline basic_ostream<_CharT, _Traits>&
- operator<<(basic_ostream<_CharT, _Traits>&& __out, thread::id __id)
+ operator<<(basic_ostream<_CharT, _Traits>& __out, thread::id __id)
{
if (__id == thread::id())
return __out << "thread::id of a non-executing thread";
return __out << __id._M_thread;
}
- // 30.2.2 Namespace this_thread.
+_GLIBCXX_END_NAMESPACE_VERSION
+
+ /** @namespace std::this_thread
+ * @brief ISO C++ 0x entities sub namespace for thread.
+ * 30.2.2 Namespace this_thread.
+ */
namespace this_thread
{
+ _GLIBCXX_BEGIN_NAMESPACE_VERSION
+
/// get_id
inline thread::id
get_id() { return thread::id(__gthread_self()); }
::nanosleep(&__ts, 0);
}
#endif
+
+ _GLIBCXX_END_NAMESPACE_VERSION
}
-}
+
+ // @} group threads
+
+} // namespace
#endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1