fiber (Fiber) and coroutine are similar concepts, also called user-level threads or light threading. Windows system provides a set of API users to create and use fiber, the library in this article is based on this set of API implementation, so can not be used across the platform, non-Windows programmers may flash, of course, if interested can continue to look, find a third-party libraries package, also can achieve the same effect. More detailed information on fiber can be found on MSDN.
There are two key points in the concept of fiber:
- Fiber has a separate stack space and register environment ;
- Fiber in the user-state implementation of scheduling, that is, completely controlled by the programmer;
The following figure shows the process of switching between several fibers, noting that each fiber has a separate stack and switches to other fibers via the SwitchToFiber function:
As a comparison, we can look at the stack changes in the process of the function call, and the following is a common function nesting call relationship func1, FUNC2, func3:
Each function call creates a new stack frame, which, together, forms the entire call stack, and the stack frame is released when the function returns. For a function call, one thing we can determine is that (without throwing an exception) The called function will definitely return at the call point and continue executing the next statement. But the call between fibers (switching) is different, a fiber can switch to other fibers in any position, and may never again switch back, or from any other fiber (not necessarily just switch to) back, the previous description is a very simple situation, the actual situation can be very complex, Complex to export are jumping to jump the arrow is also not clear. Switching between fibers, a bit like using the enhanced version of the Goto, when used is very cool, but the subsequent maintenance is a hassle.
So, as with while/for/switch-case instead of Goto, we also need to encapsulate a new set of APIs in place of a direct call to the operating system API. On the one hand, in the encapsulation process, we can impose some security constraints on the behavior of the fiber (actually the behavior of the programmer), making it easier to write safe code or more difficult to write unsafe code, on the other hand, the process control statements from Goto to While/switch are actually an abstraction level of ascension , the latter is more convenient for most common needs, the code written is also more concise and understandable, similar from the system API to the new encapsulation API or encapsulation class is also an abstraction level of improvement, can be more convenient to apply in various business scenarios. Finally, the direct use of the system API requires a lot of maintenance of fiber auxiliary code, which is often repeated and dispersed to the various corners of the business code, further reducing the readability of the program and improve the maintenance difficulty, encapsulation is to solve the problem.
Well, the crap is over, let's start with a piece of code to try fresh:
1 Const intRun_times =5;2 3 intNumber =0;4 BOOLshutdown =false;5 6Fiber fib ([&number, &shutdown]7 {8 while(!shutdown)9 {Tennumber++; OneFiber::yield();//A: Control transfer to main fiber A } - }); - the for(inti =0; i < run_times; i++) - { -Fib.resume ();//B: Switch to sub-fiber execution - } + -printf"Number =%d\r\n", number);
This first creates a fiber that implements the sum of number variables, and then executes it in the For loop (this word is used) to get the correct result. The AB two code implements a fiber switch, which actually encapsulates the call to the SwitchToFiber, noting the difference in the details of the two function calls: Resume is the normal member function that represents the switch to the object wrapper in the fiber execution, and yield is Static member functions represent the transfer of control to the caller's fiber, and you can think about why there is such a difference.
Here is the code for implementing a producer-consumer model with fiber:
1 intProduct_count =0;2 BOOLIs_end_time =false;3 4 Const intRun_times =3;5 6 //Producer Fiber Range7Fiber Fib_producer ([&is_end_time, &Product_count]8 {9 Srand ((unsigned) time (NULL));Ten One while(!is_end_time) A { - intNew_product_count = (int)((Double) rand ()/Rand_max *Ten) +1; -Product_count + =New_product_count; the -printf"[Producer] Create new products:%d\r\n", new_product_count); - -Fiber::yield(); + } - +printf"[producer] off duty.\r\n"); A }); at - //executive function of consumer fiber -Auto Consumer_proc = [&is_end_time, &product_count] (Const intseq_number) - { - intTotal_count =0; - in while(!is_end_time) - { to if(Product_count >0) + { -product_count--; thetotal_count++; *printf"[Consumer%d] got 1 product, total got%d, remain%d\r\n", Seq_number, Total_count, product_count); $ }Panax Notoginseng -Fiber::yield(); the } + Aprintf"[consumer%d] off duty.\r\n", seq_number); the }; + - Const intConsumer_count =3; $ intConsumer_seq_number =0; $ - //Create a consumer fiber array -Std::vector<fiber>Consumer_array (consumer_count); theStd::for_each (Consumer_array.begin (), Consumer_array.end (), [&] (fiber& item) {item = Fiber ([&]{consumer_ Proc (consumer_seq_number); }); consumer_seq_number++; }); - WuyiConsumer_seq_number =0; the - for(inti =0; i < run_times; i++) Wu { - Fib_producer.resume (); About $ while(Product_count >0) - { - Consumer_array[consumer_seq_number].resume (); -Consumer_seq_number = (Consumer_seq_number +1) %Consumer_count; A } + } the -Is_end_time =true; $ the //wait for fiber to end the Fiber::await_all (consumer_array); theFiber::await (Fib_producer);
At the end of the program, await and await_all two new methods can be used without a tube, without affecting the primary logic. Since all fibers run in the same thread, no locking is required, which is an important benefit of using fiber.
Confined to space, this time only to write so much, more content will be put in the post in the back, the total also write 四、五篇 look. But the code has actually been finished, the impatient classmate can directly to this address to see the code:
Https://code.csdn.net/xrunning/fiber
Asynchronous Programming for C + + based on fiber (Fiber): Principles and examples