5 ms·
Async destructors, async genericity and completion futures
- josephcsible 4y ago> There is no way to statically guarantee that the method isn’t called twice, that’s up to the user. Couldn't this be solved by giving the user a dummy object that isn't Clone and that the method takes ownership of?
- lilyball 4y agoYes, but you'd have to generate that dummy value upon creating the real value, and then pass it along with the real value so it's available to the spot that needs to consume it. This would ultimately end up being just a much more awkward way of having the real value just track a boolean internally for this and slapping Option around any non-trivial return value from the method.
- Animats 4y ago> There is no way to statically guarantee that the method isn’t called twice, that’s up to the user. That sounds like "re-animation", where a destructor leaks something to the outside that keeps the object from being destructed. That was in Microsoft Managed C++, and it was similarly awful. If all you want to do is clean up something on deletion, how about passing the thing that needs cleanup to a channel, to be handled by another task?
- sbf501 4y agoI started reading this hoping to get some insight into creating a way to abort an in flight promise, e.g. async/await pattern for a tower of async functons, and not a Promise.all[]. However, this is so exhaustively well-written then I realized this is a much harder problem. Yes, I know this is Rust, but the syntax and problems are similar for any deferred execution, ESPECIALLY when hardware is sitting at the bottom of the call. While I applaud the author's completeness and attention to detail -- and how they are refreshingly open about certain solutions looking like "hacks" -- the paper would benefit from a Conclusions/Recommendations. (I know, that's lazy of me, but I think it would be a nice finish.)
- AgentME 4y agoA good way across languages to cancel an asynchronous task is by passing a CancellationToken / AbortSignal (Javascript) as an argument. This scales nicely as a task can pass the token onward to any number of other tasks, and the original creator of the token can abort it and all uses of it at any time.
- e12e 4y agoFeels like this should be a language feature, though - like how python passes self for objects - or ruby binds self for you?
- AgentME 4y agoKotlin has "structured concurrency" which I believe automatically handles some cases of this, but I don't fully understand it. I find explicit cancellation tokens without any magic easier to understand.
- sbf501 4y agoI remember a github repo like this from ages ago. How is the token used? I assume the token has a function that triggers an abort, but does that mean the downstream code has to constantly check the token, or does it simply generate a fault/exception at the lowest level that bubbles upstream? I'm not sure of the token mechanics.
- AgentME 4y agoIt works like your first guess, but it's not so bad. Downstream code has to either check the token occasionally, subscribe to an event from it, or just pass it forward to another function which uses the token. So if you were writing a function that just made a series of network requests, you would make it take a CancellationToken as a parameter, and then you would pass that parameter on to each of the network request function calls inside your function. Then if the token is in the aborted state while any of the network function calls are in-progress, then that network function call will throw an exception which will bubble up through your function, without your function needing to do anything special with the CancellationToken directly.
- saghm 4y agoMy team had to deal with something like this a couple years ago. Because of some external constraints on the implementation of our connection pool, we needed to emit events to a listener whenever a connection was returned to the pool, but we wanted to have the connection automatically checked back into the pool when dropped, and that required doing some async things. The "solution" we came up with was that checking the connection back in a short bit later was acceptable, so we just spawned an async task in the `Drop` implementation that would emit the event and check the connection back into the pool. Spawning an async task is fairly cheap, so the `drop` method would finish quickly, and the work needed to check the connection back in the pool was done in the background. The only tricky part was implementing the test suite, as part of the external constraint was that we had to verify our behavior with some tests expressed in an agnostic, declarative fashion which expected us to be able to assert that events happened in a deterministic order. In practice, adding a short yield to the runtime in the test harness between operations caused the async runtime to almost always return the connection to the pool with the spare time it had, and we reasoned that we could always increase the length of time the test executor yielded if we ended up having too many spurious failures.
- mastax 4y agoThis website is on the McAfee blocklist for some reason.
- StefanHamminga 4y agoAm I the only one who would want [language] tags for these kind of ambiguous titles? This is about Rust, for those who wondered.
- Akronymus 4y agoYou can actually do that on submissions, it just isn't a cultural default on HN yet.
- artemonster 4y agoWould the same be achieved with an algebraic effect? Static type system will enforce that „close“ is thrown and handled and thats it?
- bruce343434 4y agoCould you explain in non-academeze what an algebraic effect is and how it's the solution here? Genuine question since everything I read about algebraic effects is either impenetrable math notation or some article about how it's a resumable exception. It's almost analogous to monads apparently being wrapper types (but somehow different/with implications?).
- cute_boi 4y agoThanks, Sabrina for this wonderful article regarding async destructors. I think the Rust team committed a mistake by not considering Async destructors. I think they can use edition boundry to fix this issue. Let's see.