-
Notifications
You must be signed in to change notification settings - Fork 2k
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
doc: What is movability in types #17826
Open
chrysn
wants to merge
8
commits into
RIOT-OS:master
Choose a base branch
from
chrysn-pull-requests:doc-move-semantics
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
f5e9f04
doc: What is movability in types
chrysn f0c1af3
fixup! doc: What is movability in types
chrysn 10b449a
fixup! doc: What is movability in types
chrysn abdaf2f
squash! / Add 'why do we care'
kaspar030 fa2ff8e
Merge branch 'doc-move-semantics' of github.com:chrysn-pull-requests/…
chrysn f24074c
fixup! doc: What is movability in types
chrysn 31553c2
fixup! doc: What is movability in types
chrysn 6971170
fixup! doc: What is movability in types
chrysn File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
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
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 |
---|---|---|
@@ -0,0 +1,101 @@ | ||
Semantics of typedefs and moving their values {#typedef-and-move} | ||
============================================= | ||
|
||
This page describes general properties of types defined (`typedef`'d) in RIOT. | ||
It is mostly aimed at developers who alter or extend RIOT; | ||
API users can often ignore them if they stick to idiomatic C. | ||
|
||
Movability | ||
---------- | ||
|
||
In C, generally, | ||
any type can technically be copied or moved, | ||
e.g. by returning it, | ||
by assigning it to other variables | ||
or by using `memcpy` / `memmove`. | ||
|
||
Once a value has been passed through an initializer that takes it by reference, | ||
any further copy or move are generally *not* allowed any more, | ||
for the initializer might have done anything self-referential inside the value, | ||
or (more commonly) have inserted it into some linked list. | ||
|
||
Some types are described to be "movable". | ||
If a type is movable, its values may be moved to a different memory address | ||
even after it has been passed into a function by reference. | ||
Consequently, functions taking a reference | ||
may use the reference to access the value for the duration of the function, | ||
but not store the pointer anywhere. | ||
|
||
Why do we care? | ||
--------------- | ||
|
||
In C we avoid passing large items by value, | ||
and consequently pass pointers around to initialize and finalize values; | ||
consequently, a stable address of a value is often around and ready to be used. | ||
|
||
In @rust using-rust "Rust" there are no restrictions on the size of return values, | ||
and logically moving values makes it easy to uphold [RAII] guarantees. | ||
(The Rust compiler will often use its knowledge of the program to not make values actually move, | ||
but neither is that guaranteed nor can it be reliably observed). | ||
|
||
[RAII]: https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization | ||
|
||
As most of RIOT's C APIs are being used by Rust through wrappers, | ||
movability of a type needs to be specified | ||
in order to no force Rust to assume *may never move* on *all* types. | ||
Types that may not move but are allocated by Rust | ||
require more [verbose and complicated] application code. | ||
|
||
[verbose and complicated]: https://doc.rust-lang.org/core/pin/index.html | ||
|
||
In addition to the benefits for the Rust wrappers, | ||
the documenting movability helps keeping RIOT internally consistent, | ||
and assists in other advanced use cases like coroutines. | ||
|
||
Is a type movable? | ||
------------------ | ||
|
||
Types are generally not movable, unless they are | ||
|
||
* documented to be movable, or | ||
* taken by value (or returned by value) in public API functions (or preprocessor macros) that use the type. | ||
|
||
In addition, | ||
individual functions may state that they take a reference to be short-lived, | ||
and make no requirements on the pointer's validity beyond the function's execution. | ||
(The @ref ztimer_is_set function might make such a statement). | ||
|
||
The lack of a required destructor / finalizer / closing function for a type | ||
is not a reliable indicator that a type is movable | ||
(but it is a pretty good hint). | ||
|
||
Examples | ||
-------- | ||
|
||
The @ref ipv6_addr_t type is movable (because @ref IPV6_ADDR_LOOPBACK returns one by value): | ||
while it is frequently passed by referenced due to its sheer size, | ||
an application may just `memcpy` an address out of an obtained pointer and store it for later use | ||
(maybe along with a cache entry). | ||
|
||
In contrast, a @ref ztimer_t is not movable: | ||
a value may be created locally and populated (in theory even be moved around), | ||
but once it is passed to @ref ztimer_set by reference, | ||
that pointer needs to stay valid until further notice. | ||
Unlike with other types, this is documented in very explicit words on the function. | ||
|
||
More subtly, @ref vfs_DIR is also not movable (because that is the default for any type): | ||
Once passed into @ref vfs_opendir, its memory location needs to stay stable | ||
until @ref vfs_closedir releases it. | ||
Moving it is less likely to have ill-effects (because only the @ref pkg_littlefs2 uses the property), | ||
but users still need to treat it as not movable. | ||
|
||
In contrast, the file descriptors of the VFS are movable | ||
because they are returned by value in the @ref vfs_open function and passed into @ref vfs_close the same way. | ||
(Also, file descriptors are `int`, and as primitive types are not covered by this page). | ||
|
||
API stability | ||
------------- | ||
|
||
Removing the note from a function that the type is movable should be considered a breaking change. | ||
The change note on such an API change may say that | ||
"this change is unlikely to break idiomatic C applications". |
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.
This is a nice explanation, but also slightly verbose and might be missing the "why do we care?".
Something along the lines of:
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.
Thanks, taken in and modified (because Rust doesn't just move data around either).