Last active
December 21, 2015 20:19
-
-
Save arturl/6360774 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using namespace std; | |
class exception_list : public exception | |
{ | |
public: | |
typedef exception_ptr value_type; | |
typedef const value_type& reference; | |
typedef const value_type& const_reference; | |
typedef size_t size_type; | |
typedef vector<exception_ptr>::iterator iterator; | |
typedef vector<exception_ptr>::const_iterator const_iterator; | |
exception_list() {} | |
exception_list(const vector<exception_ptr>& exceptions) : exceptions_(exceptions) {} | |
size_t size() const { | |
return exceptions_.size(); | |
} | |
const_iterator begin() const { | |
return exceptions_.begin(); | |
} | |
const_iterator end() const { | |
return exceptions_.end(); | |
} | |
private: | |
vector<exception_ptr> exceptions_; | |
}; | |
class task_group | |
{ | |
private: | |
enum class exception_handling_mode{ handle, ignore }; | |
enum class dummy_type { tag }; | |
// scratch buffer for locally allocated tasks | |
static const auto scratch_buffer_size = 128; | |
char buff[scratch_buffer_size]; | |
char* buffptr = &buff[0]; | |
task_group(exception_handling_mode mode, dummy_type) : exception_handling_mode_(mode) | |
{ | |
} | |
template<class Func> | |
task_group(const Func& f, dummy_type) : exception_handling_mode_(exception_handling_mode::handle), exception_handler_func_(f) | |
{ | |
} | |
public: | |
static const auto ignore_exceptions = exception_handling_mode::ignore; | |
template<class ExceptionHandler> | |
task_group(ExceptionHandler&& handler) : task_group(handler, dummy_type::tag) {} | |
template<class Func> | |
void run(const Func& f) | |
{ | |
auto size = sizeof(concurrency::task_handle<Func>); | |
concurrency::task_handle<Func> *th; | |
if (buffptr + size >= buff + scratch_buffer_size) | |
{ | |
th = new concurrency::task_handle<Func>(f); | |
owned_tasks.push_back(th); | |
} | |
else | |
{ | |
// dtor is empty, so no need to call it | |
// TODO: ensure proper alignment | |
th = new(buffptr)concurrency::task_handle<Func>(f); | |
buffptr += size; | |
} | |
stg_.run(*th); | |
} | |
// wait swallows exceptions now | |
void wait() /* noexcept */ | |
{ | |
try | |
{ | |
// PPL wait throws | |
stg_.wait(); | |
} | |
catch (...) | |
{ | |
} | |
} | |
~task_group() | |
{ | |
stg_.wait(); | |
try | |
{ | |
stg_.wait(); | |
} | |
catch (...) | |
{ | |
if (exception_handling_mode_ == exception_handling_mode::handle) | |
{ | |
auto exp = std::current_exception(); | |
vector<exception_ptr> exceptions = { exp }; // TBD, for now, only one exception (PPL limitation) | |
exception_handler_func_(exceptions); | |
} | |
} | |
for (auto task : owned_tasks) | |
{ | |
delete task; | |
} | |
} | |
private: | |
function<void(exception_list)> exception_handler_func_; | |
concurrency::structured_task_group stg_; | |
exception_handling_mode exception_handling_mode_; // this member can be avoided by checking if exception_handler_func_ is set | |
vector<concurrency::details::_UnrealizedChore*> owned_tasks; // this can be avoided, but requires changes in the PPL | |
}; | |
#if 0 | |
template<typename Func> | |
auto make_future(task_group &tg, Func&& func) -> std::future<decltype(func())> | |
{ | |
typedef decltype(func()) T; | |
auto p = std::make_unique<std::promise<T>>(); | |
auto f = p->get_future(); | |
tg.run([func, p{ std::move(p) }] { | |
p->set_value(func()); | |
}); | |
return f; | |
} | |
#endif | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment