This paper studies possible changes to the Threads Library to make
broad use of noexcept. The paper addresses National Body comments CH 16
and GB 60. It is a revision of N3252 in the mailing based on
discussions in Madrid, after the update of new criteria for
noexcept.
Changes in this paper are restricted to chapter 30 (threads library).
All changes in this paper are relative to N3242.
Several swap() functions have been made noexcept as they are defined in terms of the corresponding noexcept member function.
In 30.4.1 mutex, recursive_mutex, timed_mutex and recursive_timed_mutex constructors have been made noexcept In section 30.6.1 some operations have been made noexcept to be consistent with the disgnostics library. In section 30.6.10 member function valid is not consistent with its definition in 30.6.10.1. It has been updated. In general all the swap member functions have been revised regarding to its noexcept specification. Member function unlock() has lost its noexcept specification because it has a precondition.
namespace std {
#define __STDCPP_THREADS__ __cplusplus
class thread;
void swap(thread& x, thread& y) noexcept;
namespace this_thread {
thread::id get_id() noexcept;
void yield() noexcept;
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);
}
}
namespace std {After p. 3
namespace this_thread {
thread::id get_id() noexcept;
void yield() noexcept;
template <class Clock, class Duration>
void sleep_until(const chrono::time_point<Clock, Duration>& abs_time)noexcept;
template <class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& rel_time)noexcept;
}
}
template <class Clock, class Duration>After p. 5
void sleep_until(const chrono::time_point<Clock, Duration>& abs_time)noexcept;
template <class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& rel_time)noexcept;
void swap(thread& x, thread& y) noexcept;
namespace std {
...
template <class Mutex>
void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
...
}
namespace std {
class mutex {
public:
constexpr mutex() noexcept;
~mutex();
mutex(const mutex&) = delete;
mutex& operator=(const mutex&) = delete;
void lock();
bool try_lock()noexcept;
void unlock()noexcept;
typedef implementation-defined native_handle_type; // See 30.2.3
native_handle_type native_handle(); // See 30.2.3
};
}
namespace std {
class recursive_mutex {
public:
recursive_mutex();
~recursive_mutex();
recursive_mutex(const recursive_mutex&) = delete;
recursive_mutex& operator=(const recursive_mutex&) = delete;
void lock();
bool try_lock() noexcept;
void unlock()noexcept;
typedef implementation-defined native_handle_type; // See 30.2.3
native_handle_type native_handle(); // See 30.2.3
};
}
namespace std {
class timed_mutex {
public:
timed_mutex();
~timed_mutex();
timed_mutex(const timed_mutex&) = delete;
timed_mutex& operator=(const timed_mutex&) = delete;
void lock();
bool try_lock();
template <class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)noexcept;
template <class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)noexcept;
void unlock();
typedef implementation-defined native_handle_type; // See 30.2.3
native_handle_type native_handle(); // See 30.2.3
};
}
namespace std {
class recursive_timed_mutex {
public:
recursive_timed_mutex();
~recursive_timed_mutex();
recursive_timed_mutex(const recursive_timed_mutex&) = delete;
recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
void lock();
bool try_lock() noexcept;
template <class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)noexcept;
template <class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)noexcept;
void unlock();
typedef implementation-defined native_handle_type; // See 30.2.3
native_handle_type native_handle(); // See 30.2.3
};
}
namespace std {After p. 5
template <class Mutex>
class lock_guard {
public:
...
lock_guard(mutex_type& m, adopt_lock_t)noexcept;
...
};
}
lock_guard(mutex_type& m, adopt_lock_t)noexcept;
Requires: The calling thread owns the mutex m.
Postcondition: &pm == &m
Throws: Nothing.
namespace std {
template <class Mutex>
class unique_lock {
public:
...
// 30.4.2.2.1, construct/copy/destroy:
unique_lock() noexcept;
explicit unique_lock(mutex_type& m);
unique_lock(mutex_type& m, defer_lock_t) noexcept;
unique_lock(mutex_type& m, try_to_lock_t)noexcept;
unique_lock(mutex_type& m, adopt_lock_t)noexcept;
template <class Clock, class Duration>
unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time)noexcept;
template <class Rep, class Period>
unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time)noexcept;
~unique_lock();
...
};
}
unique_lock(mutex_type& m, try_to_lock_t)noexcept;
After p. 10
unique_lock(mutex_type& m, adopt_lock_t)After p. 13noexcept;
Requires: The calling thread own the mutex.
Effects: Constructs an object of type unique_lock.
Postconditions: pm
Throws: Nothing.
template <class Clock, class Duration>After p. 16
unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time)noexcept;
template <class Rep, class Period>
unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time)noexcept;
namespace std {
...
template <class R>
void swap(promise<R>& x, promise<R>& y) noexcept;
...
template <class R>
void swap(packaged_task<R(ArgTypes...)>&, packaged_task<R(ArgTypes...)>&) noexcept;
...
}
const error_category& future_category() noexcept;After p. 2
error_code make_error_code(future_errc e) noexcept;After p. 3
error_condition make_error_condition(future_errc e) noexcept;
template <class R>
void swap(promise<R>& x, promise<R>& y) noexcept;
namespace std {After p. 4
template <class R>
class future {
public:
future() noexcept;
future(future &&) noexcept;
future(const future& rhs) = delete;
~future();
future& operator=(const future& rhs) = delete;
future& operator=(future&&) noexcept;
shared_futureshare() &&;
// retrieving the value
see below get();
// functions to check state
bool valid() const noexcept;
void wait() const;
...
};
}
future() noexcept;After p. 9
future& operator=(future&& rhs) noexcept;After p. 17
bool valid() const noexcept;
namespace std {After p. 11
template <class R>
class shared_future {
public:
shared_future() noexcept;
shared_future(const shared_future& rhs);
shared_future(future<R>&&) noexcept;
shared_future(shared_future&& rhs) noexcept;
~shared_future();
shared_future& operator=(const shared_future& rhs);
shared_future& operator=(shared_future&& rhs) noexcept;
// retrieving the value
see below get() const;
// functions to check state
bool valid() const noexcept;
void wait() const;
...
};
}
shared_future& operator=(shared_future&& rhs) noexcept;After p. 20
bool valid() const noexcept;
namespace std {After p. 6
template<class R, class... ArgTypes>
class packaged_task<R(ArgTypes...)> {
public:
...
// move support
packaged_task(packaged_task&& other) noexcept;
packaged_task& operator=(packaged_task&& other) noexcept;
void swap(packaged_task& other) noexcept;
...
};
}
packaged_task& operator=(packaged_task&& other) noexcept;