On the contrary, in my experience such stateful APIs are a great use case for state machines. You just approach them differently. Instead of doing a blocking call, you introduce a "waiting for <something>" state. You leave the "blocking" state when the correct event comes, or after a timeout. And while you are waiting for the event, you don't just burn CPU cycles, but yield control quickly, so that other threads can execute in the meantime.