From 258f03cf58dee6e017b51b4e6072b8ef50f2d311 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Tue, 11 Dec 2018 06:47:48 +0700 Subject: [PATCH] update modules --- headers/3rdparty/promise.hpp/jobber.hpp | 399 ++++++++++++++++++++ headers/3rdparty/promise.hpp/promise.hpp | 180 ++++++++- headers/3rdparty/promise.hpp/scheduler.hpp | 307 +++++++++++++++ headers/3rdparty/variant/lib.hpp | 7 - headers/3rdparty/variant/variant.hpp | 7 - modules/catch2 | 2 +- modules/promise.hpp | 2 +- modules/pugixml | 2 +- modules/rapidjson | 2 +- modules/variant | 2 +- scripts/update_modules.sh | 2 + sources/3rdparty/rapidjson/filereadstream.h | 2 +- sources/3rdparty/rapidjson/internal/regex.h | 7 +- sources/3rdparty/rapidjson/istreamwrapper.h | 82 ++-- toolset/model_converter/modules/assimp | 2 +- 15 files changed, 929 insertions(+), 76 deletions(-) create mode 100644 headers/3rdparty/promise.hpp/jobber.hpp create mode 100644 headers/3rdparty/promise.hpp/scheduler.hpp diff --git a/headers/3rdparty/promise.hpp/jobber.hpp b/headers/3rdparty/promise.hpp/jobber.hpp new file mode 100644 index 00000000..4cef5289 --- /dev/null +++ b/headers/3rdparty/promise.hpp/jobber.hpp @@ -0,0 +1,399 @@ +/******************************************************************************* + * This file is part of the "promise.hpp" + * For conditions of distribution and use, see copyright notice in LICENSE.md + * Copyright (C) 2018 Matvey Cherevko + ******************************************************************************/ + +#pragma once + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "promise.hpp" + +namespace jobber_hpp +{ + using namespace promise_hpp; + + enum class jobber_priority { + lowest, + below_normal, + normal, + above_normal, + highest + }; + + enum class jobber_wait_status { + no_timeout, + cancelled, + timeout + }; + + class jobber_cancelled_exception : public std::runtime_error { + public: + jobber_cancelled_exception() + : std::runtime_error("jobber has stopped working") {} + }; + + class jobber final : private detail::noncopyable { + public: + explicit jobber(std::size_t threads); + ~jobber() noexcept; + + template < typename F, typename... Args > + using async_invoke_result_t = invoke_hpp::invoke_result_t< + std::decay_t, + std::decay_t...>; + + template < typename F, typename... Args + , typename R = async_invoke_result_t > + promise async(F&& f, Args&&... args); + + template < typename F, typename... Args + , typename R = async_invoke_result_t > + promise async(jobber_priority priority, F&& f, Args&&... args); + + void pause() noexcept; + void resume() noexcept; + bool is_paused() const noexcept; + + jobber_wait_status wait_all() const noexcept; + jobber_wait_status active_wait_all() noexcept; + + template < typename Rep, typename Period > + jobber_wait_status wait_all_for( + const std::chrono::duration& timeout_duration) const; + + template < typename Clock, typename Duration > + jobber_wait_status wait_all_until( + const std::chrono::time_point& timeout_time) const; + + template < typename Rep, typename Period > + jobber_wait_status active_wait_all_for( + const std::chrono::duration& timeout_duration); + + template < typename Clock, typename Duration > + jobber_wait_status active_wait_all_until( + const std::chrono::time_point& timeout_time); + private: + class task; + using task_ptr = std::unique_ptr; + template < typename R, typename F, typename... Args > + class concrete_task; + private: + void push_task_(jobber_priority priority, task_ptr task); + task_ptr pop_task_() noexcept; + void shutdown_() noexcept; + void worker_main_() noexcept; + void process_task_(std::unique_lock lock) noexcept; + private: + std::vector threads_; + std::vector> tasks_; + std::atomic paused_{false}; + std::atomic cancelled_{false}; + std::atomic active_task_count_{0}; + mutable std::mutex tasks_mutex_; + mutable std::condition_variable cond_var_; + }; + + class jobber::task : private noncopyable { + public: + virtual ~task() noexcept = default; + virtual void run() noexcept = 0; + virtual void cancel() noexcept = 0; + }; + + template < typename R, typename F, typename... Args > + class jobber::concrete_task : public task { + F f_; + std::tuple args_; + promise promise_; + public: + template < typename U > + concrete_task(U&& u, std::tuple&& args); + void run() noexcept final; + void cancel() noexcept final; + promise future() noexcept; + }; + + template < typename F, typename... Args > + class jobber::concrete_task : public task { + F f_; + std::tuple args_; + promise promise_; + public: + template < typename U > + concrete_task(U&& u, std::tuple&& args); + void run() noexcept final; + void cancel() noexcept final; + promise future() noexcept; + }; +} + +namespace jobber_hpp +{ + inline jobber::jobber(std::size_t threads) { + try { + threads_.resize(threads); + for ( std::thread& thread : threads_ ) { + thread = std::thread(&jobber::worker_main_, this); + } + } catch (...) { + shutdown_(); + throw; + } + } + + inline jobber::~jobber() noexcept { + shutdown_(); + } + + template < typename F, typename... Args, typename R > + promise jobber::async(F&& f, Args&&... args) { + return async( + jobber_priority::normal, + std::forward(f), + std::forward(args)...); + } + + template < typename F, typename... Args, typename R > + promise jobber::async(jobber_priority priority, F&& f, Args&&... args) { + using task_t = concrete_task< + R, + std::decay_t, + std::decay_t...>; + std::unique_ptr task = std::make_unique( + std::forward(f), + std::make_tuple(std::forward(args)...)); + promise future = task->future(); + std::lock_guard guard(tasks_mutex_); + push_task_(priority, std::move(task)); + return future; + } + + inline void jobber::pause() noexcept { + std::lock_guard guard(tasks_mutex_); + paused_.store(true); + cond_var_.notify_all(); + } + + inline void jobber::resume() noexcept { + std::lock_guard guard(tasks_mutex_); + paused_.store(false); + cond_var_.notify_all(); + } + + inline bool jobber::is_paused() const noexcept { + return paused_; + } + + inline jobber_wait_status jobber::wait_all() const noexcept { + std::unique_lock lock(tasks_mutex_); + cond_var_.wait(lock, [this](){ + return cancelled_ || !active_task_count_; + }); + return cancelled_ + ? jobber_wait_status::cancelled + : jobber_wait_status::no_timeout; + } + + inline jobber_wait_status jobber::active_wait_all() noexcept { + while ( !cancelled_ && active_task_count_ ) { + std::unique_lock lock(tasks_mutex_); + cond_var_.wait(lock, [this](){ + return cancelled_ || !active_task_count_ || !tasks_.empty(); + }); + if ( !tasks_.empty() ) { + process_task_(std::move(lock)); + } + } + return cancelled_ + ? jobber_wait_status::cancelled + : jobber_wait_status::no_timeout; + } + + template < typename Rep, typename Period > + jobber_wait_status jobber::wait_all_for( + const std::chrono::duration& timeout_duration) const + { + return wait_all_until( + std::chrono::steady_clock::now() + timeout_duration); + } + + template < typename Clock, typename Duration > + jobber_wait_status jobber::wait_all_until( + const std::chrono::time_point& timeout_time) const + { + std::unique_lock lock(tasks_mutex_); + return cond_var_.wait_until(lock, timeout_time, [this](){ + return cancelled_ || !active_task_count_; + }) ? jobber_wait_status::no_timeout + : jobber_wait_status::timeout; + } + + template < typename Rep, typename Period > + jobber_wait_status jobber::active_wait_all_for( + const std::chrono::duration& timeout_duration) + { + return active_wait_all_until( + std::chrono::steady_clock::now() + timeout_duration); + } + + template < typename Clock, typename Duration > + jobber_wait_status jobber::active_wait_all_until( + const std::chrono::time_point& timeout_time) + { + while ( !cancelled_ && active_task_count_ ) { + if ( !(Clock::now() < timeout_time) ) { + return jobber_wait_status::timeout; + } + std::unique_lock lock(tasks_mutex_); + cond_var_.wait_until(lock, timeout_time, [this](){ + return cancelled_ || !active_task_count_ || !tasks_.empty(); + }); + if ( !tasks_.empty() ) { + process_task_(std::move(lock)); + } + } + return cancelled_ + ? jobber_wait_status::cancelled + : jobber_wait_status::no_timeout; + } + + inline void jobber::push_task_(jobber_priority priority, task_ptr task) { + tasks_.emplace_back(priority, std::move(task)); + std::push_heap(tasks_.begin(), tasks_.end()); + ++active_task_count_; + cond_var_.notify_all(); + } + + inline jobber::task_ptr jobber::pop_task_() noexcept { + if ( !tasks_.empty() ) { + std::pop_heap(tasks_.begin(), tasks_.end()); + task_ptr task = std::move(tasks_.back().second); + tasks_.pop_back(); + return task; + } + return nullptr; + } + + inline void jobber::shutdown_() noexcept { + { + std::lock_guard guard(tasks_mutex_); + while ( !tasks_.empty() ) { + task_ptr task = pop_task_(); + if ( task ) { + task->cancel(); + --active_task_count_; + } + } + cancelled_.store(true); + cond_var_.notify_all(); + } + for ( std::thread& thread : threads_ ) { + if ( thread.joinable() ) { + thread.join(); + } + } + } + + inline void jobber::worker_main_() noexcept { + while ( true ) { + std::unique_lock lock(tasks_mutex_); + cond_var_.wait(lock, [this](){ + return cancelled_ || (!paused_ && !tasks_.empty()); + }); + if ( cancelled_ ) { + break; + } + process_task_(std::move(lock)); + } + } + + inline void jobber::process_task_(std::unique_lock lock) noexcept { + assert(lock.owns_lock()); + task_ptr task = pop_task_(); + if ( task ) { + lock.unlock(); + task->run(); + --active_task_count_; + cond_var_.notify_all(); + } + } +} + +namespace jobber_hpp +{ + // + // concrete_task + // + + template < typename R, typename F, typename... Args > + template < typename U > + jobber::concrete_task::concrete_task(U&& u, std::tuple&& args) + : f_(std::forward(u)) + , args_(std::move(args)) {} + + template < typename R, typename F, typename... Args > + void jobber::concrete_task::run() noexcept { + try { + R value = invoke_hpp::apply(std::move(f_), std::move(args_)); + promise_.resolve(std::move(value)); + } catch (...) { + promise_.reject(std::current_exception()); + } + } + + template < typename R, typename F, typename... Args > + void jobber::concrete_task::cancel() noexcept { + promise_.reject(jobber_cancelled_exception()); + } + + template < typename R, typename F, typename... Args > + promise jobber::concrete_task::future() noexcept { + return promise_; + } + + // + // concrete_task + // + + template < typename F, typename... Args > + template < typename U > + jobber::concrete_task::concrete_task(U&& u, std::tuple&& args) + : f_(std::forward(u)) + , args_(std::move(args)) {} + + template < typename F, typename... Args > + void jobber::concrete_task::run() noexcept { + try { + invoke_hpp::apply(std::move(f_), std::move(args_)); + promise_.resolve(); + } catch (...) { + promise_.reject(std::current_exception()); + } + } + + template < typename F, typename... Args > + void jobber::concrete_task::cancel() noexcept { + promise_.reject(jobber_cancelled_exception()); + } + + template < typename F, typename... Args > + promise jobber::concrete_task::future() noexcept { + return promise_; + } +} diff --git a/headers/3rdparty/promise.hpp/promise.hpp b/headers/3rdparty/promise.hpp/promise.hpp index febbf579..62678a80 100644 --- a/headers/3rdparty/promise.hpp/promise.hpp +++ b/headers/3rdparty/promise.hpp/promise.hpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -20,6 +21,7 @@ #include #include #include +#include // // invoke.hpp @@ -368,6 +370,15 @@ namespace promise_hpp }; } + // + // promise_wait_status + // + + enum class promise_wait_status { + no_timeout, + timeout + }; + // // promise // @@ -376,12 +387,6 @@ namespace promise_hpp class promise final { public: using value_type = T; - - enum class status : std::uint8_t { - pending, - resolved, - rejected - }; public: promise() : state_(std::make_shared()) {} @@ -535,6 +540,28 @@ namespace promise_hpp return state_->reject( std::make_exception_ptr(std::forward(e))); } + + const T& get() const { + return state_->get(); + } + + void wait() const noexcept { + state_->wait(); + } + + template < typename Rep, typename Period > + promise_wait_status wait_for( + const std::chrono::duration& timeout_duration) const + { + return state_->wait_for(timeout_duration); + } + + template < typename Clock, typename Duration > + promise_wait_status wait_until( + const std::chrono::time_point& timeout_time) const + { + return state_->wait_until(timeout_time); + } private: class state; std::shared_ptr state_; @@ -552,6 +579,7 @@ namespace promise_hpp storage_.set(std::forward(value)); status_ = status::resolved; invoke_resolve_handlers_(); + cond_var_.notify_all(); return true; } @@ -563,9 +591,51 @@ namespace promise_hpp exception_ = e; status_ = status::rejected; invoke_reject_handlers_(); + cond_var_.notify_all(); return true; } + const T& get() { + std::unique_lock lock(mutex_); + cond_var_.wait(lock, [this](){ + return status_ != status::pending; + }); + if ( status_ == status::rejected ) { + std::rethrow_exception(exception_); + } + assert(status_ == status::resolved); + return storage_.value(); + } + + void wait() const noexcept { + std::unique_lock lock(mutex_); + cond_var_.wait(lock, [this](){ + return status_ != status::pending; + }); + } + + template < typename Rep, typename Period > + promise_wait_status wait_for( + const std::chrono::duration& timeout_duration) const + { + std::unique_lock lock(mutex_); + return cond_var_.wait_for(lock, timeout_duration, [this](){ + return status_ != status::pending; + }) ? promise_wait_status::no_timeout + : promise_wait_status::timeout; + } + + template < typename Clock, typename Duration > + promise_wait_status wait_until( + const std::chrono::time_point& timeout_time) const + { + std::unique_lock lock(mutex_); + return cond_var_.wait_until(lock, timeout_time, [this](){ + return status_ != status::pending; + }) ? promise_wait_status::no_timeout + : promise_wait_status::timeout; + } + template < typename U, typename ResolveF, typename RejectF > std::enable_if_t::value, void> attach(promise& next, ResolveF&& resolve, RejectF&& reject) { @@ -674,11 +744,17 @@ namespace promise_hpp handlers_.clear(); } private: - detail::storage storage_; - status status_ = status::pending; - std::exception_ptr exception_ = nullptr; + enum class status { + pending, + resolved, + rejected + }; - std::mutex mutex_; + status status_{status::pending}; + std::exception_ptr exception_{nullptr}; + + mutable std::mutex mutex_; + mutable std::condition_variable cond_var_; struct handler { using resolve_t = std::function; @@ -694,6 +770,7 @@ namespace promise_hpp }; std::vector handlers_; + detail::storage storage_; }; }; @@ -705,12 +782,6 @@ namespace promise_hpp class promise final { public: using value_type = void; - - enum class status : std::uint8_t { - pending, - resolved, - rejected - }; public: promise() : state_(std::make_shared()) {} @@ -858,6 +929,28 @@ namespace promise_hpp return state_->reject( std::make_exception_ptr(std::forward(e))); } + + void get() const { + state_->get(); + } + + void wait() const noexcept { + state_->wait(); + } + + template < typename Rep, typename Period > + promise_wait_status wait_for( + const std::chrono::duration& timeout_duration) const + { + return state_->wait_for(timeout_duration); + } + + template < typename Clock, typename Duration > + promise_wait_status wait_until( + const std::chrono::time_point& timeout_time) const + { + return state_->wait_until(timeout_time); + } private: class state; std::shared_ptr state_; @@ -873,6 +966,7 @@ namespace promise_hpp } status_ = status::resolved; invoke_resolve_handlers_(); + cond_var_.notify_all(); return true; } @@ -884,9 +978,50 @@ namespace promise_hpp exception_ = e; status_ = status::rejected; invoke_reject_handlers_(); + cond_var_.notify_all(); return true; } + void get() { + std::unique_lock lock(mutex_); + cond_var_.wait(lock, [this](){ + return status_ != status::pending; + }); + if ( status_ == status::rejected ) { + std::rethrow_exception(exception_); + } + assert(status_ == status::resolved); + } + + void wait() const noexcept { + std::unique_lock lock(mutex_); + cond_var_.wait(lock, [this](){ + return status_ != status::pending; + }); + } + + template < typename Rep, typename Period > + promise_wait_status wait_for( + const std::chrono::duration& timeout_duration) const + { + std::unique_lock lock(mutex_); + return cond_var_.wait_for(lock, timeout_duration, [this](){ + return status_ != status::pending; + }) ? promise_wait_status::no_timeout + : promise_wait_status::timeout; + } + + template < typename Clock, typename Duration > + promise_wait_status wait_until( + const std::chrono::time_point& timeout_time) const + { + std::unique_lock lock(mutex_); + return cond_var_.wait_until(lock, timeout_time, [this](){ + return status_ != status::pending; + }) ? promise_wait_status::no_timeout + : promise_wait_status::timeout; + } + template < typename U, typename ResolveF, typename RejectF > std::enable_if_t::value, void> attach(promise& next, ResolveF&& resolve, RejectF&& reject) { @@ -991,10 +1126,17 @@ namespace promise_hpp handlers_.clear(); } private: - status status_ = status::pending; - std::exception_ptr exception_ = nullptr; + enum class status { + pending, + resolved, + rejected + }; - std::mutex mutex_; + status status_{status::pending}; + std::exception_ptr exception_{nullptr}; + + mutable std::mutex mutex_; + mutable std::condition_variable cond_var_; struct handler { using resolve_t = std::function; diff --git a/headers/3rdparty/promise.hpp/scheduler.hpp b/headers/3rdparty/promise.hpp/scheduler.hpp new file mode 100644 index 00000000..303fa577 --- /dev/null +++ b/headers/3rdparty/promise.hpp/scheduler.hpp @@ -0,0 +1,307 @@ +/******************************************************************************* + * This file is part of the "promise.hpp" + * For conditions of distribution and use, see copyright notice in LICENSE.md + * Copyright (C) 2018 Matvey Cherevko + ******************************************************************************/ + +#pragma once + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "promise.hpp" + +namespace scheduler_hpp +{ + using namespace promise_hpp; + + enum class scheduler_priority { + lowest, + below_normal, + normal, + above_normal, + highest + }; + + enum class scheduler_wait_status { + no_timeout, + cancelled, + timeout + }; + + class scheduler_cancelled_exception : public std::runtime_error { + public: + scheduler_cancelled_exception() + : std::runtime_error("scheduler has stopped working") {} + }; + + class scheduler final : private detail::noncopyable { + public: + scheduler(); + ~scheduler() noexcept; + + template < typename F, typename... Args > + using schedule_invoke_result_t = invoke_hpp::invoke_result_t< + std::decay_t, + std::decay_t...>; + + template < typename F, typename... Args + , typename R = schedule_invoke_result_t > + promise schedule(F&& f, Args&&... args); + + template < typename F, typename... Args + , typename R = schedule_invoke_result_t > + promise schedule(scheduler_priority scheduler_priority, F&& f, Args&&... args); + + scheduler_wait_status process_all_tasks() noexcept; + + template < typename Rep, typename Period > + scheduler_wait_status process_tasks_for( + const std::chrono::duration& timeout_duration) noexcept; + + template < typename Clock, typename Duration > + scheduler_wait_status process_tasks_until( + const std::chrono::time_point& timeout_time) noexcept; + private: + class task; + using task_ptr = std::unique_ptr; + template < typename R, typename F, typename... Args > + class concrete_task; + private: + void push_task_(scheduler_priority scheduler_priority, task_ptr task); + task_ptr pop_task_() noexcept; + void shutdown_() noexcept; + void process_task_(std::unique_lock lock) noexcept; + private: + std::vector> tasks_; + std::atomic cancelled_{false}; + std::atomic active_task_count_{0}; + mutable std::mutex tasks_mutex_; + mutable std::condition_variable cond_var_; + }; + + class scheduler::task : private noncopyable { + public: + virtual ~task() noexcept = default; + virtual void run() noexcept = 0; + virtual void cancel() noexcept = 0; + }; + + template < typename R, typename F, typename... Args > + class scheduler::concrete_task : public task { + F f_; + std::tuple args_; + promise promise_; + public: + template < typename U > + concrete_task(U&& u, std::tuple&& args); + void run() noexcept final; + void cancel() noexcept final; + promise future() noexcept; + }; + + template < typename F, typename... Args > + class scheduler::concrete_task : public task { + F f_; + std::tuple args_; + promise promise_; + public: + template < typename U > + concrete_task(U&& u, std::tuple&& args); + void run() noexcept final; + void cancel() noexcept final; + promise future() noexcept; + }; +} + +namespace scheduler_hpp +{ + inline scheduler::scheduler() = default; + + inline scheduler::~scheduler() noexcept { + shutdown_(); + } + + template < typename F, typename... Args, typename R > + promise scheduler::schedule(F&& f, Args&&... args) { + return schedule( + scheduler_priority::normal, + std::forward(f), + std::forward(args)...); + } + + template < typename F, typename... Args, typename R > + promise scheduler::schedule(scheduler_priority priority, F&& f, Args&&... args) { + using task_t = concrete_task< + R, + std::decay_t, + std::decay_t...>; + std::unique_ptr task = std::make_unique( + std::forward(f), + std::make_tuple(std::forward(args)...)); + promise future = task->future(); + std::lock_guard guard(tasks_mutex_); + push_task_(priority, std::move(task)); + return future; + } + + inline scheduler_wait_status scheduler::process_all_tasks() noexcept { + while ( !cancelled_ && active_task_count_ ) { + std::unique_lock lock(tasks_mutex_); + cond_var_.wait(lock, [this](){ + return cancelled_ || !active_task_count_ || !tasks_.empty(); + }); + if ( !tasks_.empty() ) { + process_task_(std::move(lock)); + } + } + return cancelled_ + ? scheduler_wait_status::cancelled + : scheduler_wait_status::no_timeout; + } + + template < typename Rep, typename Period > + scheduler_wait_status scheduler::process_tasks_for( + const std::chrono::duration& timeout_duration) noexcept + { + return process_tasks_until( + std::chrono::steady_clock::now() + timeout_duration); + } + + template < typename Clock, typename Duration > + scheduler_wait_status scheduler::process_tasks_until( + const std::chrono::time_point& timeout_time) noexcept + { + while ( !cancelled_ && active_task_count_ ) { + if ( !(Clock::now() < timeout_time) ) { + return scheduler_wait_status::timeout; + } + std::unique_lock lock(tasks_mutex_); + cond_var_.wait_until(lock, timeout_time, [this](){ + return cancelled_ || !active_task_count_ || !tasks_.empty(); + }); + if ( !tasks_.empty() ) { + process_task_(std::move(lock)); + } + } + return cancelled_ + ? scheduler_wait_status::cancelled + : scheduler_wait_status::no_timeout; + } + + inline void scheduler::push_task_(scheduler_priority priority, task_ptr task) { + tasks_.emplace_back(priority, std::move(task)); + std::push_heap(tasks_.begin(), tasks_.end()); + ++active_task_count_; + cond_var_.notify_all(); + } + + inline scheduler::task_ptr scheduler::pop_task_() noexcept { + if ( !tasks_.empty() ) { + std::pop_heap(tasks_.begin(), tasks_.end()); + task_ptr task = std::move(tasks_.back().second); + tasks_.pop_back(); + return task; + } + return nullptr; + } + + inline void scheduler::shutdown_() noexcept { + std::lock_guard guard(tasks_mutex_); + while ( !tasks_.empty() ) { + task_ptr task = pop_task_(); + if ( task ) { + task->cancel(); + --active_task_count_; + } + } + cancelled_.store(true); + cond_var_.notify_all(); + } + + inline void scheduler::process_task_(std::unique_lock lock) noexcept { + assert(lock.owns_lock()); + task_ptr task = pop_task_(); + if ( task ) { + lock.unlock(); + task->run(); + --active_task_count_; + cond_var_.notify_all(); + } + } +} + +namespace scheduler_hpp +{ + // + // concrete_task + // + + template < typename R, typename F, typename... Args > + template < typename U > + scheduler::concrete_task::concrete_task(U&& u, std::tuple&& args) + : f_(std::forward(u)) + , args_(std::move(args)) {} + + template < typename R, typename F, typename... Args > + void scheduler::concrete_task::run() noexcept { + try { + R value = invoke_hpp::apply(std::move(f_), std::move(args_)); + promise_.resolve(std::move(value)); + } catch (...) { + promise_.reject(std::current_exception()); + } + } + + template < typename R, typename F, typename... Args > + void scheduler::concrete_task::cancel() noexcept { + promise_.reject(scheduler_cancelled_exception()); + } + + template < typename R, typename F, typename... Args > + promise scheduler::concrete_task::future() noexcept { + return promise_; + } + + // + // concrete_task + // + + template < typename F, typename... Args > + template < typename U > + scheduler::concrete_task::concrete_task(U&& u, std::tuple&& args) + : f_(std::forward(u)) + , args_(std::move(args)) {} + + template < typename F, typename... Args > + void scheduler::concrete_task::run() noexcept { + try { + invoke_hpp::apply(std::move(f_), std::move(args_)); + promise_.resolve(); + } catch (...) { + promise_.reject(std::current_exception()); + } + } + + template < typename F, typename... Args > + void scheduler::concrete_task::cancel() noexcept { + promise_.reject(scheduler_cancelled_exception()); + } + + template < typename F, typename... Args > + promise scheduler::concrete_task::future() noexcept { + return promise_; + } +} diff --git a/headers/3rdparty/variant/lib.hpp b/headers/3rdparty/variant/lib.hpp index 81ffabf2..a36870bd 100644 --- a/headers/3rdparty/variant/lib.hpp +++ b/headers/3rdparty/variant/lib.hpp @@ -207,15 +207,8 @@ namespace mpark { template ::value> struct is_nothrow_swappable { -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wnoexcept" -#endif static constexpr bool value = noexcept(swap(std::declval(), std::declval())); -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic pop -#endif }; template diff --git a/headers/3rdparty/variant/variant.hpp b/headers/3rdparty/variant/variant.hpp index bc7dd87d..f0ac1c61 100644 --- a/headers/3rdparty/variant/variant.hpp +++ b/headers/3rdparty/variant/variant.hpp @@ -1814,19 +1814,12 @@ namespace mpark { lib::forward(vs)...)) #endif -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wnoexcept" -#endif template inline auto swap(variant &lhs, variant &rhs) noexcept(noexcept(lhs.swap(rhs))) -> decltype(lhs.swap(rhs)) { lhs.swap(rhs); } -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic pop -#endif namespace detail { diff --git a/modules/catch2 b/modules/catch2 index 4902cd72..461843b1 160000 --- a/modules/catch2 +++ b/modules/catch2 @@ -1 +1 @@ -Subproject commit 4902cd721586822ded795afe0c418c553137306a +Subproject commit 461843b1f02a4bf5c59db88ff201d2c56fabf3a4 diff --git a/modules/promise.hpp b/modules/promise.hpp index 8491a7a2..4fb77fb4 160000 --- a/modules/promise.hpp +++ b/modules/promise.hpp @@ -1 +1 @@ -Subproject commit 8491a7a2efc5496b065a9f5029afae3db58911c0 +Subproject commit 4fb77fb49d2932cf44157f4d154465520f3c420d diff --git a/modules/pugixml b/modules/pugixml index 7664bbf9..b3db08ff 160000 --- a/modules/pugixml +++ b/modules/pugixml @@ -1 +1 @@ -Subproject commit 7664bbf9af474b71bd4be02359da8ab4ebe315fc +Subproject commit b3db08ffccb78d680d8f7665ad9ed4cff6f92fcf diff --git a/modules/rapidjson b/modules/rapidjson index 30d92a63..66eb6067 160000 --- a/modules/rapidjson +++ b/modules/rapidjson @@ -1 +1 @@ -Subproject commit 30d92a6399b6077006d976b1dc05ee13305bf1c4 +Subproject commit 66eb6067b10fd02e419f88816a8833a64eb33551 diff --git a/modules/variant b/modules/variant index 8e46e094..7dd1e48c 160000 --- a/modules/variant +++ b/modules/variant @@ -1 +1 @@ -Subproject commit 8e46e0941f9e75e94b82dd90accfff72558e3990 +Subproject commit 7dd1e48c33856a3dbee44c2a1ba8f2daa3665a58 diff --git a/scripts/update_modules.sh b/scripts/update_modules.sh index 3c173695..9bdf1804 100755 --- a/scripts/update_modules.sh +++ b/scripts/update_modules.sh @@ -26,7 +26,9 @@ mkdir -p $HEADERS_RDPARTY_DIR/invoke.hpp cp -rfv $MODULES_DIR/invoke.hpp/invoke.hpp $HEADERS_RDPARTY_DIR/invoke.hpp/invoke.hpp mkdir -p $HEADERS_RDPARTY_DIR/promise.hpp +cp -rfv $MODULES_DIR/promise.hpp/jobber.hpp $HEADERS_RDPARTY_DIR/promise.hpp/jobber.hpp cp -rfv $MODULES_DIR/promise.hpp/promise.hpp $HEADERS_RDPARTY_DIR/promise.hpp/promise.hpp +cp -rfv $MODULES_DIR/promise.hpp/scheduler.hpp $HEADERS_RDPARTY_DIR/promise.hpp/scheduler.hpp mkdir -p $SOURCES_RDPARTY_DIR/pugixml cp -rfv $MODULES_DIR/pugixml/src/. $SOURCES_RDPARTY_DIR/pugixml/ diff --git a/sources/3rdparty/rapidjson/filereadstream.h b/sources/3rdparty/rapidjson/filereadstream.h index f1bfb7d0..6b343707 100644 --- a/sources/3rdparty/rapidjson/filereadstream.h +++ b/sources/3rdparty/rapidjson/filereadstream.h @@ -59,7 +59,7 @@ public: // For encoding detection only. const Ch* Peek4() const { - return (current_ + 4 <= bufferLast_) ? current_ : 0; + return (current_ + 4 - !eof_ <= bufferLast_) ? current_ : 0; } private: diff --git a/sources/3rdparty/rapidjson/internal/regex.h b/sources/3rdparty/rapidjson/internal/regex.h index 377f86ce..16e35592 100644 --- a/sources/3rdparty/rapidjson/internal/regex.h +++ b/sources/3rdparty/rapidjson/internal/regex.h @@ -395,8 +395,7 @@ private: } return false; - default: - RAPIDJSON_ASSERT(op == kOneOrMore); + case kOneOrMore: if (operandStack.GetSize() >= sizeof(Frag)) { Frag e = *operandStack.template Pop(1); SizeType s = NewState(kRegexInvalidState, e.start, 0); @@ -405,6 +404,10 @@ private: return true; } return false; + + default: + // syntax error (e.g. unclosed kLeftParenthesis) + return false; } } diff --git a/sources/3rdparty/rapidjson/istreamwrapper.h b/sources/3rdparty/rapidjson/istreamwrapper.h index 5f816982..f304fb03 100644 --- a/sources/3rdparty/rapidjson/istreamwrapper.h +++ b/sources/3rdparty/rapidjson/istreamwrapper.h @@ -48,57 +48,71 @@ template class BasicIStreamWrapper { public: typedef typename StreamType::char_type Ch; - BasicIStreamWrapper(StreamType& stream) : stream_(stream), count_(), peekBuffer_() {} - Ch Peek() const { - typename StreamType::int_type c = stream_.peek(); - return RAPIDJSON_LIKELY(c != StreamType::traits_type::eof()) ? static_cast(c) : static_cast('\0'); + //! Constructor. + /*! + \param stream stream opened for read. + */ + BasicIStreamWrapper(StreamType &stream) : stream_(stream), buffer_(peekBuffer_), bufferSize_(4), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { + Read(); } - Ch Take() { - typename StreamType::int_type c = stream_.get(); - if (RAPIDJSON_LIKELY(c != StreamType::traits_type::eof())) { - count_++; - return static_cast(c); - } - else - return '\0'; + //! Constructor. + /*! + \param stream stream opened for read. + \param buffer user-supplied buffer. + \param bufferSize size of buffer in bytes. Must >=4 bytes. + */ + BasicIStreamWrapper(StreamType &stream, char* buffer, size_t bufferSize) : stream_(stream), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { + RAPIDJSON_ASSERT(bufferSize >= 4); + Read(); } - // tellg() may return -1 when failed. So we count by ourself. - size_t Tell() const { return count_; } + Ch Peek() const { return *current_; } + Ch Take() { Ch c = *current_; Read(); return c; } + size_t Tell() const { return count_ + static_cast(current_ - buffer_); } - Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + // Not implemented void Put(Ch) { RAPIDJSON_ASSERT(false); } - void Flush() { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } // For encoding detection only. const Ch* Peek4() const { - RAPIDJSON_ASSERT(sizeof(Ch) == 1); // Only usable for byte stream. - int i; - bool hasError = false; - for (i = 0; i < 4; ++i) { - typename StreamType::int_type c = stream_.get(); - if (c == StreamType::traits_type::eof()) { - hasError = true; - stream_.clear(); - break; - } - peekBuffer_[i] = static_cast(c); - } - for (--i; i >= 0; --i) - stream_.putback(peekBuffer_[i]); - return !hasError ? peekBuffer_ : 0; + return (current_ + 4 - !eof_ <= bufferLast_) ? current_ : 0; } private: + BasicIStreamWrapper(); BasicIStreamWrapper(const BasicIStreamWrapper&); BasicIStreamWrapper& operator=(const BasicIStreamWrapper&); - StreamType& stream_; - size_t count_; //!< Number of characters read. Note: - mutable Ch peekBuffer_[4]; + void Read() { + if (current_ < bufferLast_) + ++current_; + else if (!eof_) { + count_ += readCount_; + readCount_ = bufferSize_; + bufferLast_ = buffer_ + readCount_ - 1; + current_ = buffer_; + + if (!stream_.read(buffer_, static_cast(bufferSize_))) { + readCount_ = static_cast(stream_.gcount()); + *(bufferLast_ = buffer_ + readCount_) = '\0'; + eof_ = true; + } + } + } + + StreamType &stream_; + Ch peekBuffer_[4], *buffer_; + size_t bufferSize_; + Ch *bufferLast_; + Ch *current_; + size_t readCount_; + size_t count_; //!< Number of characters read + bool eof_; }; typedef BasicIStreamWrapper IStreamWrapper; diff --git a/toolset/model_converter/modules/assimp b/toolset/model_converter/modules/assimp index d7eae5bb..15fe157f 160000 --- a/toolset/model_converter/modules/assimp +++ b/toolset/model_converter/modules/assimp @@ -1 +1 @@ -Subproject commit d7eae5bb1384025b3e7e7812fd45195970d79917 +Subproject commit 15fe157fdc51b99143aefaf7d33c3552c1cbc46a