New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DOCS-PluginApi:Wording, tense and passive changes (minor). #677
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,10 @@ | ||
# Kaleidoscope Plugin API Internals | ||
|
||
This document attempts to explain how the plugin system works internally, behind | ||
the scenes. We feel this is necessary, because there are some unorthodox | ||
solutions in play, which make the code incredibly hard to untangle. This is an | ||
unavoidable side-effect of employing a system that lets us use non-virtual | ||
functions, and save large amounts of RAM thereby. It would be a lot simpler | ||
without this feature, but alas, saving hundreds of bytes of RAM is something we | ||
felt is worth the complexity. | ||
In this document we explain how the plugin system works behind the scenes. | ||
|
||
Lets start at the top: | ||
This is useful because there are some unorthodox solutions in play that make the code incredibly hard to untangle. It's an unavoidable side effect of employing a system that uses non-virtual functions, which lets us save large amounts of RAM. | ||
|
||
Let's start at the top: | ||
|
||
## `KALEIDOSCOPE_INIT_PLUGINS` | ||
|
||
|
@@ -45,20 +41,20 @@ another header, because it belongs to `Kaleidoscope.h`. | |
This is where things get interesting. This macro does two things: | ||
|
||
- It creates `kaleidoscope_internal::EventDispatcher`, a class with a single | ||
method, `apply`. This is a templated method, the template argument is the | ||
method `apply` will call. Thus, `EventDispatcher::template apply<foo>` will | ||
resolve to a function that calls the `foo` method of each plugin we listed | ||
method, `apply`. This is a templated method. The template argument is the | ||
method `apply` calls. Therefore, `EventDispatcher::template apply<foo>` | ||
resolves to a function that calls the `foo` method of each plugin we list | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's an extra space in |
||
for `KALEIDOSCOPE_INIT_PLUGINS`. We'll see in a bit how this happens. | ||
|
||
- The other part creates overrides for the `Kaleidoscope::Hooks::` family of | ||
functions. These are wrappers around `EventDispatcher::template apply<foo>`. | ||
We have these so higher level code would not need to care about the | ||
implementation details, so that it can invoke the hooks as if they were | ||
We have these so that higher level code does not need to be concerned with the | ||
implementation details. It can invoke the hooks as if they were | ||
ordinary functions. | ||
|
||
## `_FOR_EACH_EVENT_HANDLER(_REGISTER_EVENT_HANDLER)` | ||
|
||
Lets look at `_FOR_EACH_EVENT_HANDLER` and `_REGISTER_EVENT_HANDLER` first, | ||
Let's look at `_FOR_EACH_EVENT_HANDLER` and `_REGISTER_EVENT_HANDLER` first, | ||
because that's easier to explain, and does not lead down another rabbit hole. | ||
|
||
### `_REGISTER_EVENT_HANDLER` | ||
|
@@ -163,7 +159,7 @@ this to be able to make sense of `_REGISTER_EVENT_HANDLER` above. | |
|
||
### `_INLINE_EVENT_HANDLER_FOR_PLUGIN` | ||
|
||
This in isolation, is not very interesting, and is closely tied to | ||
In isolation, this is not very interesting, and is closely tied to | ||
`EventDispatcher`. The definition is here so we can look at it while we learn | ||
the details of `EventDispatcher` below. | ||
|
||
|
@@ -180,10 +176,10 @@ the details of `EventDispatcher` below. | |
|
||
### Back to `EventDispatcher`... | ||
|
||
The `EventDispatcher` structure has a single method: `apply<>`, which needs an | ||
event handler as its template argument. What the macro does, is call the event | ||
The `EventDispatcher` structure has a single method: `apply<>`, which requires an | ||
event handler as its template argument. The macros calls the event | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
handler given in the template argument for each and every initialised plugin. | ||
It's best explained with an example! Lets use two plugins, `SomePlugin` and | ||
It's best explained with an example! Let's use two plugins, `SomePlugin` and | ||
`ExampleEffect`: | ||
|
||
```c++ | ||
|
@@ -243,9 +239,9 @@ struct EventDispatcher { | |
Because we call `EventHandler_onSetup::call` with the plugin as the first | ||
argument, and because `call` is also a templated function, where the first | ||
argument is templated, we get a method that is polymorphic on its first | ||
argument. Meaning, for each and every plugin, we'll have a matching | ||
`EventHandler_onSetup::call`, that is tied to that plugin. *This* is the magic | ||
that lets us use non-virtual methods! | ||
argument. This means that for each and every plugin, we have a matching | ||
`EventHandler_onSetup::call` that is tied to that plugin. *This* is the magic | ||
that lets us use non-virtual methods. | ||
|
||
## Exploring what the compiler does | ||
|
||
|
@@ -335,8 +331,8 @@ present. | |
|
||
## Summary | ||
|
||
As we can see, there is a lot going on behind the scenes, and a combination of | ||
As you can see, there is a lot going on behind the scenes, and a combination of | ||
template meta programming and pre-processor macros is used to accomplish our | ||
goal. But following the code path like we did above allows us to see what the | ||
compiler sees (more or less), and inlining all the things that are done | ||
compile-time gives us the final code, which is pretty simple by that point. | ||
goal. Following the code path as outlined above allows us to see what the | ||
compiler sees (more or less), and inlining all the things that are done at | ||
compile-time provides us with the final code, which is pretty simple by that point. |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the term "incredibly hard" is a bit hyperbolic. Perhaps "surprisingly hard" would be better. Or even just "difficult", à la Mark Twain's advice…
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The term comes from the original, but I do like the suggestion, and "difficult" sounds like a perfect word.