bloomen / transwarp

A header-only C++ library for task concurrency

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

store parallel executor as a member variable causing crash

niyue opened this issue · comments

commented

I would like to re-use transwarp's parallel executor for transforming data multiple times, so I store it as a class's member variable like this:

class Transformer {
public:
  vector<int> transform(vector<int> &data) {
    vector<int> result(data.size());
    auto t = tw::transform(_exec, data.begin(), data.end(), result.begin(),
                           [&](int x) { return x * 2; });

    return result;
  }

private:
  tw::parallel _exec{1};
};

TEST_CASE("transwarp test") {
  Transformer t;
  auto data = vector<int>{1, 2, 3};
  auto r = t.transform(data);
  REQUIRE(r.size() == 3);
}

But this will cause crash on macOS Big Sur (11.3.1), with stack like this:

Thread 1 Crashed:
0   libsystem_platform.dylib      	0x00007fff2061650c _os_unfair_lock_recursive_abort + 23
1   libsystem_platform.dylib      	0x00007fff20611125 _os_unfair_lock_lock_slow + 258
2   libsystem_malloc.dylib        	0x00007fff203f90e5 free_tiny + 134
3   tracing-tests                 	0x000000010bed15a5 std::__1::_DeallocateCaller::__do_call(void*) + 21 (new:334)
4   tracing-tests                 	0x000000010bed1559 std::__1::_DeallocateCaller::__do_deallocate_handle_size(void*, unsigned long) + 25 (new:292)
5   tracing-tests                 	0x000000010bf4fbf5 std::__1::_DeallocateCaller::__do_deallocate_handle_size_align(void*, unsigned long, unsigned long) + 85 (new:268)
6   tracing-tests                 	0x000000010bf4fb95 std::__1::__libcpp_deallocate(void*, unsigned long, unsigned long) + 37 (new:340)
7   tracing-tests                 	0x000000010bf78a0d std::__1::allocator<std::__1::unique_ptr<std::__1::basic_ostringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::default_delete<std::__1::basic_ostringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >::deallocate(std::__1::unique_ptr<std::__1::basic_ostringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::default_delete<std::__1::basic_ostringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >*, unsigned long) + 45 (memory:1673)
8   tracing-tests                 	0x000000010bf78865 std::__1::allocator_traits<std::__1::allocator<std::__1::unique_ptr<std::__1::basic_ostringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::default_delete<std::__1::basic_ostringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > > >::deallocate(std::__1::allocator<std::__1::unique_ptr<std::__1::basic_ostringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::default_delete<std::__1::basic_ostringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >&, std::__1::unique_ptr<std::__1::basic_ostringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::default_delete<std::__1::basic_ostringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >*, unsigned long) + 37 (memory:1408)
9   tracing-tests                 	0x000000010bf787f4 std::__1::__split_buffer<std::__1::unique_ptr<std::__1::basic_ostringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::default_delete<std::__1::basic_ostringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >, std::__1::allocator<std::__1::unique_ptr<std::__1::basic_ostringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::default_delete<std::__1::basic_ostringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >&>::~__split_buffer() + 100 (__split_buffer:350)
10  tracing-tests                 	0x000000010bf77fb5 std::__1::__split_buffer<std::__1::unique_ptr<std::__1::basic_ostringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::default_delete<std::__1::basic_ostringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >, std::__1::allocator<std::__1::unique_ptr<std::__1::basic_ostringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::default_delete<std::__1::basic_ostringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >&>::~__split_buffer() + 21 (__split_buffer:347)
11  tracing-tests                 	0x000000010bf779ba void std::__1::vector<std::__1::unique_ptr<std::__1::basic_ostringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::default_delete<std::__1::basic_ostringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >, std::__1::allocator<std::__1::unique_ptr<std::__1::basic_ostringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::default_delete<std::__1::basic_ostringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > > >::__push_back_slow_path<std::__1::unique_ptr<std::__1::basic_ostringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::default_delete<std::__1::basic_ostringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >(std::__1::unique_ptr<std::__1::basic_ostringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::default_delete<std::__1::basic_ostringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&&) + 186 (vector:1632)
12  tracing-tests                 	0x000000010bf77757 std::__1::vector<std::__1::unique_ptr<std::__1::basic_ostringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::default_delete<std::__1::basic_ostringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >, std::__1::allocator<std::__1::unique_ptr<std::__1::basic_ostringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::default_delete<std::__1::basic_ostringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > > >::push_back(std::__1::unique_ptr<std::__1::basic_ostringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::default_delete<std::__1::basic_ostringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&&) + 103 (vector:1659)
13  tracing-tests                 	0x000000010bf34a96 Catch::StringStreams::add() + 134 (catch.hpp:13662)
14  tracing-tests                 	0x000000010bf34979 Catch::ReusableStringStream::ReusableStringStream() + 73 (catch.hpp:13679)
15  tracing-tests                 	0x000000010bf1ab45 Catch::ReusableStringStream::ReusableStringStream() + 21 (catch.hpp:13681)
16  tracing-tests                 	0x000000010bf2b745 Catch::MessageStream::MessageStream() + 21 (catch.hpp:2623)
17  tracing-tests                 	0x000000010bf2b70a Catch::MessageBuilder::MessageBuilder(Catch::StringRef const&, Catch::SourceLineInfo const&, Catch::ResultWas::OfType) + 42 (catch.hpp:11782)
18  tracing-tests                 	0x000000010bf24bab Catch::MessageBuilder::MessageBuilder(Catch::StringRef const&, Catch::SourceLineInfo const&, Catch::ResultWas::OfType) + 43 (catch.hpp:11785)
19  tracing-tests                 	0x000000010bf249d9 Catch::AssertionStats::AssertionStats(Catch::AssertionResult const&, std::__1::vector<Catch::MessageInfo, std::__1::allocator<Catch::MessageInfo> > const&, Catch::Totals const&) + 297 (catch.hpp:11044)
20  tracing-tests                 	0x000000010bf24ced Catch::AssertionStats::AssertionStats(Catch::AssertionResult const&, std::__1::vector<Catch::MessageInfo, std::__1::allocator<Catch::MessageInfo> > const&, Catch::Totals const&) + 45 (catch.hpp:11038)
21  tracing-tests                 	0x000000010bf2f48a Catch::RunContext::assertionEnded(Catch::AssertionResult const&) + 330 (catch.hpp:12708)
22  tracing-tests                 	0x000000010bf308ec Catch::RunContext::handleFatalErrorCondition(Catch::StringRef) + 268 (catch.hpp:12831)
23  tracing-tests                 	0x000000010bf24320 (anonymous namespace)::reportFatal(char const*) + 64 (catch.hpp:10756)
24  tracing-tests                 	0x000000010bf2423f Catch::FatalConditionHandler::handleSignal(int) + 143 (catch.hpp:10850)
25  libsystem_platform.dylib      	0x00007fff20612d7d _sigtramp + 29
26  ???                           	0x0000000000008fd0 0 + 36816
27  libsystem_malloc.dylib        	0x00007fff203f97b3 tiny_free_no_lock + 1112
28  libsystem_malloc.dylib        	0x00007fff203f9219 free_tiny + 442
29  tracing-tests                 	0x000000010bf033b7 std::__1::default_delete<transwarp::detail::runner<void, transwarp::root_type, transwarp::detail::task_impl_base<void, transwarp::root_type, std::__1::shared_ptr<transwarp::task_impl<transwarp::wait_type, transwarp::no_op_functor, std::__1::vector<std::__1::shared_ptr<transwarp::task<void> >, std::__1::allocator<std::__1::shared_ptr<transwarp::task<void> > > > > > transwarp::transform<std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, Transformer::transform(std::__1::vector<int, std::__1::allocator<int> >&)::'lambda'(int)>(std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, Transformer::transform(std::__1::vector<int, std::__1::allocator<int> >&)::'lambda'(int))::'lambda'()>, std::__1::tuple<> > >::operator()(transwarp::detail::runner<void, transwarp::root_type, transwarp::detail::task_impl_base<void, transwarp::root_type, std::__1::shared_ptr<transwarp::task_impl<transwarp::wait_type, transwarp::no_op_functor, std::__1::vector<std::__1::shared_ptr<transwarp::task<void> >, std::__1::allocator<std::__1::shared_ptr<transwarp::task<void> > > > > > transwarp::transform<std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, Transformer::transform(std::__1::vector<int, std::__1::allocator<int> >&)::'lambda'(int)>(std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, Transformer::transform(std::__1::vector<int, std::__1::allocator<int> >&)::'lambda'(int))::'lambda'()>, std::__1::tuple<> >*) const + 55 (memory:2084)
30  tracing-tests                 	0x000000010bf03089 std::__1::__shared_ptr_pointer<transwarp::detail::runner<void, transwarp::root_type, transwarp::detail::task_impl_base<void, transwarp::root_type, std::__1::shared_ptr<transwarp::task_impl<transwarp::wait_type, transwarp::no_op_functor, std::__1::vector<std::__1::shared_ptr<transwarp::task<void> >, std::__1::allocator<std::__1::shared_ptr<transwarp::task<void> > > > > > transwarp::transform<std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, Transformer::transform(std::__1::vector<int, std::__1::allocator<int> >&)::'lambda'(int)>(std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, Transformer::transform(std::__1::vector<int, std::__1::allocator<int> >&)::'lambda'(int))::'lambda'()>, std::__1::tuple<> >*, std::__1::shared_ptr<transwarp::detail::runner<void, transwarp::root_type, transwarp::detail::task_impl_base<void, transwarp::root_type, std::__1::shared_ptr<transwarp::task_impl<transwarp::wait_type, transwarp::no_op_functor, std::__1::vector<std::__1::shared_ptr<transwarp::task<void> >, std::__1::allocator<std::__1::shared_ptr<transwarp::task<void> > > > > > transwarp::transform<std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, Transformer::transform(std::__1::vector<int, std::__1::allocator<int> >&)::'lambda'(int)>(std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, Transformer::transform(std::__1::vector<int, std::__1::allocator<int> >&)::'lambda'(int))::'lambda'()>, std::__1::tuple<> > >::__shared_ptr_default_delete<transwarp::detail::runner<void, transwarp::root_type, transwarp::detail::task_impl_base<void, transwarp::root_type, std::__1::shared_ptr<transwarp::task_impl<transwarp::wait_type, transwarp::no_op_functor, std::__1::vector<std::__1::shared_ptr<transwarp::task<void> >, std::__1::allocator<std::__1::shared_ptr<transwarp::task<void> > > > > > transwarp::transform<std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, Transformer::transform(std::__1::vector<int, std::__1::allocator<int> >&)::'lambda'(int)>(std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, Transformer::transform(std::__1::vector<int, std::__1::allocator<int> >&)::'lambda'(int))::'lambda'()>, std::__1::tuple<> >, transwarp::detail::runner<void, transwarp::root_type, transwarp::detail::task_impl_base<void, transwarp::root_type, std::__1::shared_ptr<transwarp::task_impl<transwarp::wait_type, transwarp::no_op_functor, std::__1::vector<std::__1::shared_ptr<transwarp::task<void> >, std::__1::allocator<std::__1::shared_ptr<transwarp::task<void> > > > > > transwarp::transform<std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, Transformer::transform(std::__1::vector<int, std::__1::allocator<int> >&)::'lambda'(int)>(std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, Transformer::transform(std::__1::vector<int, std::__1::allocator<int> >&)::'lambda'(int))::'lambda'()>, std::__1::tuple<> > >, std::__1::allocator<transwarp::detail::runner<void, transwarp::root_type, transwarp::detail::task_impl_base<void, transwarp::root_type, std::__1::shared_ptr<transwarp::task_impl<transwarp::wait_type, transwarp::no_op_functor, std::__1::vector<std::__1::shared_ptr<transwarp::task<void> >, std::__1::allocator<std::__1::shared_ptr<transwarp::task<void> > > > > > transwarp::transform<std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, Transformer::transform(std::__1::vector<int, std::__1::allocator<int> >&)::'lambda'(int)>(std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, Transformer::transform(std::__1::vector<int, std::__1::allocator<int> >&)::'lambda'(int))::'lambda'()>, std::__1::tuple<> > > >::__on_zero_shared() + 89 (memory:3265)
31  tracing-tests                 	0x000000010bedbdfd std::__1::__shared_count::__release_shared() + 61 (memory:3169)
32  tracing-tests                 	0x000000010bedbd9f std::__1::__shared_weak_count::__release_shared() + 31 (memory:3211)
33  tracing-tests                 	0x000000010bedbd6c std::__1::shared_ptr<jaegertracing::Tracer>::~shared_ptr() + 44 (memory:3884)
34  tracing-tests                 	0x000000010becaad5 std::__1::shared_ptr<opentracing::v3::Tracer>::~shared_ptr() + 21 (memory:3882)
35  tracing-tests                 	0x000000010befb225 transwarp::detail::add_listener_visitor::~add_listener_visitor() + 21 (transwarp.h:1328)
36  tracing-tests                 	0x000000010befb0b5 transwarp::detail::add_listener_visitor::~add_listener_visitor() + 21 (transwarp.h:1328)
37  tracing-tests                 	0x000000010bf04205 std::__1::__compressed_pair_elem<transwarp::detail::task_impl_base<void, transwarp::root_type, std::__1::shared_ptr<transwarp::task_impl<transwarp::wait_type, transwarp::no_op_functor, std::__1::vector<std::__1::shared_ptr<transwarp::task<void> >, std::__1::allocator<std::__1::shared_ptr<transwarp::task<void> > > > > > transwarp::transform<std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, Transformer::transform(std::__1::vector<int, std::__1::allocator<int> >&)::'lambda'(int)>(std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, Transformer::transform(std::__1::vector<int, std::__1::allocator<int> >&)::'lambda'(int))::'lambda'()>::schedule_impl(bool, transwarp::executor*)::'lambda0'(), 0, false>::~__compressed_pair_elem() + 21 (memory:1909)
38  tracing-tests                 	0x000000010bf04448 std::__1::__compressed_pair<transwarp::detail::task_impl_base<void, transwarp::root_type, std::__1::shared_ptr<transwarp::task_impl<transwarp::wait_type, transwarp::no_op_functor, std::__1::vector<std::__1::shared_ptr<transwarp::task<void> >, std::__1::allocator<std::__1::shared_ptr<transwarp::task<void> > > > > > transwarp::transform<std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, Transformer::transform(std::__1::vector<int, std::__1::allocator<int> >&)::'lambda'(int)>(std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, Transformer::transform(std::__1::vector<int, std::__1::allocator<int> >&)::'lambda'(int))::'lambda'()>::schedule_impl(bool, transwarp::executor*)::'lambda0'(), std::__1::allocator<transwarp::detail::task_impl_base<void, transwarp::root_type, std::__1::shared_ptr<transwarp::task_impl<transwarp::wait_type, transwarp::no_op_functor, std::__1::vector<std::__1::shared_ptr<transwarp::task<void> >, std::__1::allocator<std::__1::shared_ptr<transwarp::task<void> > > > > > transwarp::transform<std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, Transformer::transform(std::__1::vector<int, std::__1::allocator<int> >&)::'lambda'(int)>(std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, Transformer::transform(std::__1::vector<int, std::__1::allocator<int> >&)::'lambda'(int))::'lambda'()>::schedule_impl(bool, transwarp::executor*)::'lambda0'()> >::~__compressed_pair() + 24 (memory:1983)
39  tracing-tests                 	0x000000010bf04425 std::__1::__compressed_pair<transwarp::detail::task_impl_base<void, transwarp::root_type, std::__1::shared_ptr<transwarp::task_impl<transwarp::wait_type, transwarp::no_op_functor, std::__1::vector<std::__1::shared_ptr<transwarp::task<void> >, std::__1::allocator<std::__1::shared_ptr<transwarp::task<void> > > > > > transwarp::transform<std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, Transformer::transform(std::__1::vector<int, std::__1::allocator<int> >&)::'lambda'(int)>(std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, Transformer::transform(std::__1::vector<int, std::__1::allocator<int> >&)::'lambda'(int))::'lambda'()>::schedule_impl(bool, transwarp::executor*)::'lambda0'(), std::__1::allocator<transwarp::detail::task_impl_base<void, transwarp::root_type, std::__1::shared_ptr<transwarp::task_impl<transwarp::wait_type, transwarp::no_op_functor, std::__1::vector<std::__1::shared_ptr<transwarp::task<void> >, std::__1::allocator<std::__1::shared_ptr<transwarp::task<void> > > > > > transwarp::transform<std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, Transformer::transform(std::__1::vector<int, std::__1::allocator<int> >&)::'lambda'(int)>(std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, Transformer::transform(std::__1::vector<int, std::__1::allocator<int> >&)::'lambda'(int))::'lambda'()>::schedule_impl(bool, transwarp::executor*)::'lambda0'()> >::~__compressed_pair() + 21 (memory:1983)
40  tracing-tests                 	0x000000010bf06b15 std::__1::__function::__alloc_func<transwarp::detail::task_impl_base<void, transwarp::root_type, std::__1::shared_ptr<transwarp::task_impl<transwarp::wait_type, transwarp::no_op_functor, std::__1::vector<std::__1::shared_ptr<transwarp::task<void> >, std::__1::allocator<std::__1::shared_ptr<transwarp::task<void> > > > > > transwarp::transform<std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, Transformer::transform(std::__1::vector<int, std::__1::allocator<int> >&)::'lambda'(int)>(std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, Transformer::transform(std::__1::vector<int, std::__1::allocator<int> >&)::'lambda'(int))::'lambda'()>::schedule_impl(bool, transwarp::executor*)::'lambda0'(), std::__1::allocator<transwarp::detail::task_impl_base<void, transwarp::root_type, std::__1::shared_ptr<transwarp::task_impl<transwarp::wait_type, transwarp::no_op_functor, std::__1::vector<std::__1::shared_ptr<transwarp::task<void> >, std::__1::allocator<std::__1::shared_ptr<transwarp::task<void> > > > > > transwarp::transform<std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, Transformer::transform(std::__1::vector<int, std::__1::allocator<int> >&)::'lambda'(int)>(std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, Transformer::transform(std::__1::vector<int, std::__1::allocator<int> >&)::'lambda'(int))::'lambda'()>::schedule_impl(bool, transwarp::executor*)::'lambda0'()>, void ()>::destroy() + 21 (functional:1572)
41  tracing-tests                 	0x000000010bf057ce std::__1::__function::__func<transwarp::detail::task_impl_base<void, transwarp::root_type, std::__1::shared_ptr<transwarp::task_impl<transwarp::wait_type, transwarp::no_op_functor, std::__1::vector<std::__1::shared_ptr<transwarp::task<void> >, std::__1::allocator<std::__1::shared_ptr<transwarp::task<void> > > > > > transwarp::transform<std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, Transformer::transform(std::__1::vector<int, std::__1::allocator<int> >&)::'lambda'(int)>(std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, Transformer::transform(std::__1::vector<int, std::__1::allocator<int> >&)::'lambda'(int))::'lambda'()>::schedule_impl(bool, transwarp::executor*)::'lambda0'(), std::__1::allocator<transwarp::detail::task_impl_base<void, transwarp::root_type, std::__1::shared_ptr<transwarp::task_impl<transwarp::wait_type, transwarp::no_op_functor, std::__1::vector<std::__1::shared_ptr<transwarp::task<void> >, std::__1::allocator<std::__1::shared_ptr<transwarp::task<void> > > > > > transwarp::transform<std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, Transformer::transform(std::__1::vector<int, std::__1::allocator<int> >&)::'lambda'(int)>(std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, Transformer::transform(std::__1::vector<int, std::__1::allocator<int> >&)::'lambda'(int))::'lambda'()>::schedule_impl(bool, transwarp::executor*)::'lambda0'()>, void ()>::destroy() + 30 (functional:1709)
42  tracing-tests                 	0x000000010bee7b45 std::__1::__function::__value_func<void ()>::~__value_func() + 53 (functional:1839)
43  tracing-tests                 	0x000000010bee7b05 std::__1::__function::__value_func<void ()>::~__value_func() + 21 (functional:1837)
44  tracing-tests                 	0x000000010bee7ae5 std::__1::function<void ()>::~function() + 21 (functional:2542)
45  tracing-tests                 	0x000000010bee70c5 std::__1::function<void ()>::~function() + 21 (functional:2542)
46  tracing-tests                 	0x000000010bee5f3f transwarp::detail::thread_pool::worker(unsigned long) + 447 (transwarp.h:786)
47  tracing-tests                 	0x000000010bee899f decltype(*(std::__1::forward<transwarp::detail::thread_pool*>(fp0)).*fp(std::__1::forward<unsigned long>(fp1))) std::__1::__invoke<void (transwarp::detail::thread_pool::*)(unsigned long), transwarp::detail::thread_pool*, unsigned long, void>(void (transwarp::detail::thread_pool::*&&)(unsigned long), transwarp::detail::thread_pool*&&, unsigned long&&) + 143 (type_traits:3688)
48  tracing-tests                 	0x000000010bee8897 void std::__1::__thread_execute<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, void (transwarp::detail::thread_pool::*)(unsigned long), transwarp::detail::thread_pool*, unsigned long, 2ul, 3ul>(std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, void (transwarp::detail::thread_pool::*)(unsigned long), transwarp::detail::thread_pool*, unsigned long>&, std::__1::__tuple_indices<2ul, 3ul>) + 87 (thread:280)
49  tracing-tests                 	0x000000010bee7fb6 void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, void (transwarp::detail::thread_pool::*)(unsigned long), transwarp::detail::thread_pool*, unsigned long> >(void*) + 118 (thread:291)
50  libsystem_pthread.dylib       	0x00007fff205cd954 _pthread_start + 224
51  libsystem_pthread.dylib       	0x00007fff205c94a7 thread_start + 15

