4 ms·
It would be possible to livelock the system but deadlocks are easier to avoid: don't use locks [1] at all in the runtime and don't expose them in the language.
by strmpnk 7y ago
It would be possible to livelock the system but deadlocks are easier to avoid: don't use locks [1] at all in the runtime and don't expose them in the language.
The longer answer of how the possibility of a deadlock in user code in Pony is prevented:
* messages are handled FIFO so w/o selective receive or multiple channels, there is no way to skip or wait for a specific message w/o doing work (_progress must be made by receivers_)
* combined with the last one, the sender can't wait for a response as it has to be sent as a FIFO message back (which can come interleaved with other messages; _progress must be made by senders_)
* multiple actors cannot simultaneously modify anything (you can't create a lock out of shared memory + Lamport's bakery algorithm because memory can't be r+w on two threads and even then, your exclusion failure would require explicit looping, so the thread is technically livelocked/starved)
What this results in is a system that always makes progress when more than one actor is involved.
Now that doesn't stop hanging the system (imagine putting N actors in infinite loops, one for each scheduler thread in the pony runtime, which we should call a livelock rather than a deadlock) and of course you could call some kind of C code via the FFI that decides it wants to take a lock or similar exclusive operation. Or there could be a bug in the runtime [2] which is tightly integrated with the language design and its guarantees so it avoids using locks for common things and uses atomic operations which provide a wait-free properties.
[1]: Pony uses atomic operations exclusively last time I looked. Relatively clever and there is room for bugs but theoretically this allows for wait-free progress in the runtime (there's a lot more to say here about theory vs practice but generally lock-free properties are enough here anyway).
[2]: I believe there have been edge cases in Pony's GC which might fall into the bug category but it's been awhile since I've used Pony myself so I can't comment on the current status.
- RantyDave 7y agoRegarding [1], I think there's pain to be had with memory barriers and such like unless one is very careful. In short, they're expensive.
- strmpnk 7y agoIt's definitely true, though likewise, it's expensive to use locks in such places too. The main idea with Pony's runtime is that contending for an actors attention will certainly incur costs but independent pairs of actors should not, even during GC. I also glossed over the I/O system and back pressure support which make the above discussion a bit more nuanced but my goal was to lay down some form of intuition around thinking in terms of progress in a system as a guarantee of the concurrency model. Empirically speaking, there are real limits to what hardware will hide and plenty of room for leveraging knowledge of the system as a whole (esp. the memory model) rather than sticking to one set of abstractions. Pony is no exception here, though the co-design of various features might make that less necessary than it might be in other systems with similar properties as it matures.