If you need debouncing it means your pushbutton are connected to an interrupt. And interrupts should be exclusively for inter-ic communications to prevent issues. So you'd need extra hardware, which costs money and board space. Instead of that, reading a key is done every 20 ms. Which is plenty for user-interacted-actuators. Measure the down-time of the key, in x*20ms, and you can do some filtering on press times.
A single event is a press-and-release with 2 to 15 times 20ms.
A hold event is more than 20 * 20ms. Which is used to increment values automatically. The event is fired repeatedly.
Depending on the application usage of the key, a long hold event may be enabled, with a down-time of several seconds.
This all can be run from either a single thread, interrupt routine, or call from super-loop. With a for-loop and a settings struct, so the "module" is usable in ALL future projects with similar hardware.
A human does not need sub-milliseconds interaction with hardware, so attaching buttons to interrupts is useless. ( except for wake-up purposes )