mirror of
https://github.com/phil-opp/blog_os.git
synced 2025-12-16 22:37:49 +00:00
Minor fixes
This commit is contained in:
@@ -913,7 +913,7 @@ The `from_raw` function is unsafe because undefined behavior can occur if the pr
|
|||||||
|
|
||||||
##### `RawWaker`
|
##### `RawWaker`
|
||||||
|
|
||||||
The [`RawWaker`] type requires the programmer to explicitly define a [_virtual method table_] (_vtable_) that specifies the functions that should be called when the `RawWaker` is cloned, woken, or dropped. The layout of this vtable is defined by the [`RawWakerVTable`] type. Each function receives a `*const ()` argument that is basically a _type-erased_ `&self` pointer to some struct, e.g. allocated on the heap. The reason for using a `*const ()` pointer instead of a proper reference is that the `RawWaker` type should be non-generic. The pointer value that is passed to the functions is the `data` pointer given to [`RawWaker::new`].
|
The [`RawWaker`] type requires the programmer to explicitly define a [_virtual method table_] (_vtable_) that specifies the functions that should be called when the `RawWaker` is cloned, woken, or dropped. The layout of this vtable is defined by the [`RawWakerVTable`] type. Each function receives a `*const ()` argument that is basically a _type-erased_ `&self` pointer to some struct, e.g. allocated on the heap. The reason for using a `*const ()` pointer instead of a proper reference is that the `RawWaker` type should be non-generic but still support arbitrary types. The pointer value that is passed to the functions is the `data` pointer given to [`RawWaker::new`].
|
||||||
|
|
||||||
[_virtual method table_]: https://en.wikipedia.org/wiki/Virtual_method_table
|
[_virtual method table_]: https://en.wikipedia.org/wiki/Virtual_method_table
|
||||||
[`RawWakerVTable`]: https://doc.rust-lang.org/stable/core/task/struct.RawWakerVTable.html
|
[`RawWakerVTable`]: https://doc.rust-lang.org/stable/core/task/struct.RawWakerVTable.html
|
||||||
@@ -961,7 +961,7 @@ use core::task::{Context, Poll};
|
|||||||
impl SimpleExecutor {
|
impl SimpleExecutor {
|
||||||
pub fn run(&mut self) {
|
pub fn run(&mut self) {
|
||||||
while let Some(mut task) = self.task_queue.pop_front() {
|
while let Some(mut task) = self.task_queue.pop_front() {
|
||||||
let waker = DummyWaker.to_waker();
|
let waker = dummy_waker();
|
||||||
let mut context = Context::from_waker(&waker);
|
let mut context = Context::from_waker(&waker);
|
||||||
match task.poll(&mut context) {
|
match task.poll(&mut context) {
|
||||||
Poll::Ready(()) => {} // task done
|
Poll::Ready(()) => {} // task done
|
||||||
@@ -972,7 +972,7 @@ impl SimpleExecutor {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The function uses a `while let` loop to handle all tasks in the `task_queue`. For each task, it first creates a `Context` type by wrapping a `Waker` instance created from our `DummyWaker` type. Then it invokes the `Task::poll` method with this `Context`. If the `poll` method returns `Poll::Ready`, the task is finished and we can continue with the next task. If the task is still `Poll::Pending`, we add it to the back of the queue again so that it will be polled again in a subsequent loop iteration.
|
The function uses a `while let` loop to handle all tasks in the `task_queue`. For each task, it first creates a `Context` type by wrapping a `Waker` instance returned by our `dummy_waker` function. Then it invokes the `Task::poll` method with this `Context`. If the `poll` method returns `Poll::Ready`, the task is finished and we can continue with the next task. If the task is still `Poll::Pending`, we add it to the back of the queue again so that it will be polled again in a subsequent loop iteration.
|
||||||
|
|
||||||
#### Trying It
|
#### Trying It
|
||||||
|
|
||||||
@@ -1004,7 +1004,7 @@ Let's summarize the various steps that happen for this example:
|
|||||||
- Next, we call the asynchronous `example_task` function, which returns a future. We wrap this future in the `Task` type, which moves it to the heap and pins it, and then add the task to the `task_queue` of the executor through the `spawn` method.
|
- Next, we call the asynchronous `example_task` function, which returns a future. We wrap this future in the `Task` type, which moves it to the heap and pins it, and then add the task to the `task_queue` of the executor through the `spawn` method.
|
||||||
- We then wall the `run` method to start the execution of the single task in the queue. This involves:
|
- We then wall the `run` method to start the execution of the single task in the queue. This involves:
|
||||||
- Popping the task from the front of the `task_queue`.
|
- Popping the task from the front of the `task_queue`.
|
||||||
- Creating a `DummyWaker` for the task, converting it to a [`Waker`] instance, and then creating a [`Context`] instance from it.
|
- Creating a `RawWaker` for the task, converting it to a [`Waker`] instance, and then creating a [`Context`] instance from it.
|
||||||
- Calling the [`poll`] method on the future of the task, using the `Context` we just created.
|
- Calling the [`poll`] method on the future of the task, using the `Context` we just created.
|
||||||
- Since the `example_task` does not wait for anything, it can directly run til its end on the first `poll` call. This is where the _"async number: 42"_ line is printed.
|
- Since the `example_task` does not wait for anything, it can directly run til its end on the first `poll` call. This is where the _"async number: 42"_ line is printed.
|
||||||
- Since the `example_task` directly returns `Poll::Ready`, it is not added back to the task queue.
|
- Since the `example_task` directly returns `Poll::Ready`, it is not added back to the task queue.
|
||||||
@@ -1392,6 +1392,11 @@ To fix this, we need to create an executor that properly utilizes the `Waker` no
|
|||||||
### Executor with Waker Support
|
### Executor with Waker Support
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Old
|
||||||
|
|
||||||
#### The `Wake` Trait
|
#### The `Wake` Trait
|
||||||
|
|
||||||
The simplest way to do this is by implementing the unstable [`Wake`] trait for an empty `DummyWaker` struct:
|
The simplest way to do this is by implementing the unstable [`Wake`] trait for an empty `DummyWaker` struct:
|
||||||
|
|||||||
Reference in New Issue
Block a user