I have to move the executor as a local variable instead of a instance member variable like below:

class Transformer {
public:
  vector<int> transform(vector<int> &data) {
    vector<int> result(data.size());
    tw::parallel exec{1}; // use it as a local variable
    auto t =
        tw::transform(exec, data.begin(), data.end(), result.begin(), [&](int x) { return x * 2; });

    return result;
  }

private:
//    tw::parallel exec{1}; // have to commit it out
};

I searched all the tests in the repo but cannot find an example like this, is the executor expected to be used as an instance variable like above? I think if I make it as a local variable, the thread pool will be launched every time I call the transform, what would be the correct approach for re-using the thread pool for multiple times of transformation? Thanks.

I think this is happening because t may not be finished running before transform returns. One of the assumptions of transwarp is that the tasks in a transwarp graph outlive their computations. So, in order to fix the bug here you need to wait for tasks to finish computing:

class Transformer {
public:
  vector<int> transform(vector<int> &data) {
    vector<int> result(data.size());
    auto t = tw::transform(_exec, data.begin(), data.end(), result.begin(),
                           [&](int x) { return x * 2; });
    t->wait(); // <- this is new
    return result;
  }

private:
  tw::parallel _exec{1};
};

I think this makes a lot of sense here because otherwise result may not be fully populated but you're already returning. Note that tw::transform is non-blocking.

commented

@bloomen thanks for your quick reply. You are right and I realized I made some mistake when posting this issue. I tried to narrow down the problem from a large code base, and wrote this small test case for verification and somehow posted an intermediate revision without this t->wait() line when when posting this issue (sorry for the confusion).

And thanks to your prompt, I figured out the cause of my code. I understood that tw::transform is non blocking, and in my large code base, I tried to use task->get()API to wait for the computation to finish and throw an exception if there is any error. However, I made a stupid mistake and typed it as task.get() instead of task->get(). Since the task returned by tw::transform is a shared_ptr, the task.get() actually calls the shared_ptr.get() to return a pointer instead of transwarp's task get API, which essentially led to the same result as without this line (causing the crash). And compiler is happy to accept the code because shared_ptr has a get function as well :(

Thanks so much for the help!