libcxx initial import
git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@103490 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
322
include/thread
Normal file
322
include/thread
Normal file
@@ -0,0 +1,322 @@
|
||||
// -*- C++ -*-
|
||||
//===--------------------------- thread -----------------------------------===//
|
||||
//
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP_THREAD
|
||||
#define _LIBCPP_THREAD
|
||||
|
||||
/*
|
||||
|
||||
thread synopsis
|
||||
|
||||
#define __STDCPP_THREADS __cplusplus
|
||||
|
||||
namespace std
|
||||
{
|
||||
|
||||
class thread
|
||||
{
|
||||
public:
|
||||
class id;
|
||||
typedef pthread_t native_handle_type;
|
||||
|
||||
thread();
|
||||
template <class F, class ...Args> explicit thread(F&& f, Args&&... args);
|
||||
~thread();
|
||||
|
||||
thread(const thread&) = delete;
|
||||
thread(thread&& t);
|
||||
|
||||
thread& operator=(const thread&) = delete;
|
||||
thread& operator=(thread&& t);
|
||||
|
||||
void swap(thread& t);
|
||||
|
||||
bool joinable() const;
|
||||
void join();
|
||||
void detach();
|
||||
id get_id() const;
|
||||
native_handle_type native_handle();
|
||||
|
||||
static unsigned hardware_concurrency();
|
||||
};
|
||||
|
||||
void swap(thread& x, thread& y);
|
||||
|
||||
class thread::id
|
||||
{
|
||||
public:
|
||||
id();
|
||||
};
|
||||
|
||||
bool operator==(thread::id x, thread::id y);
|
||||
bool operator!=(thread::id x, thread::id y);
|
||||
bool operator< (thread::id x, thread::id y);
|
||||
bool operator<=(thread::id x, thread::id y);
|
||||
bool operator> (thread::id x, thread::id y);
|
||||
bool operator>=(thread::id x, thread::id y);
|
||||
|
||||
template<class charT, class traits>
|
||||
basic_ostream<charT, traits>&
|
||||
operator<<(basic_ostream<charT, traits>& out, thread::id id);
|
||||
|
||||
namespace this_thread
|
||||
{
|
||||
|
||||
thread::id get_id();
|
||||
|
||||
void yield();
|
||||
|
||||
template <class Clock, class Duration>
|
||||
void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
|
||||
|
||||
template <class Rep, class Period>
|
||||
void sleep_for(const chrono::duration<Rep, Period>& rel_time);
|
||||
|
||||
} // this_thread
|
||||
|
||||
} // std
|
||||
|
||||
*/
|
||||
|
||||
#include <__config>
|
||||
#include <iosfwd>
|
||||
#include <__functional_base>
|
||||
#include <type_traits>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <system_error>
|
||||
#include <chrono>
|
||||
#include <__mutex_base>
|
||||
#include <pthread.h>
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#define __STDCPP_THREADS __cplusplus
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
class thread;
|
||||
class __thread_id;
|
||||
|
||||
namespace this_thread
|
||||
{
|
||||
|
||||
__thread_id get_id();
|
||||
|
||||
} // this_thread
|
||||
|
||||
class __thread_id
|
||||
{
|
||||
pthread_t __id_;
|
||||
|
||||
public:
|
||||
__thread_id() : __id_(0) {}
|
||||
|
||||
friend bool operator==(__thread_id __x, __thread_id __y)
|
||||
{return __x.__id_ == __y.__id_;}
|
||||
friend bool operator!=(__thread_id __x, __thread_id __y)
|
||||
{return !(__x == __y);}
|
||||
friend bool operator< (__thread_id __x, __thread_id __y)
|
||||
{return __x.__id_ < __y.__id_;}
|
||||
friend bool operator<=(__thread_id __x, __thread_id __y)
|
||||
{return !(__y < __x);}
|
||||
friend bool operator> (__thread_id __x, __thread_id __y)
|
||||
{return __y < __x ;}
|
||||
friend bool operator>=(__thread_id __x, __thread_id __y)
|
||||
{return !(__x < __y);}
|
||||
|
||||
template<class _CharT, class _Traits>
|
||||
friend
|
||||
basic_ostream<_CharT, _Traits>&
|
||||
operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id)
|
||||
{return __os << __id.__id_;}
|
||||
|
||||
private:
|
||||
__thread_id(pthread_t __id) : __id_(__id) {}
|
||||
|
||||
friend __thread_id this_thread::get_id();
|
||||
friend class thread;
|
||||
};
|
||||
|
||||
template<class _Tp> struct hash;
|
||||
|
||||
template<>
|
||||
struct hash<__thread_id>
|
||||
: public unary_function<__thread_id, size_t>
|
||||
{
|
||||
size_t operator()(__thread_id __v) const
|
||||
{
|
||||
const size_t* const __p = reinterpret_cast<const size_t*>(&__v);
|
||||
return *__p;
|
||||
}
|
||||
};
|
||||
|
||||
namespace this_thread
|
||||
{
|
||||
|
||||
inline
|
||||
__thread_id
|
||||
get_id()
|
||||
{
|
||||
return pthread_self();
|
||||
}
|
||||
|
||||
} // this_thread
|
||||
|
||||
class thread
|
||||
{
|
||||
pthread_t __t_;
|
||||
|
||||
#ifndef _LIBCPP_MOVE
|
||||
thread(const thread&); // = delete;
|
||||
thread& operator=(const thread&); // = delete;
|
||||
#endif
|
||||
public:
|
||||
typedef __thread_id id;
|
||||
typedef pthread_t native_handle_type;
|
||||
|
||||
thread() : __t_(0) {}
|
||||
#ifndef _LIBCPP_HAS_NO_VARIADICS
|
||||
template <class _F, class ..._Args,
|
||||
class = typename enable_if
|
||||
<
|
||||
!is_same<typename decay<_F>::type, thread>::value
|
||||
>::type
|
||||
>
|
||||
explicit thread(_F&& __f, _Args&&... __args);
|
||||
#else
|
||||
template <class _F> explicit thread(_F __f);
|
||||
#endif
|
||||
~thread();
|
||||
|
||||
#ifdef _LIBCPP_MOVE
|
||||
thread(const thread&) = delete;
|
||||
thread(thread&& __t) : __t_(__t.__t_) {__t.__t_ = 0;}
|
||||
thread& operator=(const thread&) = delete;
|
||||
thread& operator=(thread&& __t);
|
||||
#endif
|
||||
|
||||
void swap(thread& __t) {_STD::swap(__t_, __t.__t_);}
|
||||
|
||||
bool joinable() const {return __t_ != nullptr;}
|
||||
void join();
|
||||
void detach();
|
||||
id get_id() const {return __t_;}
|
||||
native_handle_type native_handle() {return __t_;}
|
||||
|
||||
static unsigned hardware_concurrency();
|
||||
};
|
||||
|
||||
template <class _F>
|
||||
void*
|
||||
__thread_proxy(void* __vp)
|
||||
{
|
||||
std::unique_ptr<_F> __p(static_cast<_F*>(__vp));
|
||||
(*__p)();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_VARIADICS
|
||||
|
||||
template <class _F, class ..._Args,
|
||||
class
|
||||
>
|
||||
thread::thread(_F&& __f, _Args&&... __args)
|
||||
{
|
||||
typedef decltype(bind(std::forward<_F>(__f), std::forward<_Args>(__args)...)) _G;
|
||||
std::unique_ptr<_G> __p(new _G(bind(std::forward<_F>(__f),
|
||||
std::forward<_Args>(__args)...)));
|
||||
int __ec = pthread_create(&__t_, 0, &__thread_proxy<_G>, __p.get());
|
||||
if (__ec == 0)
|
||||
__p.release();
|
||||
else
|
||||
__throw_system_error(__ec, "thread constructor failed");
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template <class _F>
|
||||
thread::thread(_F __f)
|
||||
{
|
||||
std::unique_ptr<_F> __p(new _F(__f));
|
||||
int __ec = pthread_create(&__t_, 0, &__thread_proxy<_F>, __p.get());
|
||||
if (__ec == 0)
|
||||
__p.release();
|
||||
else
|
||||
__throw_system_error(__ec, "thread constructor failed");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef _LIBCPP_MOVE
|
||||
|
||||
inline
|
||||
thread&
|
||||
thread::operator=(thread&& __t)
|
||||
{
|
||||
if (__t_ != nullptr)
|
||||
terminate();
|
||||
__t_ = __t.__t_;
|
||||
__t.__t_ = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
inline
|
||||
void swap(thread& __x, thread& __y) {__x.swap(__y);}
|
||||
|
||||
|
||||
namespace this_thread
|
||||
{
|
||||
|
||||
void sleep_for(const chrono::nanoseconds& ns);
|
||||
|
||||
template <class _Rep, class _Period>
|
||||
void
|
||||
sleep_for(const chrono::duration<_Rep, _Period>& __d)
|
||||
{
|
||||
using namespace chrono;
|
||||
nanoseconds __ns = duration_cast<nanoseconds>(__d);
|
||||
if (__ns < __d)
|
||||
++__ns;
|
||||
sleep_for(__ns);
|
||||
}
|
||||
|
||||
template <class _Clock, class _Duration>
|
||||
void
|
||||
sleep_until(const chrono::time_point<_Clock, _Duration>& __t)
|
||||
{
|
||||
using namespace chrono;
|
||||
mutex __mut;
|
||||
condition_variable __cv;
|
||||
unique_lock<mutex> __lk(__mut);
|
||||
while (_Clock::now() < __t)
|
||||
__cv.wait_until(__lk, __t);
|
||||
}
|
||||
|
||||
template <class _Duration>
|
||||
inline
|
||||
void
|
||||
sleep_until(const chrono::time_point<chrono::monotonic_clock, _Duration>& __t)
|
||||
{
|
||||
using namespace chrono;
|
||||
sleep_for(__t - monotonic_clock::now());
|
||||
}
|
||||
|
||||
inline
|
||||
void yield() {sched_yield();}
|
||||
|
||||
} // this_thread
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP_THREAD
|
Reference in New Issue
Block a user