Skip to content

Commit 64d3936

Browse files
NieRclaude
andcommitted
Add comprehensive documentation for examples/folly
This commit adds a detailed README.md for the Folly integration example, covering: - Bidirectional async calls between Rust and C++ - Parallel computation with both coroutines and futures - Exception handling across language boundaries - Stream processing and complex communication patterns - Complete build requirements and troubleshooting guide - Comprehensive test coverage documentation The documentation provides clear setup instructions, architecture overview, and practical examples for developers wanting to understand Folly-based async interoperability. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent 098fbfc commit 64d3936

File tree

1 file changed

+265
-0
lines changed

1 file changed

+265
-0
lines changed

examples/folly/README.md

Lines changed: 265 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
# Folly Integration Example
2+
3+
This example demonstrates comprehensive async interoperability between Rust and C++ using the [Folly](https://github.com/facebook/folly) library. It showcases bidirectional async function calls, parallel computation, exception handling, stream processing, and complex communication patterns.
4+
5+
## Overview
6+
7+
The Folly example is a sophisticated demonstration of Rust-C++ async integration that covers:
8+
9+
- **Bidirectional Async Calls**: Both Rust calling C++ async functions and C++ calling Rust async functions
10+
- **Parallel Computation**: Multithreaded dot product calculation using both Folly coroutines and futures
11+
- **Exception Handling**: Proper propagation of exceptions across language boundaries
12+
- **Stream Processing**: Async stream generators (FizzBuzz implementations)
13+
- **Complex Communication**: Ping-pong pattern with recursive async calls
14+
- **Resource Management**: Future dropping and coroutine lifecycle management
15+
16+
## Prerequisites
17+
18+
### System Requirements
19+
20+
- **C++20 compiler** (GCC 10+, Clang 11+, or MSVC 2019+)
21+
- **Folly library** installed and available
22+
- **Rust 2018 edition** or later
23+
24+
### Folly Installation
25+
26+
The build script uses the `find-folly` crate to automatically locate your Folly installation. Ensure Folly is properly installed on your system:
27+
28+
#### Ubuntu/Debian
29+
```bash
30+
sudo apt-get install libfolly-dev
31+
```
32+
33+
#### macOS (with Homebrew)
34+
```bash
35+
brew install folly
36+
```
37+
38+
#### Building from Source
39+
Follow the [official Folly installation guide](https://github.com/facebook/folly#build) for your platform.
40+
41+
## Building and Running
42+
43+
### Build the Example
44+
```bash
45+
cd examples/folly
46+
cargo build
47+
```
48+
49+
### Run the Interactive Demo
50+
```bash
51+
cargo run
52+
```
53+
54+
### Run Tests
55+
```bash
56+
cargo test
57+
```
58+
59+
## Architecture
60+
61+
### Key Components
62+
63+
#### Rust Side (`src/main.rs`)
64+
- **Future Types**: `RustFutureVoid`, `RustFutureF64`, `RustFutureString`, `RustFutureStringNamespaced`
65+
- **Stream Types**: `RustStreamString`
66+
- **Parallel Computation**: Recursive async dot product using `async-recursion`
67+
- **Thread Pool**: Shared `ThreadPool` for concurrent execution
68+
69+
#### C++ Side (`src/folly_example.cpp`)
70+
- **Folly Coroutines**: Using `folly::coro::Task` for async operations
71+
- **Folly Futures**: Traditional future combinators with `folly::Future`
72+
- **Thread Pool**: `folly::CPUThreadPoolExecutor` for parallel work
73+
- **Exception Handling**: Custom exception types with proper propagation
74+
75+
#### Headers (`include/folly_example.h`)
76+
- **Future Definitions**: `CXXASYNC_DEFINE_FUTURE` macros for type mapping
77+
- **Stream Definitions**: `CXXASYNC_DEFINE_STREAM` macros
78+
- **Custom Exception Handling**: Specialized `TryCatch` implementation
79+
80+
## Features Demonstrated
81+
82+
### 1. Bidirectional Async Calls
83+
84+
**Rust → C++**:
85+
```rust
86+
// Call C++ coroutine from Rust
87+
let result = ffi::folly_dot_product_coro().await.unwrap();
88+
89+
// Call C++ future combinator from Rust
90+
let result = ffi::folly_dot_product_futures().await.unwrap();
91+
```
92+
93+
**C++ → Rust**:
94+
```cpp
95+
// Call Rust async function from C++
96+
auto future = rust_dot_product();
97+
double result = co_await std::move(future);
98+
```
99+
100+
### 2. Parallel Computation
101+
102+
Both languages implement the same parallel dot product algorithm:
103+
- **Vector Size**: 16,384 elements
104+
- **Split Threshold**: 32 elements
105+
- **Thread Pool**: 8 threads (C++), futures thread pool (Rust)
106+
- **Algorithm**: Recursive divide-and-conquer with async/await
107+
108+
### 3. Exception Handling
109+
110+
**C++ Exceptions → Rust**:
111+
```cpp
112+
// C++ throws custom exception
113+
throw MyException("kaboom");
114+
```
115+
116+
```rust
117+
// Rust catches as CxxAsyncException
118+
match result {
119+
Err(err) => assert_eq!(err.what(), "kaboom"),
120+
Ok(_) => panic!("should have failed"),
121+
}
122+
```
123+
124+
**Rust Errors → C++**:
125+
```rust
126+
// Rust returns error
127+
Err(CxxAsyncException::new("kapow".into()))
128+
```
129+
130+
```cpp
131+
// C++ catches exception
132+
try {
133+
co_await rust_function();
134+
} catch (const rust::async::Error& e) {
135+
std::cout << e.what() << std::endl; // "kapow"
136+
}
137+
```
138+
139+
### 4. Stream Processing
140+
141+
Async stream generators demonstrating:
142+
- **Basic Streams**: FizzBuzz sequence generation
143+
- **Nested Async**: Streams that internally await other futures
144+
- **Exception Propagation**: Streams that throw exceptions mid-stream
145+
- **Resource Cleanup**: Proper stream termination and cleanup
146+
147+
### 5. Complex Communication Patterns
148+
149+
**Ping-Pong Pattern**:
150+
```rust
151+
fn rust_folly_ping_pong(i: i32) -> RustFutureString {
152+
RustFutureString::infallible(async move {
153+
format!("{}ping ",
154+
if i < 4 {
155+
ffi::folly_ping_pong(i + 1).await.unwrap()
156+
} else {
157+
"".to_owned()
158+
}
159+
)
160+
})
161+
}
162+
```
163+
164+
This creates a recursive call chain: Rust → C++ → Rust → C++ → ... until termination.
165+
166+
## Test Coverage
167+
168+
The example includes comprehensive tests covering:
169+
170+
### Core Functionality Tests
171+
- `test_rust_calling_cpp_synchronously_coro()` - Rust → C++ coroutine calls
172+
- `test_rust_calling_cpp_synchronously_futures()` - Rust → C++ future calls
173+
- `test_rust_calling_cpp_on_scheduler()` - Scheduled execution
174+
- `test_cpp_calling_void_rust_synchronously()` - C++ → Rust void calls
175+
- `test_cpp_calling_rust_synchronously()` - C++ → Rust value calls
176+
- `test_cpp_calling_rust_on_scheduler()` - Scheduled Rust execution
177+
178+
### Error Handling Tests
179+
- `test_cpp_async_functions_throwing_exceptions()` - C++ exception propagation
180+
- `test_rust_async_functions_returning_errors()` - Rust error propagation
181+
182+
### Advanced Pattern Tests
183+
- `test_ping_pong()` - Recursive async communication
184+
- `test_complete()` - Void future completion
185+
- `test_dropping_futures()` - Resource cleanup
186+
- `test_fizzbuzz()` - Basic stream processing
187+
- `test_indirect_fizzbuzz()` - Nested async streams
188+
- `test_streams_throwing_exceptions()` - Stream error handling
189+
- `test_dropping_coroutines()` - Coroutine lifecycle management
190+
191+
## Implementation Notes
192+
193+
### Thread Safety
194+
- All async operations are thread-safe
195+
- Shared thread pools coordinate work between languages
196+
- Proper synchronization for cross-language communication
197+
198+
### Memory Management
199+
- Automatic resource cleanup for futures and streams
200+
- RAII patterns ensure proper destruction
201+
- No memory leaks in cross-language async operations
202+
203+
### Performance Considerations
204+
- Minimal overhead for language boundary crossings
205+
- Efficient parallel computation with proper work distribution
206+
- Optimized for both throughput and latency
207+
208+
### Namespace Support
209+
The example demonstrates C++ namespace mapping:
210+
```cpp
211+
CXXASYNC_DEFINE_FUTURE(::rust::String, foo, rust, bar, RustFutureStringNamespaced);
212+
```
213+
214+
```rust
215+
#[cxx_async::bridge(namespace = foo::rust::bar)]
216+
unsafe impl Future for RustFutureStringNamespaced {
217+
type Output = StringNamespaced;
218+
}
219+
```
220+
221+
## Troubleshooting
222+
223+
### Common Build Issues
224+
225+
**Folly Not Found**:
226+
```
227+
error: Couldn't find the Folly library!
228+
```
229+
Solution: Ensure Folly is installed and `PKG_CONFIG_PATH` includes Folly's `.pc` file.
230+
231+
**C++20 Support**:
232+
```
233+
error: coroutines are a C++20 extension
234+
```
235+
Solution: Verify your compiler supports C++20 and the `--std=c++20` flag is properly set.
236+
237+
**Linker Errors**:
238+
```
239+
undefined reference to folly symbols
240+
```
241+
Solution: Ensure all Folly dependencies are properly linked. Check `find-folly` output.
242+
243+
### Runtime Issues
244+
245+
**Thread Pool Errors**: Ensure sufficient system resources for the configured thread pools.
246+
247+
**Segmentation Faults**: Usually indicate improper future/stream lifecycle management. Review the test patterns for proper usage.
248+
249+
## Contributing
250+
251+
When modifying this example:
252+
253+
1. **Maintain Test Coverage**: All new features must include comprehensive tests
254+
2. **Document Changes**: Update this README for any new functionality
255+
3. **Follow Patterns**: Use existing error handling and async patterns
256+
4. **Verify Cross-Platform**: Test on multiple platforms if possible
257+
258+
## Related Examples
259+
260+
- [`examples/cppcoro`](../cppcoro/README.md) - Similar patterns using cppcoro instead of Folly
261+
- [`examples/common`](../common/README.md) - Shared utilities and patterns
262+
263+
## License
264+
265+
This example is licensed under both MIT and Apache 2.0 licenses, following the same licensing as the parent project.

0 commit comments

Comments
 (0)