对于小型线程池(等于物理内核的数量),我需要一个非常简单的多读取器/单写入器队列实现。现在我用条件变量实现了它,但是我正在为未来的版本探索更轻的替代品。我结束了这样的事情(C伪代码):
#define QUEUE_MAXSIZE 16
struct queue {
OS_WAIT_OBJECT writer_waitobj;
OS_WAIT_OBJECT reader_waitobj;
size_t head;
size_t tail;
int data[QUEUE_MAXSIZE];
};
/* Called by a single writer. */
void enqueue(struct queue* queue, int value)
{
/* If queue is full wait to avoid overwriting. */
while (queue->head - queue->tail == QUEUE_MAXSIZE) {
OS_WAIT(queue->writer_waitobj);
}
/* There are a single writer so synchronization isn't necessary. */
queue->data[queue->head] = value;
queue->head++;
/* If queue was empty, signal the new state to one reader. */
if (queue->head == queue->tail) {
OS_AWAKE_ONE(queue->reader_waitobj);
}
}
/* Called by (few) multiple readers. */
int dequeue(struct queue* queue)
{
int value;
const size_t my_tail = tail;
/* If queue is empty readers must wait. */
while (queue->head == my_tail) {
OS_WAIT(queue->reader_waitobj)
}
/* Spin-lock readers synchronization. */
do {
value = queue->data[my_tail];
} while (!CPU_COMPARE_AND_SWAP(queue->tail, my_tail, my_tail+1));
/* If queue was full, signal the new state to writer. */
if (queue->head - my_tail == QUEUE_MAXSIZE) {
OS_AWAKE_ONE(queue->writer_waitobj);
}
return value;
}
此实施是否正确?故障在哪里?什么轻量级等待信号/唤醒信号设施提供主操作系统(Linux,BSD,OS X,Windows)?
修改
OS_WAIT_OBJECT
不会被强制为条件变量。这是一个简单的“睡觉,直到调度程序唤醒你,因为其他人发送了信号”。