This is, in fact, basically what a Queue or StreamBuffer does. The Queue code has some complications in that it allows multiple tasks to be waiting for data from the Queue (which StreamBuffers omit, allowing them to be a bit more efficient).
Yes, you can perhaps make yourself slightly more efficient knowing the exact use case for the buffer, but the Stream Buffers themselves are fairly efficient.
The one advantage of the “roll your own” method is that, if you don’t put a task notify in the ISR, you can put it above the SYSCALL limit so it isn’t blocked by a critical section, then it can software signal a lower priority ISR to send the notification if needed.