···11+# This file is automatically @generated by Cargo.
22+# It is not intended for manual editing.
33+version = 4
44+55+[[package]]
66+name = "futures"
77+version = "0.1.0"
+95
README.md
···11+I will make no_std no_alloc stack allocated async work.
22+33+> What does bcsc stand for?
44+55+Borrow checked structured concurrency
66+77+Normal rust async is borrow checked, but this uses lifetimes (as opposed to spamming ref counting) to enforce structured concurrency in a more elegant, performant, and nostd compatible manner.
88+99+> What is wrong with you asa??
1010+1111+I set out to build the best robotics framework in every aspect. I will do that. It's unfortunate that rust doesn't currently make it easy, but I will gladly fix the problems in rust first.
1212+1313+> Ok(())
1414+1515+[multi-task vs intra-task concurrency](https://without.boats/blog/futures-unordered/)
1616+1717+multi-task concurrency extends better to parallelism
1818+- in my case, you can also implement thread affinity for hardware
1919+2020+`FuturesUnordered` requires Arc (std)
2121+2222+[scoped/non-'static futures](https://github.com/rmanoka/async-scoped)
2323+2424+why this (nostd structured concurrency) is unsound/impossible to do safetly
2525+2626+- https://tmandry.gitlab.io/blog/posts/2023-03-01-scoped-tasks/ !!
2727+- https://without.boats/blog/the-scoped-task-trilemma/ !!
2828+- https://conradludgate.com/posts/async-stack !!
2929+- https://cglab.ca/~abeinges/blah/everyone-poops/
3030+- https://sabrinajewson.org/blog/async-drop
3131+- https://blog.yoshuawuyts.com/the-waker-allocation-problem/
3232+- https://faultlore.com/blah/linear-rust/
3333+- https://blog.yoshuawuyts.com/linear-types-one-pager/
3434+3535+problem: i really want this feature, and am fine with unsound code
3636+3737+sound options:
3838+[async nursery](https://github.com/najamelan/async_nursery) - still 'static and not ergonomic api, wraps `FuturesUnordered`
3939+[async-scoped](https://github.com/rmanoka/async-scoped) - wraps `FuturesUnordered`, stores in executor
4040+better?
4141+https://github.com/maroider/async_scoped_task/blob/master/src/lib.rs
4242+unsafe `async_scoped::scope_and_collect` is perfect (unsafe) but uses heap alloc
4343+4444+[moro](https://github.com/nikomatsakis/moro) - wraps `FuturesUnordered`, relies on single threaded for invariants
4545+[task scope](https://docs.rs/task_scope/0.1.1/task_scope/) - scoped tasks but no drop guarantees unless blocking
4646+relevant rfc for Forget
4747+https://github.com/rust-lang/rfcs/pull/3782 !!
4848+4949+outdated tracking issue
5050+https://github.com/rust-lang/compiler-team/issues/727
5151+5252+other similar proposal for Leak
5353+https://zetanumbers.github.io/book/myosotis.html
5454+5555+alternate way of fixing drop issue
5656+https://github.com/Matthias247/rfcs/pull/1
5757+5858+other relevant work/rfc tracking pr
5959+https://github.com/rust-lang/rfcs/pull/2958
6060+6161+why drop?
6262+https://without.boats/blog/wakers-i/
6363+https://without.boats/blog/wakers-ii/
6464+6565+wakers are references to a Task/whatever the executor uses to wrap and enqueue Futures
6666+6767+safe api: [Wake](https://doc.rust-lang.org/beta/std/task/trait.Wake.html)
6868+where `Task: Wake`, wakers are essentially `Weak<Task>` so they can wake the task while it exists (Weak won't get upgraded once the task goes out of scope, so this is safe)
6969+why can't there be a safe api with `Arc`?
7070+`&dyn Wake` doesn't work because concurrency (think: joins) involves multiple wakers for the same task (unless everything is spawned instead of joined!??)
7171+wakers must be cloned, but clone -> Self (Self vtable is unknown through `&dyn Wake` pointer)
7272+ok that explains *const (), but why remove the lifetimes?
7373+not sure?? it seems like it wouldn't make a difference, most futures are static anyway for afformentioned soundness reasons
7474+- what if wakers are an intrusive linked list that the task traverses to cancel when dropped? (requires `!Forget`)/leak safety
7575+- what if wakers were `&dyn Task` with no cloning, and all intra-task concurrency was moved to join handles for scoped spawns
7676+ - also note that stuff like join!() doesn't actually execute the specific future, the outermost task gets woken and then executes all subtasks, which return Pending if they aren't ready
7777+ - intra-task concurrency is evil??
7878+ - still have to wait on concurrent join handles? -> join handles are part of nursery/scope, which stores its own waker-per-task -> subwakers/scope's wakers get called -> scope queues relevant tasks -> call higher level task waker
7979+there is no way to make existing `RawWaker`/`AtomicWaker` api safe because it cannot be "invalidated"?
8080+8181+## What is this project?
8282+8383+New async primitives that disallow intra-task concurrency, clone of `futures` and `futures-concurrency` for the new primitives.
8484+8585+## TODO:
8686+- [x] ScopedFuture
8787+- [ ] static combinators (Join Race etc), see futures-concurrency
8888+- [ ] `#[bsync]` or some compiler ScopedFuture generation
8989+- [ ] growable combinators (eg. `FutureGroup`, `FuturesUnordered`) (require alloc?)
9090+- [ ] unsound (needs `Forget`) multithreading
9191+- [ ] "rethinking async rust"
9292+- [ ] all of the above for streams
9393+- [ ] rfc?
9494+9595+channels: need lifetimed receievers, probably needs `Forget` (arc-like channels would be unsafe)
+14
futures/src/future.rs
···11+pub trait Wake {
22+ fn wake(&mut self);
33+}
44+55+/// ScopedFuture represents a unit of asynchronous computation that must be
66+/// polled by an external actor.
77+///
88+///
99+pub trait ScopedFuture<'scope> {
1010+ type Output;
1111+1212+ // TODO make new Context with &'a mut dyn Wake field
1313+ fn poll(self: Pin<&mut Self>, cx: &'scope mut dyn Wake) -> Poll<Self::Output>;
1414+}
+227-333
futures/src/lib.rs
···11-// what issue does this solve??
22-// first, literature review:
33-//
44-// multi-task vs intra-task concurrency
55-// https://without.boats/blog/futures-unordered/
66-// multi-task concurrency extends better to parallelism
77-// - in my case, you can also implement thread affinity for hardware
88-//
99-// `FuturesUnordered` requires Arc (std)
1010-//
1111-// scoped/non-'static futures https://github.com/rmanoka/async-scoped
1212-//
1313-// why this is unsound/impossible to do safetly
1414-// https://tmandry.gitlab.io/blog/posts/2023-03-01-scoped-tasks/ !!
1515-// https://without.boats/blog/the-scoped-task-trilemma/ !!
1616-// https://conradludgate.com/posts/async-stack !!
1717-// https://cglab.ca/~abeinges/blah/everyone-poops/
1818-// https://sabrinajewson.org/blog/async-drop
1919-// https://blog.yoshuawuyts.com/the-waker-allocation-problem/
2020-// https://faultlore.com/blah/linear-rust/
2121-// https://blog.yoshuawuyts.com/linear-types-one-pager/
2222-// problem: i really want this feature, and am fine with unsound code
2323-//
2424-// sound options:
2525-// async nursery - still 'static and not ergonomic api, wraps `FuturesUnordered`
2626-// https://github.com/najamelan/async_nursery
2727-//
2828-// async-scoped - wraps `FuturesUnordered`, stores in executor
2929-// https://github.com/rmanoka/async-scoped
3030-// better?
3131-// https://github.com/maroider/async_scoped_task/blob/master/src/lib.rs
3232-// unsafe `async_scoped::scope_and_collect` is perfect (unsafe) but uses heap alloc
3333-//
3434-// moro - wraps `FuturesUnordered`, relies on single threaded for invariants
3535-// https://github.com/nikomatsakis/moro
3636-//
3737-// task scope - scoped tasks but no drop guarantees unless blocking
3838-// https://docs.rs/task_scope/0.1.1/task_scope/
3939-//
4040-// relevant rfc for Forget
4141-// https://github.com/rust-lang/rfcs/pull/3782
4242-// outdated tracking issue
4343-// https://github.com/rust-lang/compiler-team/issues/727
4444-// other similar proposal for Leak
4545-// https://zetanumbers.github.io/book/myosotis.html
4646-// alternate way of fixing drop issue
4747-// https://github.com/Matthias247/rfcs/pull/1
4848-// other relevant work
4949-// https://github.com/rust-lang/rfcs/pull/2958
5050-//
5151-// why drop?
5252-// https://without.boats/blog/wakers-i/
5353-// https://without.boats/blog/wakers-ii/
5454-//
5555-// wakers are references to a Task/whatever the executor uses to wrap and enqueue Futures
5656-//
5757-// safe api: [Wake](https://doc.rust-lang.org/beta/std/task/trait.Wake.html)
5858-// where `Task: Wake`, wakers are essentially `Weak<Task>` so they can wake the task while it exists (Weak won't get upgraded once the task goes out of scope, so this is safe)
5959-//
6060-// why can't there be a safe api with `Arc`?
6161-// `&dyn Wake` doesn't work because concurrency (think: joins) involves multiple wakers for the same task (unless everything is spawned instead of joined!??)
6262-// wakers must be cloned, but clone -> Self (Self vtable is unknown through `&dyn Wake` pointer)
6363-//
6464-// ok that explains *const (), but why remove the lifetimes?
6565-// not sure?? it seems like it wouldn't make a difference, most futures are static anyway for afformentioned soundness reasons
6666-//
6767-// - what if wakers are an intrusive linked list that the task traverses to cancel when dropped? (requires `!Forget`)/leak safety
6868-// - what if wakers were `&dyn Task` with no cloning, and all intra-task concurrency was moved to join handles for scoped spawns
6969-// - also note that stuff like join!() doesn't actually execute the specific future, the outermost task gets woken and then executes all subtasks, which return Pending if they aren't ready
7070-// - intra-task concurrency is evil??
7171-// - still have to wait on concurrent join handles? -> join handles are part of nursery/scope, which stores its own waker-per-task -> subwakers/scope's wakers get called -> scope queues relevant tasks -> call higher level task waker
7272-// there is no way to make existing `RawWaker`/`AtomicWaker` api safe because it cannot be "invalidated"
11+mod future;
7327474-mod mental_illness {
7575- use std::{
7676- cell::Cell,
7777- pin::{self, Pin},
7878- ptr::NonNull,
7979- task::Poll,
8080- };
33+use std::{
44+ cell::Cell,
55+ pin::{self, Pin},
66+ ptr::NonNull,
77+ task::Poll,
88+};
8198282- use cordyceps::{list, Linked};
1010+use cordyceps::{Linked, list};
83118484- pub trait Wake {
8585- fn wake(&mut self);
8686- }
1212+/// from yoshuawuyts/futures-concurrency
1313+/// Wait for all futures to complete.
1414+///
1515+/// Awaits multiple futures simultaneously, returning the output of the futures
1616+/// in the same container type they were created once all complete.
1717+pub trait Join<'scope> {
1818+ /// The resulting output type.
1919+ type Output;
87208888- pub trait ScopedFuture<'scope> {
8989- type Output;
9090-9191- // TODO make new Context with &'a mut dyn Wake field
9292- fn poll(self: Pin<&mut Self>, cx: &'scope mut dyn Wake) -> Poll<Self::Output>;
9393- }
2121+ /// The [`Future`] implementation returned by this method.
2222+ type Future: ScopedFuture<'scope, Output = Self::Output>;
94239595- /// from yoshuawuyts/futures-concurrency
9696- /// Wait for all futures to complete.
2424+ /// Waits for multiple futures to complete.
9725 ///
9826 /// Awaits multiple futures simultaneously, returning the output of the futures
9999- /// in the same container type they were created once all complete.
100100- pub trait Join<'scope> {
101101- /// The resulting output type.
102102- type Output;
2727+ /// in the same container type they we're created once all complete.
2828+ ///
2929+ /// # Examples
3030+ ///
3131+ /// Awaiting multiple futures of the same type can be done using either a vector
3232+ /// or an array.
3333+ /// ```rust
3434+ /// # futures::executor::block_on(async {
3535+ /// use futures_concurrency::prelude::*;
3636+ ///
3737+ /// // all futures passed here are of the same type
3838+ /// let fut1 = core::future::ready(1);
3939+ /// let fut2 = core::future::ready(2);
4040+ /// let fut3 = core::future::ready(3);
4141+ ///
4242+ /// let outputs = [fut1, fut2, fut3].join().await;
4343+ /// assert_eq!(outputs, [1, 2, 3]);
4444+ /// # })
4545+ /// ```
4646+ ///
4747+ /// In practice however, it's common to want to await multiple futures of
4848+ /// different types. For example if you have two different `async {}` blocks,
4949+ /// you want to `.await`. To do that, you can call `.join` on tuples of futures.
5050+ /// ```rust
5151+ /// # futures::executor::block_on(async {
5252+ /// use futures_concurrency::prelude::*;
5353+ ///
5454+ /// async fn some_async_fn() -> usize { 3 }
5555+ ///
5656+ /// // the futures passed here are of different types
5757+ /// let fut1 = core::future::ready(1);
5858+ /// let fut2 = async { 2 };
5959+ /// let fut3 = some_async_fn();
6060+ /// // ^ NOTE: no `.await` here!
6161+ ///
6262+ /// let outputs = (fut1, fut2, fut3).join().await;
6363+ /// assert_eq!(outputs, (1, 2, 3));
6464+ /// # })
6565+ /// ```
6666+ ///
6767+ /// <br><br>
6868+ /// This function returns a new future which polls all futures concurrently.
6969+ fn join(self) -> Self::Future;
7070+}
10371104104- /// The [`Future`] implementation returned by this method.
105105- type Future: ScopedFuture<'scope, Output = Self::Output>;
7272+// "look at what they need for a fraction of our power" (more efficient join impl is regular join here)
7373+// https://github.com/yoshuawuyts/futures-concurrency/blob/main/src/utils/wakers/array/waker.rs
7474+// possibly copy large portions of futures-concurrency over here
10675107107- /// Waits for multiple futures to complete.
108108- ///
109109- /// Awaits multiple futures simultaneously, returning the output of the futures
110110- /// in the same container type they we're created once all complete.
111111- ///
112112- /// # Examples
113113- ///
114114- /// Awaiting multiple futures of the same type can be done using either a vector
115115- /// or an array.
116116- /// ```rust
117117- /// # futures::executor::block_on(async {
118118- /// use futures_concurrency::prelude::*;
119119- ///
120120- /// // all futures passed here are of the same type
121121- /// let fut1 = core::future::ready(1);
122122- /// let fut2 = core::future::ready(2);
123123- /// let fut3 = core::future::ready(3);
124124- ///
125125- /// let outputs = [fut1, fut2, fut3].join().await;
126126- /// assert_eq!(outputs, [1, 2, 3]);
127127- /// # })
128128- /// ```
129129- ///
130130- /// In practice however, it's common to want to await multiple futures of
131131- /// different types. For example if you have two different `async {}` blocks,
132132- /// you want to `.await`. To do that, you can call `.join` on tuples of futures.
133133- /// ```rust
134134- /// # futures::executor::block_on(async {
135135- /// use futures_concurrency::prelude::*;
136136- ///
137137- /// async fn some_async_fn() -> usize { 3 }
138138- ///
139139- /// // the futures passed here are of different types
140140- /// let fut1 = core::future::ready(1);
141141- /// let fut2 = async { 2 };
142142- /// let fut3 = some_async_fn();
143143- /// // ^ NOTE: no `.await` here!
144144- ///
145145- /// let outputs = (fut1, fut2, fut3).join().await;
146146- /// assert_eq!(outputs, (1, 2, 3));
147147- /// # })
148148- /// ```
149149- ///
150150- /// <br><br>
151151- /// This function returns a new future which polls all futures concurrently.
152152- fn join(self) -> Self::Future;
153153- }
7676+// contains a future that may be finished, safe to poll after ready
7777+enum MaybeReady<'scope, F: ScopedFuture<'scope>> {
7878+ Polling(F),
7979+ Ready(F::Output),
8080+}
15481155155- // "look at what they need for a fraction of our power" (more efficient join impl is regular join here)
156156- // https://github.com/yoshuawuyts/futures-concurrency/blob/main/src/utils/wakers/array/waker.rs
157157- // possibly copy large portions of futures-concurrency over here
8282+impl<'scope, F: ScopedFuture<'scope>> ScopedFuture<'scope> for MaybeReady<'scope, F> {
8383+ type Output = F::Output;
15884159159- // contains a future that may be finished, safe to poll after ready
160160- enum MaybeReady<'scope, F: ScopedFuture<'scope>> {
161161- Polling(F),
162162- Ready(F::Output),
8585+ fn poll(self: Pin<&mut Self>, cx: &'scope mut dyn Wake) -> Poll<Self::Output> {
8686+ todo!()
16387 }
8888+}
16489165165- impl<'scope, F: ScopedFuture<'scope>> ScopedFuture<'scope> for MaybeReady<'scope, F> {
166166- type Output = F::Output;
9090+// TODO bit packing
9191+struct WakeStore {
9292+ ready: bool,
9393+}
16794168168- fn poll(self: Pin<&mut Self>, cx: &'scope mut dyn Wake) -> Poll<Self::Output> {
169169- todo!()
170170- }
9595+impl WakeStore {
9696+ fn read_ready(&mut self) -> bool {
9797+ let out = self.ready;
9898+ self.ready = false;
9999+ out
171100 }
101101+}
172102173173- // TODO bit packing
174174- struct WakeStore {
175175- ready: bool,
103103+impl Wake for WakeStore {
104104+ fn wake(&mut self) {
105105+ self.ready = true;
176106 }
107107+}
177108178178- impl WakeStore {
179179- fn read_ready(&mut self) -> bool {
180180- let out = self.ready;
181181- self.ready = false;
182182- out
183183- }
184184- }
109109+// field for Join
110110+struct Pollable<'scope, F: ScopedFuture<'scope>> {
111111+ future: MaybeReady<'scope, F>,
112112+ waker: WakeStore,
113113+}
185114186186- impl Wake for WakeStore {
187187- fn wake(&mut self) {
188188- self.ready = true;
115115+impl<'scope, F: ScopedFuture<'scope>> Pollable<'scope, F> {
116116+ fn new(fut: F) -> Self {
117117+ Self {
118118+ future: MaybeReady::Polling(fut),
119119+ waker: WakeStore { ready: true },
189120 }
190121 }
122122+}
191123192192- // field for Join
193193- struct Pollable<'scope, F: ScopedFuture<'scope>> {
194194- future: MaybeReady<'scope, F>,
195195- waker: WakeStore,
196196- }
197197-198198- impl<'scope, F: ScopedFuture<'scope>> Pollable<'scope, F> {
199199- fn new(fut: F) -> Self {
200200- Self {
201201- future: MaybeReady::Polling(fut),
202202- waker: WakeStore { ready: true },
203203- }
124124+// heavily based on https://github.com/yoshuawuyts/futures-concurrency
125125+macro_rules! impl_join_tuple {
126126+ ($mod_name:ident $StructName:ident $($F:ident)+) => {
127127+ pub struct $StructName<'scope, $($F: ScopedFuture<'scope>),+> {
128128+ $($F: Pollable<'scope, $F>,)*
204129 }
205205- }
206130207207- // heavily based on https://github.com/yoshuawuyts/futures-concurrency
208208- macro_rules! impl_join_tuple {
209209- ($mod_name:ident $StructName:ident $($F:ident)+) => {
210210- pub struct $StructName<'scope, $($F: ScopedFuture<'scope>),+> {
211211- $($F: Pollable<'scope, $F>,)*
212212- }
131131+ impl<'scope, $($F: ScopedFuture<'scope>),+> ScopedFuture<'scope> for $StructName<'scope, $($F),+> {
132132+ type Output = ($($F::Output),+);
213133214214- impl<'scope, $($F: ScopedFuture<'scope>),+> ScopedFuture<'scope> for $StructName<'scope, $($F),+> {
215215- type Output = ($($F::Output),+);
216134217217-218218- fn poll(self: Pin<&mut Self>, cx: &'scope mut dyn Wake) -> Poll<Self::Output> {
219219- let this = unsafe { self.get_unchecked_mut() };
135135+ fn poll(self: Pin<&mut Self>, cx: &'scope mut dyn Wake) -> Poll<Self::Output> {
136136+ let this = unsafe { self.get_unchecked_mut() };
220137221221- let ready = true;
222222-223223- // "loop" through all futures, poll if ready
224224- $(
225225- match this.$F.future {
226226- MaybeReady::Polling(fut) => {
227227- let out = unsafe { Pin::new_unchecked(&mut fut) }.poll(&mut this.$F.waker);
228228- if let Poll::Ready(result) = out {
229229- // violate pin but that's ok because the future completed
230230- this.$F.future = MaybeReady::Ready(result);
231231- }
232232- },
233233- MaybeReady::Ready(_) => {
138138+ let ready = true;
234139140140+ // "loop" through all futures, poll if ready
141141+ $(
142142+ match this.$F.future {
143143+ MaybeReady::Polling(fut) => {
144144+ let out = unsafe { Pin::new_unchecked(&mut fut) }.poll(&mut this.$F.waker);
145145+ if let Poll::Ready(result) = out {
146146+ // violate pin but that's ok because the future completed
147147+ this.$F.future = MaybeReady::Ready(result);
235148 }
149149+ },
150150+ MaybeReady::Ready(_) => {
151151+236152 }
237237- )
238238-239239- todo!()
240153 }
241241- }
154154+ )
242155243243- impl<'scope, $($F: ScopedFuture<'scope>),+> Join<'scope> for ($($F),+) {
244244- type Output = ($($F::Output),*);
245245- type Future = $StructName<'scope, $($F),+>;
246246-247247- fn join(self) -> Self::Future {
248248- let ($($F),+): ($($F),+) = self;
249249- $StructName { $($F: Pollable::new($F),)* }
250250- }
156156+ todo!()
251157 }
252252-253253- // // Implementation block for the generated struct.
254254- // impl<$(F),+> $StructName<$(F),+> {
255255- // /// Returns the number of generic types the struct was created with.
256256- // /// This uses a common macro trick to "count" repetitions by creating
257257- // /// an array of stringified identifiers and getting its length at compile time.
258258- // const fn generic_type_count() -> usize {
259259- // [$(stringify!(F)),*].len()
260260- // }
158158+ }
261159262262- // /// Checks if the `count` field is greater than the number of generic types.
263263- // pub fn is_count_greater_than_len(&self) -> bool {
264264- // self.count as usize > Self::generic_type_count()
265265- // }
266266- // }
267267- };
268268- }
160160+ impl<'scope, $($F: ScopedFuture<'scope>),+> Join<'scope> for ($($F),+) {
161161+ type Output = ($($F::Output),*);
162162+ type Future = $StructName<'scope, $($F),+>;
269163270270- impl_join_tuple!(join2 Join2 A B);
164164+ fn join(self) -> Self::Future {
165165+ let ($($F),+): ($($F),+) = self;
166166+ $StructName { $($F: Pollable::new($F),)* }
167167+ }
168168+ }
271169272272- // scoped future combinators:
273273- //
274274- // Join<N>
275275- // TryJoin
276276- // Race
277277- // RaceOk
278278- //
279279- // add Deadline(a, rest) (deadline_against())
280280- // also functionality like (a, b, c).join().race_against(d, e, f)
281281- //
282282- // UnorderedJoinQueueStream? is this VecJoinStream?
283283- // OrderedJoinQueueStream
284284-285285- pub trait ScopedStream<'scope> {
286286- type Item;
287287-288288- fn poll_next(self: Pin<&mut Self>, cx: &'scope mut dyn Wake) -> Poll<Option<Self::Item>>;
289289- }
170170+ // // Implementation block for the generated struct.
171171+ // impl<$(F),+> $StructName<$(F),+> {
172172+ // /// Returns the number of generic types the struct was created with.
173173+ // /// This uses a common macro trick to "count" repetitions by creating
174174+ // /// an array of stringified identifiers and getting its length at compile time.
175175+ // const fn generic_type_count() -> usize {
176176+ // [$(stringify!(F)),*].len()
177177+ // }
290178291291- // represents an active task, to be used by UnorderedJoinHandle
292292- pub struct Task<'scope, Output, F: ScopedFuture<'scope, Output = Output>> {
293293- inner: F,
294294- scope: &'scope UnorderedJoinHandle<'scope, Output>,
295295- next_active: list::Links<Self>,
296296- }
179179+ // /// Checks if the `count` field is greater than the number of generic types.
180180+ // pub fn is_count_greater_than_len(&self) -> bool {
181181+ // self.count as usize > Self::generic_type_count()
182182+ // }
183183+ // }
184184+ };
185185+}
297186298298- impl<'scope, Output, F: ScopedFuture<'scope, Output = Output>> Wake for Task<'scope, Output, F> {
299299- fn wake(&self) {
300300- // TODO add self to running queue
301301- // propogate wake up scope
302302- self.scope.enqueue();
303303- }
304304- }
187187+impl_join_tuple!(join2 Join2 A B);
305188306306- // impl<'scope, Output, F: ScopedFuture<'scope, Output = Output>> TaskErasure
307307- // for Task<'scope, Output, F>
308308- // {
309309- // }
189189+// scoped future combinators:
190190+//
191191+// Join<N>
192192+// TryJoin
193193+// Race
194194+// RaceOk
195195+//
196196+// add Deadline(a, rest) (deadline_against())
197197+// also functionality like (a, b, c).join().race_against(d, e, f)
198198+//
199199+// UnorderedJoinQueueStream? is this VecJoinStream?
200200+// OrderedJoinQueueStream
310201311311- // !Forget
312312- // this is the most annoying data structure ever:
313313- // should it own the tasks?? maybe
314314- //
315315- // a)
316316- //
317317- // Task { &Future, *mut Task }
318318- //
319319- // b)
320320- //
321321- // b is better, use proc macros, no data structures!
322322- //
323323- // <n1, n2, n3 > (o1, o2, o3) etc
324324- // pub struct UnorderedJoinHandle<'scope, Output> {
325325- // parent_waker: &'scope mut dyn Wake,
326326- // active_head: Pin<*const dyn TaskErasure>,
327327- // inactive_head: Pin<*const dyn TaskErasure>,
328328- // // tasks: [&'scope dyn ScopedFuture<'scope, Output = Output>; N],
329329- // }
202202+pub trait ScopedStream<'scope> {
203203+ type Item;
330204331331- // impl<'scope, Output> UnorderedJoinHandle<'scope, Output> {
332332- // /// adds task to running queue, wakes task
333333- // pub fn enqueue(&self) {
334334- // self.parent_waker.wake();
335335- // todo!()
336336- // }
205205+ fn poll_next(self: Pin<&mut Self>, cx: &'scope mut dyn Wake) -> Poll<Option<Self::Item>>;
206206+}
337207338338- // pub fn spawn(&self) {
339339- // todo!()
340340- // }
341341- // }
208208+// represents an active task, to be used by UnorderedJoinHandle
209209+pub struct Task<'scope, Output, F: ScopedFuture<'scope, Output = Output>> {
210210+ inner: F,
211211+ scope: &'scope UnorderedJoinHandle<'scope, Output>,
212212+ next_active: list::Links<Self>,
213213+}
342214343343- // should be mandated by !Forget
344344- /// # Soundness
345345- ///
346346- /// This is unsound!! Don't use my code.
347347- impl<'scope, const N: usize, Output> Drop for UnorderedJoinHandle<'scope, N, Output> {
348348- fn drop(&mut self) {
349349- // TODO sever linked list
350350- }
215215+impl<'scope, Output, F: ScopedFuture<'scope, Output = Output>> Wake for Task<'scope, Output, F> {
216216+ fn wake(&self) {
217217+ // TODO add self to running queue
218218+ // propogate wake up scope
219219+ self.scope.enqueue();
351220 }
221221+}
352222353353- impl<'scope, const N: usize, Output> ScopedStream<'scope>
354354- for UnorderedJoinHandle<'scope, N, Output>
355355- {
356356- type Item = Output;
223223+// impl<'scope, Output, F: ScopedFuture<'scope, Output = Output>> TaskErasure
224224+// for Task<'scope, Output, F>
225225+// {
226226+// }
357227358358- fn poll_next(self: Pin<&mut Self>, cx: &'scope mut dyn Wake) -> Poll<Option<Self::Item>> {
359359- // update parent waker to latest waker
360360- // unsafe { self.get_mut(|f| &mut f.parent_waker) }.set(cx);
361361- self.get_mut().parent_waker = cx;
228228+// !Forget
229229+// this is the most annoying data structure ever:
230230+// should it own the tasks?? maybe
231231+//
232232+// a)
233233+//
234234+// Task { &Future, *mut Task }
235235+//
236236+// b)
237237+//
238238+// b is better, use proc macros, no data structures!
239239+//
240240+// <n1, n2, n3 > (o1, o2, o3) etc
241241+// pub struct UnorderedJoinHandle<'scope, Output> {
242242+// parent_waker: &'scope mut dyn Wake,
243243+// active_head: Pin<*const dyn TaskErasure>,
244244+// inactive_head: Pin<*const dyn TaskErasure>,
245245+// // tasks: [&'scope dyn ScopedFuture<'scope, Output = Output>; N],
246246+// }
362247363363- todo!()
364364- }
365365- }
248248+// impl<'scope, Output> UnorderedJoinHandle<'scope, Output> {
249249+// /// adds task to running queue, wakes task
250250+// pub fn enqueue(&self) {
251251+// self.parent_waker.wake();
252252+// todo!()
253253+// }
366254367367- mod tests {
368368- use super::*;
255255+// pub fn spawn(&self) {
256256+// todo!()
257257+// }
258258+// }
369259370370- #[test]
371371- fn hmm() {
372372- // struct Task {}
373373- // impl Wake for Task {
374374- // fn wake(&self) {
375375- // todo!()
376376- // }
377377- // }
378378- }
260260+// should be mandated by !Forget
261261+/// # Soundness
262262+///
263263+/// This is unsound!! Don't use my code.
264264+impl<'scope, const N: usize, Output> Drop for UnorderedJoinHandle<'scope, N, Output> {
265265+ fn drop(&mut self) {
266266+ // TODO sever linked list
379267 }
380268}
381269382382-use std::{pin::Pin, task::Poll};
270270+impl<'scope, const N: usize, Output> ScopedStream<'scope>
271271+ for UnorderedJoinHandle<'scope, N, Output>
272272+{
273273+ type Item = Output;
383274384384-use futures::stream::FuturesUnordered;
275275+ fn poll_next(self: Pin<&mut Self>, cx: &'scope mut dyn Wake) -> Poll<Option<Self::Item>> {
276276+ // update parent waker to latest waker
277277+ // unsafe { self.get_mut(|f| &mut f.parent_waker) }.set(cx);
278278+ self.get_mut().parent_waker = cx;
385279386386-pub fn add(left: u64, right: u64) -> u64 {
387387- left + right
280280+ todo!()
281281+ }
388282}
389283390284#[cfg(test)]