4 ms·
Oh come on. I don't agree that the proposed idea is fundamentally new and amazing; but I think it is novel, and there may be some value in being able to semant
by wokwokwok 9y ago
Oh come on.
I don't agree that the proposed idea is fundamentally new and amazing; but I think it is novel, and there may be some value in being able to semantically bind tasks to execution points, specifically when the tasks are spawned in naive (or uncontrolled, eg. library) code, and have not explicitly opted in to the scheme.
Does this particular implementation do that perfectly? No, probably not.
...but I think the idea of it has some merit.
There's more value here than just waiting for a series of deferred tasks that you have explicitly created, and explicitly opted into a specific concurrency workflow with.
Note specifically these parts of the proposal:
> we declare that a parent task cannot start any child tasks unless it first creates a place for the children to live
^-- This is not satisfied by your method, at all.
> But the problem with this is that you have to know up front the complete list of tasks you're going to run, which isn't always true.
Literally the next sentence after the one you quoted.
> What if you really do need to write a function that spawns a background task, where the background task outlives the function itself? Easy: pass the function a nursery object. There's no rule that only the code directly inside the
Notice how you can avoid the 'setTimeout(() => { .. })` in nested code issue by explicitly passing in a context that has its own scope.
...
There's a lot of stuff in here that is actually quite thoughtful.
You don't have to dig through it, finding every little nitpick you can to call it out on; just think about the idea being proposed.
It's certainly not 'just promises'; if you think it is, then... I don't know what to say. You're wrong. :P
- joshuamorton 9y ago>and have not explicitly opted in to the scheme. I think you're overestimating nurseries here. They still don't handle the case you described of a deeply nested setTimeout: import asyncio import trio import threading async def my_tricky_function(): threading.Timer(5, lambda: print('first')).start() await trio.sleep(.5) async def a_function(): async with trio.open_nursery() as n: n.start_soon(my_tricky_function) print("finished") trio.run(a_function) (requires python 3.6, I'm using threading.timer in place of setTimeout, but they're the same construct). There's a great talk by david beazly about how threads and asyncio don't play nicely, except when they do. Note that you could imagine that this timer is created in an awaited function or a supposedly synchronous child function. If the nursery did what you think it did, which is to wait until everything async within the block completes, you'd see this print first, then print finished. It doesn't though, finished is printed first. The reason is that you need to opt in to the trio constructs by using promises/futures/coroutines. Using threaded callback based things give you the same problems with trio as they do in other async/parallel constructs. If you're a good citizen and opt in to the safety guarantees trio provides, it can keep things clean for you, yes. But you do need to explicitly opt into the scheme by only using code that you know is promise/future/coroutine based. Threads are a doozy. But the same thing is pretty much true with async/await promises/coroutines in js or python. If you require that you only use promises (or you tightly wrap all of your threads/callbacks in promises and then use that), you can get the safety of nurseries in most of the situations (I noted there were some exceptions before!), but with just the async/await syntax, no need for the extra async context manager. I agree that trio is cool. I've used it before. But you're ascribing to it and this construct magical powers that they cannot and do not have.
- wokwokwok 9y ago> they cannot and do not have. sigh~ In this implementation, or perhaps, in python at all... Does that make it completely valueless? I would venture to suggest that maybe there's a big wide world of languages that actually support controlling how threads are spawned, where it might not be. Maybe its worth considering.
- joshuamorton 9y agoOr perhaps at all. I agree that it's worth considering other ways of handling concurrency. But we should do so by staying within the realm of reality. Your understanding of nurseries, conceptually, does not match their capabilities. It's not about any language or implementation, it's that what you think they can do isn't possible. It violates the halting problem. You can't statically infer whether or not a function will have async side effects without opting into some scheme that describes those effects. If you do that, nurseries provide some guarantees. But those same guarantees are provided by just using async/await, which tracks explicitly which functions are async and which are not. Nurseries do potentially provide some advantages when dealing with tasks that you want to outlive their scope, which async/await doesn't handle well, and when dealing with an unbounded number of async calls (maybe, I think an `async for` construct handles it too). But otherwise, most of the advantages you seem to think nurseries provide aren't. And not just by this implementation, but by any implementation. They are provably not providable by any implementation that isn't equivalent to marking your async functions as async.
- wokwokwok 9y agoYou are simply not correct. If you can control how threads spawn, like C# thread contexts (for example the MVC context forces async resumes on the original thread rather than an arbitrary one), this is entirely plausible without an 'opt in' model.
- joshuamorton 9y ago>If you can control how threads spawn This is an opt in model. In general, it is not possible to know if an arbitrary thread will halt. That's the halting problem. You can restrict yourself and make sure that all threads 'return' on completion (promises, futures), or do various other things. But in an unrestricted system, it is provably impossible to know whether or not an arbitrary thread will halt.