]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/fiber/examples/work_sharing.cpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / fiber / examples / work_sharing.cpp
CommitLineData
7c673cae
FG
1// Copyright Nat Goodspeed + Oliver Kowalke 2015.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at
4// http://www.boost.org/LICENSE_1_0.txt)
5
6#include <chrono>
7#include <condition_variable>
8#include <cstddef>
9#include <deque>
10#include <iomanip>
11#include <iostream>
12#include <mutex>
13#include <sstream>
14#include <string>
15#include <thread>
16
17#include <boost/assert.hpp>
18
19#include <boost/fiber/all.hpp>
20
b32b8144 21#include "thread_barrier.hpp"
7c673cae
FG
22
23static std::size_t fiber_count{ 0 };
24static std::mutex mtx_count{};
25static boost::fibers::condition_variable_any cnd_count{};
b32b8144 26typedef std::unique_lock< std::mutex > lock_type;
7c673cae
FG
27
28/*****************************************************************************
29* example fiber function
30*****************************************************************************/
31//[fiber_fn_ws
32void whatevah( char me) {
33 try {
34 std::thread::id my_thread = std::this_thread::get_id(); /*< get ID of initial thread >*/
35 {
36 std::ostringstream buffer;
37 buffer << "fiber " << me << " started on thread " << my_thread << '\n';
38 std::cout << buffer.str() << std::flush;
39 }
40 for ( unsigned i = 0; i < 10; ++i) { /*< loop ten times >*/
41 boost::this_fiber::yield(); /*< yield to other fibers >*/
42 std::thread::id new_thread = std::this_thread::get_id(); /*< get ID of current thread >*/
43 if ( new_thread != my_thread) { /*< test if fiber was migrated to another thread >*/
44 my_thread = new_thread;
45 std::ostringstream buffer;
46 buffer << "fiber " << me << " switched to thread " << my_thread << '\n';
47 std::cout << buffer.str() << std::flush;
48 }
49 }
50 } catch ( ... ) {
51 }
b32b8144 52 lock_type lk( mtx_count);
7c673cae
FG
53 if ( 0 == --fiber_count) { /*< Decrement fiber counter for each completed fiber. >*/
54 lk.unlock();
55 cnd_count.notify_all(); /*< Notify all fibers waiting on `cnd_count`. >*/
56 }
57}
58//]
59
60/*****************************************************************************
61* example thread function
62*****************************************************************************/
63//[thread_fn_ws
b32b8144 64void thread( thread_barrier * b) {
7c673cae
FG
65 std::ostringstream buffer;
66 buffer << "thread started " << std::this_thread::get_id() << std::endl;
67 std::cout << buffer.str() << std::flush;
68 boost::fibers::use_scheduling_algorithm< boost::fibers::algo::shared_work >(); /*<
69 Install the scheduling algorithm `boost::fibers::algo::shared_work` in order to
70 join the work sharing.
71 >*/
72 b->wait(); /*< sync with other threads: allow them to start processing >*/
b32b8144 73 lock_type lk( mtx_count);
7c673cae
FG
74 cnd_count.wait( lk, [](){ return 0 == fiber_count; } ); /*<
75 Suspend main fiber and resume worker fibers in the meanwhile.
76 Main fiber gets resumed (e.g returns from `condition_variable_any::wait()`)
77 if all worker fibers are complete.
78 >*/
79 BOOST_ASSERT( 0 == fiber_count);
80}
81//]
82
83/*****************************************************************************
84* main()
85*****************************************************************************/
86int main( int argc, char *argv[]) {
87 std::cout << "main thread started " << std::this_thread::get_id() << std::endl;
88//[main_ws
89 boost::fibers::use_scheduling_algorithm< boost::fibers::algo::shared_work >(); /*<
90 Install the scheduling algorithm `boost::fibers::algo::shared_work` in the main thread
91 too, so each new fiber gets launched into the shared pool.
92 >*/
93
94 for ( char c : std::string("abcdefghijklmnopqrstuvwxyz")) { /*<
95 Launch a number of worker fibers; each worker fiber picks up a character
96 that is passed as parameter to fiber-function `whatevah`.
97 Each worker fiber gets detached.
98 >*/
99 boost::fibers::fiber([c](){ whatevah( c); }).detach();
100 ++fiber_count; /*< Increment fiber counter for each new fiber. >*/
101 }
b32b8144 102 thread_barrier b( 4);
7c673cae
FG
103 std::thread threads[] = { /*<
104 Launch a couple of threads that join the work sharing.
105 >*/
106 std::thread( thread, & b),
107 std::thread( thread, & b),
108 std::thread( thread, & b)
109 };
110 b.wait(); /*< sync with other threads: allow them to start processing >*/
111 {
b32b8144 112 lock_type/*< `lock_type` is typedef'ed as __unique_lock__< [@http://en.cppreference.com/w/cpp/thread/mutex `std::mutex`] > >*/ lk( mtx_count);
7c673cae
FG
113 cnd_count.wait( lk, [](){ return 0 == fiber_count; } ); /*<
114 Suspend main fiber and resume worker fibers in the meanwhile.
115 Main fiber gets resumed (e.g returns from `condition_variable_any::wait()`)
116 if all worker fibers are complete.
117 >*/
118 } /*<
119 Releasing lock of mtx_count is required before joining the threads, otherwise
120 the other threads would be blocked inside condition_variable::wait() and
121 would never return (deadlock).
122 >*/
123 BOOST_ASSERT( 0 == fiber_count);
124 for ( std::thread & t : threads) { /*< wait for threads to terminate >*/
125 t.join();
126 }
127//]
128 std::cout << "done." << std::endl;
129 return EXIT_SUCCESS;
130}