# How to Use fiber_delay for Non-Blocking Timeouts in libfiber

> Master non-blocking timeouts with fiber_delay in libfiber. Suspend fibers effectively without blocking OS threads, enabling efficient cooperative multitasking.

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

---

**The `fiber_delay` function (C API: `acl_fiber_delay`, C++: `fiber::delay`) suspends the calling fiber for a specified duration without blocking the underlying OS thread, enabling cooperative multitasking through the fiber scheduler.**

The `iqiyi/libfiber` library provides a high-performance coroutine implementation where fibers yield control instead of blocking threads. Using `fiber_delay` allows developers to implement non-blocking timeouts that pause individual fibers while the scheduler continues processing other ready fibers on the same OS thread.

## Understanding fiber_delay and Non-Blocking Timeouts

When a fiber invokes `fiber_delay`, it triggers a four-step non-blocking sequence. First, the fiber registers with the internal timer manager via `fiber_timer_add`, storing the timer in a per-thread timer list. Second, the fiber marks itself with the `FIBER_WAIT_DELAY` state and yields the CPU through `acl_fiber_switch`, allowing the scheduler to run other ready fibers. Third, when the timer expires, the event loop (`event_get_stamp` / `wakeup_timers`) marks the waiting fiber as ready and clears the delay flag. Finally, the scheduler resumes the fiber and the function returns the remaining milliseconds (normally zero), enabling detection of early wake-up if the fiber was killed.

This architecture ensures that **no system `sleep()` or `usleep()` blocks the entire thread**; only the calling fiber pauses. The public declaration resides in [`c/include/fiber/fiber_base.h`](https://github.com/iqiyi/libfiber/blob/main/c/include/fiber/fiber_base.h) lines 84-88, while the core implementation appears in [`c/src/fiber_io.c`](https://github.com/iqiyi/libfiber/blob/main/c/src/fiber_io.c) lines 29-73.

## C API Implementation (acl_fiber_delay)

### Function Signature and Behavior

The `acl_fiber_delay` function accepts a single `int` parameter specifying milliseconds to suspend. It returns the remaining time as an `unsigned int`, which is normally zero but may be non-zero if the fiber wakes early due to termination signals.

### Basic Non-Blocking Sleep Example

```c
#include <fiber/fiber.h>

void worker(void *arg)
{
    (void) arg;
    /* Suspend this fiber for 1 second without blocking other fibers */
    acl_fiber_delay(1000);   /* 1000 ms */
    printf("Fiber resumed after 1 s\n");
}

int main(void)
{
    acl_fiber_schedule();           /* start the scheduler */
    acl_fiber_create(worker, NULL, 320000, 0);
    acl_fiber_schedule_stop();      /* stop when done */
    return 0;
}

```

This example creates a worker fiber that yields for one second while the scheduler processes other fibers. The implementation references [`c/src/fiber_io.c`](https://github.com/iqiyi/libfiber/blob/main/c/src/fiber_io.c) for the delay logic and [`c/include/fiber/fiber_base.h`](https://github.com/iqiyi/libfiber/blob/main/c/include/fiber/fiber_base.h) for the API contract.

## C++ Wrapper Interface (fiber::delay)

### Static Method Declaration

The C++ wrapper exposes non-blocking delays through the `fiber::delay` static method declared in [`cpp/include/fiber/fiber.hpp`](https://github.com/iqiyi/libfiber/blob/main/cpp/include/fiber/fiber.hpp) lines 31-38. This wrapper forwards calls to `acl_fiber_delay` via the implementation in [`cpp/src/fiber.cpp`](https://github.com/iqiyi/libfiber/blob/main/cpp/src/fiber.cpp) lines 16-18, maintaining identical non-blocking semantics.

### Object-Oriented Timeout Example

```cpp
#include <fiber/fiber.hpp>
#include <iostream>

class my_fiber : public fiber
{
public:
    void run() override
    {
        std::cout << "Sleeping for 500 ms (non-blocking)" << std::endl;
        fiber::delay(500);
        std::cout << "Awake again!" << std::endl;
    }
};

int main()
{
    fiber::schedule();      /* Start the scheduler */
    my_fiber f;
    f.start();
    fiber::schedule_stop(); /* Stop when all fibers finished */
    return 0;
}

```

The `fiber::delay(500)` call invokes the same underlying timer mechanism as the C API, ensuring the fiber yields control without blocking the native thread.

## Advanced Timer-Based Callbacks

For scenarios requiring callback-based timeouts rather than simple resumption, use `acl_fiber_create_timer`. This function creates a dedicated timer fiber that sleeps using identical `fiber_delay` mechanics but delivers the wake-up to a specified callback instead of the original fiber context.

Declared in [`c/include/fiber/fiber_base.h`](https://github.com/iqiyi/libfiber/blob/main/c/include/fiber/fiber_base.h) lines 98-106 and implemented in [`c/src/fiber_io.c`](https://github.com/iqiyi/libfiber/blob/main/c/src/fiber_io.c) lines 106-124, this API enables one-shot timer fibers:

```c
static void timer_cb(ACL_FIBER *fb, void *arg)
{
    (void)fb; (void)arg;
    printf("Timer fired after 2 seconds\n");
}

void start_timer(void)
{
    /* 2000 ms, default stack size 320000, timer_cb as entry */
    acl_fiber_create_timer(2000, 320000, timer_cb, NULL);
}

```

## Summary

- `acl_fiber_delay` suspends fibers without blocking OS threads by registering with the per-thread timer manager in [`c/src/fiber_io.c`](https://github.com/iqiyi/libfiber/blob/main/c/src/fiber_io.c)
- The fiber state transitions to `FIBER_WAIT_DELAY` before yielding via `acl_fiber_switch`, allowing the scheduler to execute other fibers
- The function returns remaining milliseconds to detect early wake-up conditions from fiber termination
- C++ wrapper provides `fiber::delay` static method forwarding to the C implementation in [`cpp/src/fiber.cpp`](https://github.com/iqiyi/libfiber/blob/main/cpp/src/fiber.cpp)
- Timer fibers utilize identical mechanics through `acl_fiber_create_timer` for callback-based timeout handling

## Frequently Asked Questions

### What is the difference between fiber_delay and standard sleep functions?

Standard `sleep()` or `usleep()` blocks the entire OS thread, preventing other fibers from executing during the wait period. In contrast, `fiber_delay` only pauses the calling fiber, allowing the scheduler to continue processing other ready fibers on the same thread through cooperative multitasking.

### Can a fiber_delay be interrupted or cancelled early?

Yes, if the fiber receives a termination signal or is killed during the delay period, `fiber_delay` returns early with a non-zero value indicating the remaining milliseconds. This return value allows cleanup code to detect premature wake-up and adjust logic accordingly.

### Is fiber_delay safe to use across multiple OS threads?

Each OS thread maintains its own fiber scheduler and independent timer list within libfiber's architecture. `fiber_delay` operates strictly within the current thread's scheduler context, making it safe when fibers remain on their creating threads according to the library's thread-affinity design.

### What precision does fiber_delay provide?

The implementation uses millisecond granularity specified in the `ms` parameter, though actual wake-up timing depends on the event loop's timer resolution (`event_get_stamp` and `wakeup_timers`) and current scheduler load. The timer expires when the event loop processes the pending timeout, which typically aligns with the requested millisecond count.