Too many incompatible platform-specific APIs: epoll and AIO on Linux, kqueue on BSD and OSX, IOCP and new thread pool API on Windows. I’m pretty sure I forgot couple others, and each of them have non-trivial amount of quirks, bugs, and performance-ruining edge cases. Also these APIs are not directly compatible to each other.
To be usable, async IO needs to be integrated into the rest of IO. You can’t just place that on top, e.g. Java did that, IMO didn’t work particularly well.
The combination of the above makes creating good cross-platform abstraction for async IO challenging.
Not saying impossible, but it’s very hard to do.
I’ve tried once in C++, for that project I needed epoll and iocp, but I wasn’t able within reasonable time. Ended up swapping relatively large IO-related parts of my app depending on platform.