Skip to content

Commit

Permalink
Merge pull request #173 from stlab/develop
Browse files Browse the repository at this point in the history
Release 1.3.1
  • Loading branch information
FelixPetriconi authored Jul 21, 2018
2 parents 128cc41 + 41d7c95 commit fdb3ab4
Show file tree
Hide file tree
Showing 10 changed files with 311 additions and 269 deletions.
8 changes: 8 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## v1.3.1 - 2018 - July - 21

- Fixed Issues
- [#169](https://github.com/stlab/libraries/issues/169) : when_all() appears to ignore the passed-in executor
- [#168](https://github.com/stlab/libraries/issues/168) : Main Executor requires "widgets" to be dragged into Qt build
- [#167](https://github.com/stlab/libraries/issues/167) : Main Executor has potential segfault
- [#166](https://github.com/stlab/libraries/issues/166) : Multiple task_system and system_timer are being created

## v1.3.0 - 2018 - July - 15

- Fixed Issues
Expand Down
6 changes: 3 additions & 3 deletions stlab/concurrency/default_executor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#define STLAB_CONCURRENCY_DEFAULT_EXECUTOR_HPP

#include <stlab/concurrency/config.hpp>
#include <stlab/concurrency/task.hpp>

#include <chrono>
#include <functional>
Expand Down Expand Up @@ -287,10 +288,9 @@ class task_system {
struct default_executor_type {
using result_type = void;

template <typename F>
void operator()(F&& f) const {
void operator()(task<void()> f) const {
static task_system only_task_system;
only_task_system(std::forward<F>(f));
only_task_system(std::move(f));
}
};

Expand Down
47 changes: 28 additions & 19 deletions stlab/concurrency/future.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1160,13 +1160,15 @@ auto when_all(E executor, F f, future<Ts>... args) {
using result_t = decltype(detail::apply_tuple(std::declval<F>(), std::declval<vt_t>()));

auto shared = std::make_shared<detail::when_all_shared<F, opt_t>>();
auto p = package<result_t()>(std::move(executor), [_f = std::move(f), _p = shared] {
auto p = package<result_t()>(executor, [_f = std::move(f), _p = shared] {
return detail::apply_when_all_args(_f, _p);
});
shared->_f = std::move(p.first);

detail::attach_when_args(shared, std::move(args)...);

executor(std::move(p.first));

return std::move(p.second);
}

Expand All @@ -1179,13 +1181,15 @@ struct make_when_any {
using result_t = typename std::result_of<F(T, size_t)>::type;

auto shared = std::make_shared<detail::when_any_shared<sizeof...(Ts) + 1, T>>();
auto p = package<result_t()>(std::move(executor), [_f = std::move(f), _p = shared] {
auto p = package<result_t()>(executor, [_f = std::move(f), _p = shared] {
return detail::apply_when_any_arg(_f, _p);
});
shared->_f = std::move(p.first);

detail::attach_when_args(shared, std::move(arg), std::move(args)...);

executor(std::move(p.first));

return std::move(p.second);
}
};
Expand All @@ -1199,13 +1203,15 @@ struct make_when_any<void> {
using result_t = typename std::result_of<F(size_t)>::type;

auto shared = std::make_shared<detail::when_any_shared<sizeof...(Ts), void>>();
auto p = package<result_t()>(std::move(executor), [_f = std::forward<F>(f), _p = shared] {
auto p = package<result_t()>(executor, [_f = std::forward<F>(f), _p = shared] {
return detail::apply_when_any_arg(_f, _p);
});
shared->_f = std::move(p.first);

detail::attach_when_args(shared, std::move(args)...);

executor(std::move(p.first));

return std::move(p.second);
}
};
Expand Down Expand Up @@ -1412,12 +1418,12 @@ struct create_range_of_futures;
template <typename R, typename T, typename C>
struct create_range_of_futures<R, T, C, enable_if_copyable<T>> {

template <typename S, typename F, typename I>
static auto do_it(S&& s, F&& f, I first, I last) {
template <typename E, typename F, typename I>
static auto do_it(E executor, F&& f, I first, I last) {
assert(first != last);

auto context = std::make_shared<C>(std::forward<F>(f), std::distance(first, last));
auto p = package<R()>(std::forward<S>(s), [_c = context] { return _c->execute(); });
auto p = package<R()>(executor, [_c = context] { return _c->execute(); });

context->_f = std::move(p.first);

Expand All @@ -1426,31 +1432,34 @@ struct create_range_of_futures<R, T, C, enable_if_copyable<T>> {
attach_tasks(index++, context, *first);
}

executor(std::move(p.first));

return std::move(p.second);
}
};

template <typename R, typename T, typename C>
struct create_range_of_futures<R, T, C, enable_if_not_copyable<T>> {

template <typename S, typename F, typename I>
static auto do_it(S&& s, F&& f, I first, I last) {
assert(first != last);
template <typename E, typename F, typename I>
static auto do_it(E executor, F&& f, I first, I last) {
assert(first != last);

auto context = std::make_shared<C>(std::forward<F>(f), std::distance(first, last));
auto p = package<R()>(std::forward<S>(s), [_c = context] { return _c->execute(); });
auto context = std::make_shared<C>(std::forward<F>(f), std::distance(first, last));
auto p = package<R()>(executor, [_c = context] { return _c->execute(); });

context->_f = std::move(p.first);
context->_f = std::move(p.first);

size_t index(0);
for (; first != last; ++first) {
attach_tasks(index++, context, std::forward<decltype(*first)>(*first));
}
size_t index(0);
for (; first != last; ++first) {
attach_tasks(index++, context, std::forward<decltype(*first)>(*first));
}

return std::move(p.second);
}
};
executor(std::move(p.first));

return std::move(p.second);
}
};

/**************************************************************************************************/

Expand Down
7 changes: 4 additions & 3 deletions stlab/concurrency/main_executor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
#endif

#if STLAB_MAIN_EXECUTOR == STLAB_MAIN_EXECUTOR_QT
#include <QApplication>
#include <QCoreApplication>
#include <QEvent>
#include <stlab/concurrency/task.hpp>
#include <memory>
Expand Down Expand Up @@ -82,7 +82,7 @@ class main_executor_type {

public:
executor_event() : QEvent(QEvent::User), _receiver(new event_receiver()) {
_receiver->moveToThread(QApplication::instance()->thread());
_receiver->moveToThread(QCoreApplication::instance()->thread());
}

template <typename F>
Expand Down Expand Up @@ -111,7 +111,8 @@ class main_executor_type {
void operator()(F f) const {
auto event = std::make_unique<executor_event>();
event->set_task(std::move(f));
QApplication::postEvent(event->receiver(), event.release());
auto receiver = event->receiver();
QCoreApplication::postEvent(receiver, event.release());
}
};

Expand Down
6 changes: 3 additions & 3 deletions stlab/concurrency/system_timer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
/**************************************************************************************************/

#include <stlab/concurrency/config.hpp>
#include <stlab/concurrency/task.hpp>

#include <chrono>
#include <functional>
Expand Down Expand Up @@ -231,10 +232,9 @@ class system_timer {
struct system_timer_type {
using result_type = void;

template <typename F>
void operator()(std::chrono::steady_clock::time_point when, F&& f) const {
void operator()(std::chrono::steady_clock::time_point when, task<void()> f) const {
static system_timer only_system_timer;
only_system_timer(when, std::forward<F>(f));
only_system_timer(when, std::move(f));
}
};

Expand Down
4 changes: 2 additions & 2 deletions stlab/version.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@
// STLAB_VERSION / 100 % 1000 is the minor version
// STLAB_VERSION / 100000 is the major version

#define STLAB_VERSION 100300
#define STLAB_VERSION 100301

//
// STLAB_LIB_VERSION must be defined to be the same as STLAB_VERSION
// but as a *string* in the form "x_y[_z]" where x is the major version
// number, y is the minor version number, and z is the patch level if not 0.

#define STLAB_LIB_VERSION "1_3_0"
#define STLAB_LIB_VERSION "1_3_1"

#endif
66 changes: 34 additions & 32 deletions test/future_when_all_arguments_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,34 +24,35 @@ BOOST_AUTO_TEST_CASE(future_when_all_args_int_with_one_element) {
BOOST_TEST_MESSAGE("running future when_all int with one element");

auto f1 = async(custom_scheduler<0>(), [] { return 42; });
sut = when_all(custom_scheduler<0>(), [](auto x) { return x + x; }, f1);
sut = when_all(custom_scheduler<1>(), [](auto x) { return x + x; }, f1);

check_valid_future(sut);
wait_until_future_completed(sut);

BOOST_REQUIRE_EQUAL(42 + 42, *sut.get_try());
BOOST_REQUIRE_LE(1, custom_scheduler<0>::usage_counter());
BOOST_REQUIRE_LE(1, custom_scheduler<1>::usage_counter());
}

BOOST_AUTO_TEST_CASE(future_when_all_args_int_with_many_elements) {
BOOST_TEST_MESSAGE("running future when_all args int with many elements");

auto f1 = async(custom_scheduler<0>(), [] { return 1; });
auto f2 = async(custom_scheduler<1>(), [] { return 2; });
auto f2 = async(custom_scheduler<0>(), [] { return 2; });
auto f3 = async(custom_scheduler<0>(), [] { return 3; });
auto f4 = async(custom_scheduler<1>(), [] { return 5; });
auto f4 = async(custom_scheduler<0>(), [] { return 5; });

sut = when_all(
custom_scheduler<0>(),
custom_scheduler<1>(),
[](int x1, int x2, int x3, int x4) { return 7 * x1 + 11 * x2 + 13 * x3 + 17 * x4; }, f1, f2,
f3, f4);

check_valid_future(sut);
wait_until_future_completed(sut);

BOOST_REQUIRE_EQUAL(1 * 7 + 2 * 11 + 3 * 13 + 5 * 17, *sut.get_try());
BOOST_REQUIRE_LE(2, custom_scheduler<0>::usage_counter());
BOOST_REQUIRE_LE(2, custom_scheduler<1>::usage_counter());
BOOST_REQUIRE_LE(4, custom_scheduler<0>::usage_counter());
BOOST_REQUIRE_LE(1, custom_scheduler<1>::usage_counter());
}
BOOST_AUTO_TEST_SUITE_END()

Expand All @@ -60,11 +61,11 @@ BOOST_AUTO_TEST_CASE(future_when_all_args_with_different_types) {
BOOST_TEST_MESSAGE("running future when_all args with different types");

auto f1 = async(custom_scheduler<0>(), [] { return 1; });
auto f2 = async(custom_scheduler<1>(), [] { return 3.1415; });
auto f2 = async(custom_scheduler<0>(), [] { return 3.1415; });
auto f3 = async(custom_scheduler<0>(), [] { return std::string("Don't panic!"); });
auto f4 = async(custom_scheduler<1>(), [] { return std::vector<size_t>(2, 3); });
auto f4 = async(custom_scheduler<0>(), [] { return std::vector<size_t>(2, 3); });

sut = when_all(custom_scheduler<0>(),
sut = when_all(custom_scheduler<1>(),
[](int x1, double x2, const std::string& x3, const std::vector<size_t>& x4) {
std::stringstream st;
st << x1 << " " << x2 << " " << x3 << " " << x4[0] << " " << x4[1];
Expand All @@ -76,8 +77,8 @@ BOOST_AUTO_TEST_CASE(future_when_all_args_with_different_types) {
wait_until_future_completed(sut);

BOOST_REQUIRE_EQUAL(std::string("1 3.1415 Don't panic! 3 3"), *sut.get_try());
BOOST_REQUIRE_LE(2, custom_scheduler<0>::usage_counter());
BOOST_REQUIRE_LE(2, custom_scheduler<1>::usage_counter());
BOOST_REQUIRE_LE(4, custom_scheduler<0>::usage_counter());
BOOST_REQUIRE_LE(1, custom_scheduler<1>::usage_counter());
}
BOOST_AUTO_TEST_SUITE_END()

Expand All @@ -90,52 +91,53 @@ BOOST_AUTO_TEST_CASE(future_when_all_args_int_failure_with_one_element) {
BOOST_TEST_MESSAGE("running future when_all int with range of one element");

auto f1 = async(custom_scheduler<0>(), []() -> int { throw test_exception("failure"); });
sut = when_all(custom_scheduler<0>(), [](auto x) { return x + x; }, f1);
sut = when_all(custom_scheduler<1>(), [](auto x) { return x + x; }, f1);

wait_until_future_fails<test_exception>(sut);

check_failure<test_exception>(sut, "failure");
BOOST_REQUIRE_LE(1, custom_scheduler<0>::usage_counter());
BOOST_REQUIRE_LE(1, custom_scheduler<1>::usage_counter());
}

BOOST_AUTO_TEST_CASE(future_when_all_args_int_with_many_elements_one_failing) {
BOOST_TEST_MESSAGE("running future when_all args int with many elements one failing");

auto f1 = async(custom_scheduler<0>(), [] { return 1; });
auto f2 = async(custom_scheduler<1>(), []() -> int { throw test_exception("failure"); });
auto f2 = async(custom_scheduler<0>(), []() -> int { throw test_exception("failure"); });
auto f3 = async(custom_scheduler<0>(), [] { return 3; });
auto f4 = async(custom_scheduler<1>(), [] { return 5; });
auto f4 = async(custom_scheduler<0>(), [] { return 5; });

sut = when_all(
custom_scheduler<0>(),
custom_scheduler<1>(),
[](int x1, int x2, int x3, int x4) { return 7 * x1 + 11 * x2 + 13 * x3 + 17 * x4; }, f1, f2,
f3, f4);

wait_until_future_fails<test_exception>(sut);

check_failure<test_exception>(sut, "failure");
BOOST_REQUIRE_LE(2, custom_scheduler<0>::usage_counter());
BOOST_REQUIRE_LE(2, custom_scheduler<1>::usage_counter());
BOOST_REQUIRE_LE(4, custom_scheduler<0>::usage_counter());
BOOST_REQUIRE_LE(1, custom_scheduler<1>::usage_counter());
}

BOOST_AUTO_TEST_CASE(future_when_all_args_int_with_many_elements_all_failing) {
BOOST_TEST_MESSAGE("running future when_all args int with many elements all failing");

auto f1 = async(custom_scheduler<0>(), []() -> int { throw test_exception("failure"); });
auto f2 = async(custom_scheduler<1>(), []() -> int { throw test_exception("failure"); });
auto f2 = async(custom_scheduler<0>(), []() -> int { throw test_exception("failure"); });
auto f3 = async(custom_scheduler<0>(), []() -> int { throw test_exception("failure"); });
auto f4 = async(custom_scheduler<1>(), []() -> int { throw test_exception("failure"); });
auto f4 = async(custom_scheduler<0>(), []() -> int { throw test_exception("failure"); });

sut = when_all(
custom_scheduler<0>(),
custom_scheduler<1>(),
[](int x1, int x2, int x3, int x4) { return 7 * x1 + 11 * x2 + 13 * x3 + 17 * x4; }, f1, f2,
f3, f4);

wait_until_future_fails<test_exception>(sut);

check_failure<test_exception>(sut, "failure");
BOOST_REQUIRE_LE(2, custom_scheduler<0>::usage_counter());
BOOST_REQUIRE_LE(2, custom_scheduler<1>::usage_counter());
BOOST_REQUIRE_LE(4, custom_scheduler<0>::usage_counter());
BOOST_REQUIRE_LE(1, custom_scheduler<1>::usage_counter());
}

BOOST_AUTO_TEST_SUITE_END()
Expand All @@ -145,12 +147,12 @@ BOOST_AUTO_TEST_CASE(future_when_all_args_with_different_types_one_failing) {
BOOST_TEST_MESSAGE("running future when_all args with different types one failing");

auto f1 = async(custom_scheduler<0>(), [] { return 1; });
auto f2 = async(custom_scheduler<1>(), [] { return 3.1415; });
auto f2 = async(custom_scheduler<0>(), [] { return 3.1415; });
auto f3 =
async(custom_scheduler<0>(), []() -> std::string { throw test_exception("failure"); });
auto f4 = async(custom_scheduler<1>(), [] { return std::vector<size_t>(2, 3); });
auto f4 = async(custom_scheduler<0>(), [] { return std::vector<size_t>(2, 3); });

sut = when_all(custom_scheduler<0>(),
sut = when_all(custom_scheduler<1>(),
[](int x1, double x2, const std::string& x3, const std::vector<size_t>& x4) {
std::stringstream st;
st << x1 << " " << x2 << " " << x3 << " " << x4[0] << " " << x4[1];
Expand All @@ -161,21 +163,21 @@ BOOST_AUTO_TEST_CASE(future_when_all_args_with_different_types_one_failing) {
wait_until_future_fails<test_exception>(sut);

check_failure<test_exception>(sut, "failure");
BOOST_REQUIRE_LE(2, custom_scheduler<0>::usage_counter());
BOOST_REQUIRE_LE(2, custom_scheduler<1>::usage_counter());
BOOST_REQUIRE_LE(4, custom_scheduler<0>::usage_counter());
BOOST_REQUIRE_LE(1, custom_scheduler<1>::usage_counter());
}

BOOST_AUTO_TEST_CASE(future_when_all_args_with_different_types_all_failing) {
BOOST_TEST_MESSAGE("running future when_all args with different types all failing");

auto f1 = async(custom_scheduler<0>(), []() -> int { throw test_exception("failure"); });
auto f2 = async(custom_scheduler<1>(), []() -> double { throw test_exception("failure"); });
auto f2 = async(custom_scheduler<0>(), []() -> double { throw test_exception("failure"); });
auto f3 =
async(custom_scheduler<0>(), []() -> std::string { throw test_exception("failure"); });
auto f4 = async(custom_scheduler<1>(),
auto f4 = async(custom_scheduler<0>(),
[]() -> std::vector<size_t> { throw test_exception("failure"); });

sut = when_all(custom_scheduler<0>(),
sut = when_all(custom_scheduler<1>(),
[](int x1, double x2, const std::string& x3, const std::vector<size_t>& x4) {
std::stringstream st;
st << x1 << " " << x2 << " " << x3 << " " << x4[0] << " " << x4[1];
Expand All @@ -186,8 +188,8 @@ BOOST_AUTO_TEST_CASE(future_when_all_args_with_different_types_all_failing) {
wait_until_future_fails<test_exception>(sut);

check_failure<test_exception>(sut, "failure");
BOOST_REQUIRE_LE(2, custom_scheduler<0>::usage_counter());
BOOST_REQUIRE_LE(2, custom_scheduler<1>::usage_counter());
BOOST_REQUIRE_LE(4, custom_scheduler<0>::usage_counter());
BOOST_REQUIRE_LE(1, custom_scheduler<1>::usage_counter());
}

BOOST_AUTO_TEST_SUITE_END()
Loading

0 comments on commit fdb3ab4

Please sign in to comment.