Skip to content

Commit 45f3a26

Browse files
committed
Add comprehensive documentation for Folly integration example
This adds a detailed README.md for the examples/folly directory that covers: - Overview of Rust-Folly async interoperability - Key components and architecture - Feature demonstrations (parallel computation, exception handling, async streams) - Build and run instructions - Test coverage details - Performance considerations Closes #14
1 parent 098fbfc commit 45f3a26

File tree

1 file changed

+192
-0
lines changed

1 file changed

+192
-0
lines changed

examples/folly/README.md

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
# Folly Integration Example
2+
3+
This example demonstrates how to use `cxx-async` to seamlessly integrate Rust async code with Facebook's [Folly](https://github.com/facebook/folly) C++ async framework.
4+
5+
## Overview
6+
7+
The example showcases bidirectional async interoperability between Rust and C++ using Folly coroutines and futures. It demonstrates various async patterns including:
8+
9+
- Rust calling C++ async functions (using both Folly coroutines and futures)
10+
- C++ calling Rust async functions
11+
- Exception/error handling across language boundaries
12+
- Async streams (generators) support
13+
- Complex async patterns like ping-pong communication
14+
15+
## Key Components
16+
17+
### Rust Side (`src/main.rs`)
18+
19+
- **Bridge Definitions**: Uses `#[cxx::bridge]` and `#[cxx_async::bridge]` to define FFI bindings for async types
20+
- **Async Functions**: Implements Rust async functions that can be called from C++
21+
- **Test Suite**: Comprehensive tests covering various interop scenarios
22+
23+
### C++ Side
24+
25+
- **`include/folly_example.h`**: Header file defining the C++ async interface using `CXXASYNC_DEFINE_FUTURE` and `CXXASYNC_DEFINE_STREAM` macros
26+
- **`src/folly_example.cpp`**: Implementation using Folly coroutines (`folly::coro::Task`) and futures
27+
28+
## Features Demonstrated
29+
30+
### 1. Parallel Computation
31+
32+
The example implements a parallel dot product calculation that:
33+
- Recursively splits the work when the array size exceeds a threshold
34+
- Spawns tasks on thread pools (both Rust and C++ sides)
35+
- Aggregates results asynchronously
36+
37+
```cpp
38+
// C++ side using Folly coroutines
39+
static folly::coro::Task<double> do_dot_product_coro(const double a[], const double b[], size_t count) {
40+
if (count > EXAMPLE_SPLIT_LIMIT) {
41+
// Split and compute in parallel
42+
auto [first, second] = co_await folly::collectAll(taskA, taskB);
43+
co_return *first + *second;
44+
}
45+
// Base case: compute directly
46+
}
47+
```
48+
49+
```rust
50+
// Rust side using async/await
51+
#[async_recursion]
52+
async fn dot_product(range: Range<usize>) -> f64 {
53+
if len > SPLIT_LIMIT {
54+
// Split and compute in parallel
55+
let (first, second) = join!(/* ... */);
56+
return first + second;
57+
}
58+
// Base case: compute directly
59+
}
60+
```
61+
62+
### 2. Exception Handling
63+
64+
Custom exception handling across the FFI boundary:
65+
66+
```cpp
67+
// C++ custom exception
68+
class MyException : public std::exception {
69+
const char* message() const noexcept;
70+
};
71+
72+
// Template specialization for exception handling
73+
template <typename T>
74+
struct TryCatch<T, Custom> {
75+
static void trycatch(Try&& func, Fail&& fail) noexcept {
76+
try {
77+
func();
78+
} catch (const MyException& exception) {
79+
fail(exception.message());
80+
}
81+
}
82+
};
83+
```
84+
85+
### 3. Async Streams
86+
87+
The example includes FizzBuzz implementations using async streams:
88+
89+
```cpp
90+
// C++ generator coroutine
91+
RustStreamString folly_fizzbuzz() {
92+
for (int i = 1; i <= 15; i++) {
93+
if (i % 15 == 0) {
94+
co_yield rust::String("FizzBuzz");
95+
} else if (i % 5 == 0) {
96+
co_yield rust::String("Buzz");
97+
} // ...
98+
}
99+
}
100+
```
101+
102+
### 4. Ping-Pong Pattern
103+
104+
Demonstrates multiple async calls across language boundaries:
105+
106+
```rust
107+
// Rust side
108+
fn rust_folly_ping_pong(i: i32) -> RustFutureString {
109+
RustFutureString::infallible(async move {
110+
format!("{}ping ",
111+
if i < 4 {
112+
ffi::folly_ping_pong(i + 1).await.unwrap()
113+
} else {
114+
"".to_owned()
115+
})
116+
})
117+
}
118+
```
119+
120+
## Building and Running
121+
122+
### Prerequisites
123+
124+
- Folly library installed (the build uses `find-folly` crate)
125+
- C++20 compiler support
126+
- Rust toolchain
127+
128+
### Build
129+
130+
```bash
131+
cargo build --example folly
132+
```
133+
134+
### Run Tests
135+
136+
```bash
137+
cargo test --example folly
138+
```
139+
140+
### Run Example
141+
142+
```bash
143+
cargo run --example folly
144+
```
145+
146+
## Test Coverage
147+
148+
The example includes extensive tests for:
149+
150+
- Synchronous calling patterns (Rust → C++, C++ → Rust)
151+
- Asynchronous execution on thread pools
152+
- Exception and error propagation
153+
- Void return types
154+
- Future dropping and cleanup
155+
- Stream operations with exceptions
156+
- Coroutine lifecycle management
157+
158+
## Architecture Notes
159+
160+
### Thread Pools
161+
162+
- **C++ Side**: Uses `folly::CPUThreadPoolExecutor` with 8 threads
163+
- **Rust Side**: Uses `futures::executor::ThreadPool`
164+
165+
### Memory Management
166+
167+
The example demonstrates proper memory management:
168+
- Coroutines run to completion ensuring destructors are called
169+
- Futures can be safely dropped
170+
- Background tasks are properly managed through Folly's reaper
171+
172+
### Type Mapping
173+
174+
| Rust Type | C++ Type | Purpose |
175+
|-----------|----------|---------|
176+
| `RustFutureVoid` | `folly::coro::Task<void>` | Async operations without return value |
177+
| `RustFutureF64` | `folly::coro::Task<double>` | Async operations returning floating point |
178+
| `RustFutureString` | `folly::coro::Task<rust::String>` | Async operations returning strings |
179+
| `RustStreamString` | Generator coroutine | Async stream of strings |
180+
181+
## Performance Considerations
182+
183+
The example is designed to showcase real parallelism:
184+
- Work is distributed across multiple threads
185+
- Large arrays (16384 elements) ensure meaningful computation
186+
- Split threshold (32 elements) balances parallelism overhead
187+
188+
## Further Reading
189+
190+
- [Folly Documentation](https://github.com/facebook/folly/tree/main/folly/docs)
191+
- [cxx-async Documentation](https://github.com/pcwalton/cxx-async)
192+
- [CXX Documentation](https://cxx.rs/)

0 commit comments

Comments
 (0)