# How to Use the C++ go_fiber API with Lambda Expressions in libfiber

> Learn to use the C++ go_fiber API with lambda expressions in libfiber. Launch fibers using intuitive lambda syntax via operator overloading on temporary go_fiber objects. Get started now.

- Repository: [iQIYI/libfiber](https://github.com/iqiyi/libfiber)
- Tags: how-to-guide
- Published: 2026-03-04

---

**The go_fiber API enables launching C++ fibers using intuitive lambda syntax via operator overloading on temporary go_fiber objects created by macros like `go`, `go_wait_fiber`, and `go_wait_thread`.**

The **iqiyi/libfiber** library provides a high-performance coroutine implementation for C++, and its `go_fiber` wrapper allows you to use modern C++ lambda expressions to spawn and manage fibers. This API abstracts the underlying C-style fiber implementation into a type-safe, ergonomic interface that feels like a native language feature. Understanding how to use the C++ go_fiber API with lambda expressions unlocks efficient concurrent programming without callback complexity.

## Architecture of the go_fiber Wrapper

### Core Components

The implementation centers on five key components defined in [`cpp/include/fiber/go_fiber.hpp`](https://github.com/iqiyi/libfiber/blob/main/cpp/include/fiber/go_fiber.hpp) and related headers:

- **go_fiber class**: Defined at lines **43‑78**, this class holds optional stack configuration and implements three critical operators that accept lambdas.
- **fiber_ctx**: A context struct at lines **24‑33** that stores the user lambda as `std::function<void()>` until the fiber begins execution.
- **fiber class**: The underlying coroutine engine in [`cpp/include/fiber/fiber.hpp`](https://github.com/iqiyi/libfiber/blob/main/cpp/include/fiber/fiber.hpp) (lines **32‑60**) that handles creation via `fiber::fiber_create`.
- **fiber_tbox**: A synchronization primitive from [`cpp/include/fiber/fiber_tbox.hpp`](https://github.com/iqiyi/libfiber/blob/main/cpp/include/fiber/fiber_tbox.hpp) (lines **40‑66**) that enables blocking semantics for the wait operators.
- **Convenience Macros**: The `go`, `go_wait_fiber`, and `go_wait_thread` macros at lines **35‑42** instantiate temporary `go_fiber` objects and apply the appropriate operator.

### The Three Operator Overloads

The `go_fiber` class overloads three operators to control execution semantics:

- **operator>**: Creates a new fiber and immediately returns a `std::shared_ptr<fiber>`. The implementation at lines **48‑52** allocates a `fiber_ctx`, invokes `fiber::fiber_create` with `fiber_main` as the entry point, and wraps the result.
- **operator<**: Runs a lambda inside a new fiber and blocks the current fiber until completion. This uses a `fiber_tbox<int>` as a one-element barrier (lines **54‑62**).
- **operator<<**: Executes the lambda in a detached OS thread while blocking the current fiber until the thread finishes, also utilizing `fiber_tbox<int>` for synchronization (lines **64‑73**).

## Launching Fibers with Lambda Expressions

### Fire-and-Forget with operator>

Use the `go` macro to spawn independent fibers that run concurrently without blocking the caller.

```cpp
#include "fiber/go_fiber.hpp"
#include "fiber/fiber.hpp"

void hello() {
    printf("Hello from fiber %u\n", acl::fiber::self());
}

int main() {
    // Launch a fiber that runs hello(). No waiting occurs.
    go[&] { hello(); };

    // Start the scheduler
    acl::fiber::schedule();
    return 0;
}

```

This pattern from [`samples/cxx/fiber/main.cpp`](https://github.com/iqiyi/libfiber/blob/main/samples/cxx/fiber/main.cpp) demonstrates the basic launch mechanism. The `go` macro expands to a temporary `go_fiber` instance followed by `operator>`, which stores your lambda in a `fiber_ctx` and creates the underlying fiber via `fiber::fiber_create`.

### Blocking Fiber-to-Fiber Waits with operator<

When you need to spawn a fiber and suspend the current one until the child completes, use `go_wait_fiber`.

```cpp
#include "fiber/go_fiber.hpp"
#include "fiber/fiber.hpp"

void task(int id) {
    printf("Fiber %d (id=%u) running\n", id, acl::fiber::self());
}

void master_fiber() {
    // Blocks until the lambda finishes
    go_wait_fiber[&] { task(42); };
    printf("Fiber %u resumed after task\n", acl::fiber::self());
}

int main() {
    go[&] { master_fiber(); };
    acl::fiber::init(acl::FIBER_EVENT_T_KERNEL, true);
    return 0;
}

```

The `go_wait_fiber` macro utilizes `operator<` (lines **54‑62** in [`go_fiber.hpp`](https://github.com/iqiyi/libfiber/blob/main/go_fiber.hpp)), which creates a `fiber_tbox<int>` barrier. The current fiber suspends on `pop()` until the child fiber pushes a completion signal.

### Blocking Fiber-to-Thread Waits with operator<<

For offloading blocking operations to OS threads without stalling the fiber scheduler, use `go_wait_thread` or its alias `go_wait`.

```cpp
#include "fiber/go_fiber.hpp"
#include "fiber/fiber.hpp"

void heavy_work() {
    std::this_thread::sleep_for(std::chrono::seconds(2));
    printf("Thread work done\n");
}

int main() {
    go[&] {
        go_wait_thread[&] { heavy_work(); };
        printf("Back in fiber after thread\n");
    };
    acl::fiber::init(acl::FIBER_EVENT_T_KERNEL, true);
    return 0;
}

```

The `operator<<` implementation (lines **64‑73**) spawns a detached `std::thread`, executes the lambda, and signals completion through a `fiber_tbox` to resume the waiting fiber.

## Customizing Stack Behavior

### Private Stack Sizes with go_stack

Control memory allocation for deep recursion or large frame sizes using `go_stack(size)`, which expands to `go_fiber(size, false)` as defined at lines **36‑37**.

```cpp
#include "fiber/go_fiber.hpp"
#include "fiber/fiber.hpp"

void deep_recursion(int depth) {
    if (depth == 0) return;
    deep_recursion(depth - 1);
}

int main() {
    // Allocate a 1 MiB private stack
    go_stack(1024 * 1024)[&] { deep_recursion(5000); };
    acl::fiber::schedule();
    return 0;
}

```

### Shared-Stack Mode with go_share

Reduce per-fiber memory footprint when spawning thousands of concurrent fibers by enabling shared-stack mode via `go_share(size)`, equivalent to `go_fiber(size, true)`.

```cpp
// Allocate a 1 MiB shared stack
go_share(1024 * 1024)[&] { deep_recursion(5000); };

```

This mode allows multiple fibers to time-share a single stack allocation, significantly reducing memory pressure in high-concurrency scenarios while maintaining the same lambda execution semantics.

## Summary

- The **go_fiber API** wraps libfiber's C-style implementation with type-safe C++ lambda support through [`cpp/include/fiber/go_fiber.hpp`](https://github.com/iqiyi/libfiber/blob/main/cpp/include/fiber/go_fiber.hpp).
- **Three operators** control execution semantics: `>` for fire-and-forget, `<` for fiber-blocking waits, and `<<` for thread-blocking waits.
- **Capture semantics** work naturally with `[&]`, `[=]`, or `[this]`, as the lambda is stored as `std::function<void()>` in `fiber_ctx`.
- **Synchronization** relies on `fiber_tbox` to implement blocking behavior without busy-waiting.
- **Stack customization** macros `go_stack` and `go_share` provide fine-grained control over memory allocation strategies.

## Frequently Asked Questions

### Can I capture local variables by reference in go_fiber lambdas?

Yes. The operators accept `std::function<void()>` parameters, so any valid C++ capture mode works as expected. The lambda executes within the scope where it was defined, maintaining references to captured variables according to standard C++ semantics.

### What is the difference between go_wait_fiber and go_wait_thread?

**go_wait_fiber** (using `operator<`) creates a new fiber within the scheduler to run your lambda and blocks the current fiber until completion. **go_wait_thread** (using `operator<<`) launches a separate OS thread to execute the lambda, allowing blocking system calls without stalling the fiber scheduler, then resumes the fiber when the thread exits.

### How do I retrieve the return value from a lambda executed via go_fiber?

The current API uses `void()` signatures, so direct return value capture is not supported. You must use capture-by-reference to modify variables in the parent scope, or implement a custom synchronization mechanism using `fiber_tbox` to pass results back to the waiting fiber.

### Where can I find production examples of go_fiber usage?

The repository provides working samples in [`samples/cxx/fiber/main.cpp`](https://github.com/iqiyi/libfiber/blob/main/samples/cxx/fiber/main.cpp), which demonstrates basic launching, waiting, and stack options. Additional examples covering thread pools and high-throughput scenarios appear in [`samples/cxx/fiber_pool/main.cpp`](https://github.com/iqiyi/libfiber/blob/main/samples/cxx/fiber_pool/main.cpp).