Traditional semaphores are a bad pattern. While these actor-based semaphores don't have the defect of potential thread starvation, they still have the fundamental problem that there's absolutely no way to implement the API that doesn't lead to priority inversion. Swift is definitely missing some sort of low-level abstraction here for gating work on a condition, but I don't want to ever add an API that looks like this. Waiters need to know what tasks are currently responsible for unblocking them.