diff --git a/folly/fibers/README.md b/folly/fibers/README.md index f5869f04607..7675f5c10bd 100644 --- a/folly/fibers/README.md +++ b/folly/fibers/README.md @@ -15,13 +15,13 @@ fiberManager.addTask([&]() { std::cout << "Task 1: start" << std::endl; baton.wait(); - std::cout << "Task 1: after baton.wait()" << std::endl; + std::cout << "Task 1: after baton.wait()" << std::endl; }); fiberManager.addTask([&]() { std::cout << "Task 2: start" << std::endl; baton.post(); - std::cout << "Task 2: after baton.post()" << std::endl; + std::cout << "Task 2: after baton.post()" << std::endl; }); evb.loop(); @@ -76,7 +76,7 @@ fiberManager.addTask([&]() { std::cout << "Task: start" << std::endl; baton.wait(); - std::cout << "Task: after baton.wait()" << std::endl; + std::cout << "Task: after baton.wait()" << std::endl; }); evb.loop(); @@ -116,7 +116,7 @@ ... Response response; fibers::Baton baton; - + asyncCall(request, [&](Response r) mutable { response = std::move(r); baton.post(); @@ -190,7 +190,7 @@
fiberManager.addTask([]() {
   ...
   auto response = asyncCallFuture(request).get();
-  
+
   // Now response holds response returned by the async call
   ...
 }
@@ -229,7 +229,7 @@
...
 Context context;
- 
+
 asyncCall(request, [request, context](Response response) mutable {
   doSomething(request, response, context);
 });
@@ -242,7 +242,7 @@
   Context context;
 
   auto response = fiberCall(request);
- 
+
   doSomething(request, response, context);
   ...
 });
@@ -255,7 +255,7 @@

Similarly to system threads, every fiber-task has some stack space assigned to it. Stack usage goes up with the number of nested function calls and objects allocated on the stack. folly::fibers implementation only supports fiber-tasks with fixed stack size. If you want to have many fiber-tasks running concurrently - you need to reduce the amount of stack assigned to each fiber-task, otherwise you may run out of memory.

-
IMPORTANT: If a fiber-task runs out of stack space (e.g. calls a function which does a lot of stack allocations) you program will fail.
+
IMPORTANT: If a fiber-task runs out of stack space (e.g. calls a function which does a lot of stack allocations) your program will fail.

However if you know that some function never suspends a fiber-task, you can use fibers::runInMainContext to safely call it from a fiber-task, without any risk of running out of stack space of the fiber-task.

@@ -308,7 +308,7 @@

First fiber-task will grab a lock and then suspend waiting on a fibers::Baton. Then second fiber-task will be run and it will try to grab a lock. Unlike system threads, fiber-task can be only suspended explicitly, so the whole system thread will be blocked waiting on the lock, and we end up with a dead-lock.

-

There're generally two ways we can solve this problem. Ideally we would re-design the program to never not hold any locks when fiber-task is suspended. However if we are absolutely sure we need that lock - folly::fibers library provides some fiber-task-aware lock implementations (e.g. +

There're generally two ways we can solve this problem. Ideally we would re-design the program to never not hold any locks when fiber-task is suspended. However if we are absolutely sure we need that lock - folly::fibers library provides some fiber-task-aware lock implementations (e.g. TimedMutex).

APIs

fibers::Baton #

All of the features of folly::fibers library are actually built on top a single synchronization primitive called Baton. fibers::Baton is a fiber-specific version of folly::Baton. It only supports two basic operations: wait() and post(). Whenever wait() is called on the Baton, the current thread or fiber-task is suspended, until post() is called on the same Baton. wait() does not suspend the thread or fiber-task if post() was already called on the Baton. Please refer to Baton for more detailed documentation.

@@ -410,7 +410,7 @@ }); auto future2 = fiberManager.addTaskRemoteFuture([]() { ... - }); + }); auto result1 = future1.get(); auto result2 = future2.get();