Unless you are writing hard realtime systems where you can make use of the strict scheduling guarantees of SCHED_FIFO, signaling while holding the lock is never necessary nor sufficient for correctness. The waiter must be checking the condition in a loop anyway.
And if you unlock the mutex after signalling the condition, another thread can be still scheduled in between the call to notify() and whatever-notified-thread-which-starts-to-run (and can still invalidate whatever-conditions-it-can-invalidate). There is absolutely no guarantee whatsoever that notified-thread gets to your mutex first (not that it really should matter for correctness in any sane program BTW).
> I signal my condition variables with mutexes locked because it's easier to guarantee correctness that way.
There is no difference in guarantees in practice whether you notify within or after; I'm not even sure that there is any difference in theory (exactly because the thread-which-was-notified is not guaranteed to get mutex first).
On all significant platforms I know, condition wait works like this:
For each thread in the wait list, the condition variable "knows" which mutex it is holding. When signalling a waiting thread, it's added to the wait list of the mutex (if mutex is locked), not actually woken up.Did you have a platform in mind that works differently from this?
Additionally, when you unlock a mutex before signalling the condition, another thread may be scheduled in between that may invalidate the condition that was signalled. This may introduce a race condition.
I signal my condition variables with mutexes locked because it's easier to guarantee correctness that way.