However, with inotify you also can't afford to perform a single read system call per event, because that will cause your "watch the filesystem" event to soak up most of the system's CPU time. So what you have to do is select to listen for "there's an event ready to be read", then sleep a little while, then read in the hope that many (but not too many!) events will have been queued that you can all read at once.
And at that point, you'll be getting a stale notification about a file or directory that may no longer even exist, or may have changed type. Consider: I create a file f, write data into it, rename it to g, then create a directory named f. You wake up 10 milliseconds later, and the first event you hear about is that a file named f was created.
This is all by way of saying that working with filesystem change notification interfaces is extremely subtle and tricky, enormously more so than you'd think on casual inspection. It's very easy to write a program that uses these interfaces in ways that will make it either generate garbage or consume huge amounts of CPU, and in fact the common case is to write a program that does both.