Skip to content

Commit

Permalink
(WIP) docs(coro): reorganize coro docs and add examples for new featu…
Browse files Browse the repository at this point in the history
…res (#818)
  • Loading branch information
Mishura4 authored Aug 30, 2023
1 parent 065d4f1 commit 32b6759
Show file tree
Hide file tree
Showing 17 changed files with 806 additions and 572 deletions.
7 changes: 4 additions & 3 deletions Doxyfile
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ OPTIMIZE_OUTPUT_VHDL = NO
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
# the files are not read by doxygen.

EXTENSION_MAPPING =
EXTENSION_MAPPING = dox=md

# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
# according to the Markdown format, which allows for more readable
Expand Down Expand Up @@ -789,7 +789,8 @@ RECURSIVE = YES
EXCLUDE = deps \
build \
include/dpp/format \
include/dpp/nlohmann
include/dpp/nlohmann \
docpages/include

# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded
Expand Down Expand Up @@ -829,7 +830,7 @@ EXCLUDE_SYMBOLS = nlohmann::* \
# that contain example code fragments that are included (see the \include
# command).

EXAMPLE_PATH =
EXAMPLE_PATH =docpages/include

# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
Expand Down
1 change: 1 addition & 0 deletions docpages/05_example_programs.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ There are example programs here for all skill levels demonstrating a great many
* \subpage the-basics
* \subpage interactions-and-components
* \subpage music-and-audio
* \subpage using-coroutines
* \subpage misc

Is the example you are looking for missing from these sections? Pop over to our [discord server](https://discord.com/dpp) and let us know what you need... Or, even better, if you know how to do something and want to contribute an example of your own, just submit a PR!
3 changes: 1 addition & 2 deletions docpages/06_advanced_reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@
* \subpage coding-standards "Coding Style Standards"
* \subpage unit-tests "Unit Tests"
* \subpage lambdas-and-locals "Ownership of local variables and safely transferring into a lambda"
* \subpage coroutines "Advanced commands with coroutines"
* \subpage governance "Project Governance"
* \subpage roadmap "Development Roadmap"
* \subpage security "Security"
* \subpage automating-with-jenkins "Automating your bot with Jenkins"
* \subpage separate-events "Separating events into new classes"
* \subpage separate-events "Separating events into new classes"
225 changes: 0 additions & 225 deletions docpages/advanced_reference/coroutines.md

This file was deleted.

10 changes: 10 additions & 0 deletions docpages/example_programs/using_coroutines.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
\page using-coroutines Using Coroutines

\include{doc} coro_warn.dox

One of the most anticipated features of C++20 is the addition of coroutines: in short, they are functions that can be paused while waiting for data and resumed when that data is ready. They make asynchronous programs much easier to write, but they do come with additional dangers and subtleties.

* \subpage coro-introduction
* \subpage coro-simple-commands
* \subpage awaiting-events
* \subpage expiring-buttons
53 changes: 53 additions & 0 deletions docpages/example_programs/using_coroutines/awaiting_events.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
\page awaiting-events Waiting for events

\include{doc} coro_warn.dox

D++ makes it possible to await events: simple use `co_await` on any of the event routers, such as \ref dpp::cluster::on_message_create "on_message_create", and your coroutine will be suspended until the next event fired by this event router. You can also `co_await` the return of an event router's \ref dpp::event_router_t::when "when()" method while passing it a predicate function object, it will only resume your coroutine when the predicate returns true. Be aware that your coroutine is attached to the event router only when you call `co_await` and not before, and will be detached as it is resumed.

\note When the event router resumes your coroutine, it will give you __a reference to the event object__. This will likely mean it will be destroyed after your next co_await, make sure to save it in a local variable if you need it for longer.

~~~~~~~~~~cpp
#include <dpp/dpp.h>

int main() {
dpp::cluster bot("token", dpp::i_default_intents | dpp::i_message_content);

bot.on_log(dpp::utility::cout_logger());

bot.on_slashcommand([](dpp::slashcommand_t event) -> dpp::job {
if (event.command.get_command_name() == "test") {
// Make a message and add a button with its custom ID set to the command interaction's ID so we can identify it
dpp::message m{"Test"};
std::string id{event.command.id.str()};
m.add_component(
dpp::component{}.add_component(dpp::component{}.set_type(dpp::cot_button).set_label("Click me!").set_id(id))
);
co_await event.co_reply(m);

dpp::button_click_t click_event = co_await event.from->creator->on_button_click.when(
// Note!! Due to a bug in g++11 and g++12, id must be captured as a reference here or the compiler will destroy it twice. This is fixed in g++13
[&id] (dpp::button_click_t const &b) {
return b.custom_id == id;
}
);
// Acknowledge the click with an empty message and edit the original response, removing the button
click_event.reply(dpp::ir_deferred_update_message, dpp::message{});
event.edit_original_response(dpp::message{"You clicked the button!"});
}
});

bot.on_ready([&bot](const dpp::ready_t & event) {
if (dpp::run_once<struct register_bot_commands>()) {
dpp::slashcommand command{"test", "Test awaiting for an event", bot.me.id};

bot.global_command_create(command);
}
});

bot.start(dpp::st_wait);
}
~~~~~~~~~~

Note that there is a problem with that! If the user never clicks your button, or if the message gets deleted, your coroutine will be stuck waiting... And waiting... Forever until your bot shuts down, occupying a space in memory. This is where the \ref expiring-buttons "next example" comes into play as a solution, with a button that expires with time.

\image html waiting_coroutine.jpg
Loading

0 comments on commit 32b6759

Please sign in to comment.