Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions benchmarks/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ if meson.get_compiler('cpp').has_argument('-fcoroutines')
elif meson.get_compiler('cpp').has_argument('-fcoroutines-ts')
cpp_args += [ '-fcoroutines-ts', '-DLIBASYNC_FORCE_USE_EXPERIMENTAL', '-fsized-deallocation' ]
deps += subproject('cxxshim').get_variable('clang_coroutine_dep')
else
error('Unsupported compiler')
endif

deps += subproject('frigg').get_variable('frigg_dep')
Expand Down
1 change: 0 additions & 1 deletion docs/src/headers/basic/any_receiver.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ struct any_receiver {
any_receiver(R receiver); // (1)

void set_value(T); // (2)
void set_value_noinline(T); // (2)
}
```

Expand Down
2 changes: 1 addition & 1 deletion docs/src/headers/basic/operation.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ struct write_operation {
write_operation(write_operation &&) = delete;
write_operation &operator=(write_operation &&) = delete;

bool start_inline() { /* omitted for brevity */ }
void start() { /* omitted for brevity */ }

private:
uv_write_t req_;
Expand Down
15 changes: 3 additions & 12 deletions docs/src/headers/basic/receives.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,17 @@ concept Receives = ...;

### Requirements

A `set_value_inline` and `set_value_noinline` members, which can be called with
a `T&&` value, or no parameters, if `T` is `void`.
A `set_value` member which can be called with a `T&&` value, or no parameters, if `T` is `void`.

## Examples

```cpp
struct discard_receiver {
template<typename T>
void set_value_inline(T) {
void set_value(T) {
assert(std::is_constant_evaluated());
}
void set_value_inline() {
assert(std::is_constant_evaluated());
}

template<typename T>
void set_value_noinline(T) {
assert(std::is_constant_evaluated());
}
void set_value_noinline() {
void set_value() {
assert(std::is_constant_evaluated());
}
};
Expand Down
6 changes: 1 addition & 5 deletions docs/src/headers/basic/spawn.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,7 @@ This function doesn't return any value.

```cpp
struct my_receiver {
void set_value_inline(int value) {
std::cout << "Value: " << value << std::endl;
}

void set_value_noinline(int value) {
void set_value(int value) {
std::cout << "Value: " << value << std::endl;
}
};
Expand Down
5 changes: 1 addition & 4 deletions docs/src/headers/execution.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,7 @@ This header contains customization point objects (CPOs) for the following
methods/functions:
- `connect` (as a member or function),
- `start` (as a member or function),
- `start_inline` (as a member),
- `set_value` (as a member),
- `set_value_inline` (as a member),
- `set_value_noinline` (as a member).

In addition to that, it provides a convenience type definition for working with operations:
```cpp
Expand All @@ -25,5 +22,5 @@ using operation_t = std::invoke_result_t<connect_cpo, S, R>;

```cpp
auto op = async::execution::connect(my_sender, my_receiver);
bool finished_inline = async::execution::start_inline(op);
async::execution::start(op);
```
5 changes: 2 additions & 3 deletions docs/src/io-service.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,17 @@ The following example shows the approximate call graph executing an event-loop-d

- `async::run(my_sender, my_io_service)`
- `my_operation = async::execution::connect(my_sender, internal_receiver)`
- `async::execution::start_inline(my_operation)`
- `async::execution::start(my_operation)`
- `my_operation` starts running...
- `co_await some_ev`
- `some_ev` operation is started
- `my_io_service.add_waiter(this)`
- (`async::execution::start_inline` returns `false`)
- `my_io_service.wait()`
- IO service waits for event to happen...
- `waiters_.front()->complete()`
- `some_ev` operation completes
- `my_operation` resumes
- `co_return 2`
- `async::execution::set_value_noinline(internal_receiver, 2)`
- `async::execution::set_value(internal_receiver, 2)`
- `return internal_receiver.value`
- (`async::run` returns `2`)
17 changes: 4 additions & 13 deletions docs/src/sender-receiver.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,14 @@ asynchronous operation. It is immovable, and as such pointers to it will remain
valid for as long as the operation exists. When the operation is finished, it
notifies the receiver and optionally passes it a result value.

Every operation must either have a `void start()` or a `bool start_inline()` method
that is invoked when the operation is first started. `void start()` is equivalent to
`bool start_inline()` with `return false;` at the end.

#### Inline and no-inline completion

Operations that complete synchronously can signal inline completion. If an operation
completes inline, it sets the value using `set_value_inline`, and returns `true` from
`start_inline` (Operations that have a `start` method cannot complete inline). Inline
completion allows for certain optimizations, like avoiding suspending the coroutine
if the operation completed synchronously.
Every operation must either have a `void start()` method
that is invoked when the operation is first started.

### Receiver

A receiver is an object that knows what to do after an operation finishes (e.g. how to
resume the coroutine). It optionally receives a result value from the operation.
It is moveable.

Every receiver must have `void set_value_inline(...)` and `void set_value_noinline(...)`
methods that are invoked by the operation when it completes.
Every receiver must have a `void set_value(...)`
method that is invoked by the operation when it completes.
32 changes: 12 additions & 20 deletions docs/src/your-own-sender.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,24 +114,20 @@ type in order to support any receiver type.
The operation is also made immovable and non-copyable so that pointers to it can
safely be taken without worrying that they may become invalid at some point.

Next, we add a `start_inline` method:
Next, we add a `start` method:
```cpp
bool start_inline() {
void start() {
auto result = uv_write(&req_, handle_, bufs_, nbufs_, [] (uv_write_t *req, int status) {
/* TODO */
});

if (result < 0) {
async::execution::set_value_inline(r_, result);
return true; // Completed inline
}

return false; // Did not complete inline
if (result < 0)
async::execution::set_value(r_, result); // Completed inline
}
```

We use `start_inline` here in order to notify the user of any immediate errors
synchronously. We use functions defined inside of `async::execution` to set the
Here, `start` completes synchronously if any errors happen immediately.
We use functions defined inside of `async::execution` to set the
value, because they properly detect which method should be called on the receiver.

Now, let's implement the actual asynchronous completion:
Expand Down Expand Up @@ -160,11 +156,11 @@ Finally, we add our `complete` method:
```cpp
private:
void complete(int status) {
async::execution::set_value_noinline(r_, status);
async::execution::set_value(r_, status);
}
```

On `complete`, we use `async::execution::set_value_noinline` to set the result
On `complete`, we use `async::execution::set_value` to set the result
value and notify the receiver that the operation is complete (so that it can
for example resume the suspended coroutine, like the `async::sender_awaiter` receiver).

Expand Down Expand Up @@ -212,24 +208,20 @@ struct write_operation {
write_operation(write_operation &&) = delete;
write_operation &operator=(write_operation &&) = delete;

bool start_inline() {
void start() {
handle_->data = this;
auto result = uv_write(&req_, handle_, bufs_, nbufs_, [] (uv_write_t *req, int status) {
auto op = static_cast<write_operation *>(req->handle->data);
op->complete(status);
});

if (result < 0) {
async::execution::set_value_inline(r_, result);
return true; // Completed inline
}

return false; // Did not complete inline
if (result < 0)
async::execution::set_value(r_, result);
}

private:
void complete(int status) {
async::execution::set_value_noinline(r_, status);
async::execution::set_value(r_, status);
}

uv_write_t req_;
Expand Down
Loading
Loading