2 // Copyright Oliver Kowalke 2015.
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
10 #include <condition_variable>
21 #include <boost/fiber/all.hpp>
23 #include "barrier.hpp"
24 #include "bind/bind_processor.hpp"
26 using allocator_type
= boost::fibers::fixedsize_stack
;
27 using channel_type
= boost::fibers::unbounded_channel
< std::uint64_t >;
28 using clock_type
= std::chrono::steady_clock
;
29 using duration_type
= clock_type::duration
;
30 using lock_type
= std::unique_lock
< std::mutex
>;
31 using time_point_type
= clock_type::time_point
;
33 static bool done
= false;
34 static std::mutex mtx
{};
35 static boost::fibers::condition_variable_any cnd
{};
38 void skynet( allocator_type
& salloc
, channel_type
& c
, std::size_t num
, std::size_t size
, std::size_t div
) {
43 for ( std::size_t i
= 0; i
< div
; ++i
) {
44 auto sub_num
= num
+ i
* size
/ div
;
45 boost::fibers::fiber
{ boost::fibers::launch::dispatch
,
46 std::allocator_arg
, salloc
,
48 std::ref( salloc
), std::ref( rc
), sub_num
, size
/ div
, div
}.detach();
50 std::uint64_t sum
{ 0 };
51 for ( std::size_t i
= 0; i
< div
; ++i
) {
52 sum
+= rc
.value_pop();
58 void thread( unsigned int i
, barrier
* b
) {
59 bind_to_processor( i
);
60 boost::fibers::use_scheduling_algorithm
< boost::fibers::algo::shared_work
>();
63 cnd
.wait( lk
, [](){ return done
; });
69 boost::fibers::use_scheduling_algorithm
< boost::fibers::algo::shared_work
>();
70 unsigned int n
= std::thread::hardware_concurrency();
72 bind_to_processor( n
- 1);
73 std::size_t stack_size
{ 4048 };
74 std::size_t size
{ 100000 };
75 std::size_t div
{ 10 };
76 std::vector
< std::thread
> threads
;
77 for ( unsigned int i
= 1; i
< n
; ++i
) {
78 threads
.push_back( std::thread( thread
, i
- 1, & b
) );
80 allocator_type salloc
{ stack_size
};
81 std::uint64_t result
{ 0 };
82 duration_type duration
{ duration_type::zero() };
85 time_point_type start
{ clock_type::now() };
86 skynet( salloc
, rc
, 0, size
, div
);
87 result
= rc
.value_pop();
88 duration
= clock_type::now() - start
;
89 std::cout
<< "Result: " << result
<< " in " << duration
.count() / 1000000 << " ms" << std::endl
;
94 for ( std::thread
& t
: threads
) {
97 std::cout
<< "done." << std::endl
;
99 } catch ( std::exception
const& e
) {
100 std::cerr
<< "exception: " << e
.what() << std::endl
;
102 std::cerr
<< "unhandled exception" << std::endl
;