Просто напишите функции синхронизации, которые делают именно то, что вы хотите. Ничего встроенного в этом нет, но написать очень просто.
Один из подходов - иметь главную таблицу ожидания, защищенную собственным мьютексом. Для ожидания вы выделяете новую переменную условия и новый объект ожидания. Вы заполняете объект ожидания тем, что ожидаете, и новой переменной условия. Вы получаете мьютекс главной таблицы ожидания, добавляете свой объект в главную таблицу ожидания и блокируете собственную переменную условия. Чтобы сигнализировать, вы изменяете любые предикаты, приобретаете мьютекс в главной таблице ожидания, смотрите, для каких потоков выполняются их условия, и сигнализируете каждую из своих выделенных переменных условия.
При пробуждении вам придется приобретать отдельные мьютексы и перепроверять отдельные предикаты. Это не будет сделано автоматически.
Но, скорее всего, правильное решение - изменить дизайн. Наиболее логичный редизайн - Почему один поток ожидает двух разных условий? Если есть две вещи, которые могут произойти, и две разные вещи, которые необходимо сделать, когда они происходят, почему один поток делает обе вещи?
Как правило, лучшее изменение дизайна - это не заставлять потоки ждать такого рода вещей. Вместо этого, когда работа должна быть выполнена, попросите поток, который обнаружил условие, которое означает, что работа должна быть выполнена, добавить рабочий элемент в очередь. Затем рабочие потоки могут ожидать размещения заданий в этой очереди. Если есть два различных условия, которые необходимо обработать, есть два задания, которые могут быть выполнены любым потоком.