Семафор - это примитив синхронизации потоков, который позволяет войти в заданный участок кода не более чем n потокам (это определение дал выдающийся ученый Эдсгер Дейкстра).
Обычно семафор нужен для того, чтобы ограничить доступ к некоторому ресурсу, заданным количеством потоков приложения (ресурсом может быть например внешнее устройство, или некий сетевой ресурс).
В некоторых случаях, может иметь значение порядок доступа потоков к ресурсу. Стандартный класс Semaphore никак не гарантирует порядок, в котором заблокированные потоки будут получать доступ к ресурсу (входить в заданный участок).
Например, за каждым потоком может скрываться пользователь, который ожидает доступа к ресурсу. Если использовать стандартный класс Semaphore, то доступ к освобождающемуся ресурсу будет получать случайный пользователь, не зависимо от того как давно он ожидает.
Для решения этой задачи, мною был написан класс FifoSemaphore, который реализует политику FIFO (английское First In First Out - первым пришел, первым ушел) по отношению к ожидающим потокам - поток который вызвал функцию Wait первым, должен получить доступ к ресурсу первым. При необходимости, его можно легко модифицировать так, чтобы он работал по принципу LIFO (Last In First Out).
Краткое описание класса
Интерфейс класса аналогичен стандартному классу, за исключением одного нюанса - он не наследует стандартный класс WaitHandle, и соответственно не реализует его свойства и методы (которые специфичны для Windows). Как следствие этот класс не получится использовать в вызове WaitAny.
Конструкторы
FifoSemaphore()
Создает объект.
FifoSemaphore(int _InitialCount)
Создает объект и инициализирует начальное значение счетчика ресурсов - N;
int Release(int _ReleaseCount)
Выходит из семафора заданное количество раз (освобождает заданное количество ресурсов), возвращает предыдущее значение счетчика ресурсов;
int Release()
Выходит из семафора 1 раз, возвращает предыдущее значение счетчика ресурсов;
bool Wait(int _MillisecondsTimeout)
Входит в семафор. Ожидает освобождения ресурса заданное время в миллисекундах. Если ресурс не был освобожден в указанный период времение, возвращает значение false, иначе - true.
void Close()
Закрывает семафор и освобождает ресурсы. После этого вызова использовать семафор более не допустимо.
P.S.
Создание примитивов синхронизации иногда кажется простым, но в реальности возможны нетривиальные ситуации которые довольно сложно предвидеть.
Вполне допускаю, что в данном коде тоже есть ошибки, буду очень рад, если на них укажете.
Загрузить проект с реализацией и тестом: FifoSemaphore.zip (7,85 kb)