使用线程的多个缓冲区

时间:2015-02-23 16:34:35

标签: c++ multithreading unix system-calls thread-synchronization

我需要一些算法帮助我写一个多线程程序。它基本上是unix中的cp命令,但有一个读线程和一个写线程。我使用信号量进行线程同步。我有结构化缓冲区和线程数据定义为

struct bufType {
    char buf[BUFFER_SIZE];
    int numBytes;
};

struct threadData {
    int fd;
    bufType buf;
};

和bufType的全局数组。我的主要代码是

int main(int argc, const char * argv[])
{
    int in, out;
    pthread_t Producer, Consumer;
    threadData producerData, consumerData;

    if (argc != 3)
    {
        cout << "Error: incorrect number of params" << endl;
        exit(0);
    }
    if ((in = open(argv[1], O_RDONLY, 0666)) == -1)
    {
        cout << "Error: cannot open input file" << endl;
        exit(0);
    }
    if ((out = open(argv[2], O_WRONLY | O_CREAT, 0666)) == -1)
    {
        cout << "Cannot create output file" << endl;
        exit(0);
    }

    sem_init(&sem_empty, 0, NUM_BUFFERS);
    sem_init(&sem_full, 0, 0);

    pthread_create (&Producer, NULL, read_thread, (void *) &producerData);
    pthread_create (&Consumer, NULL, write_thread, (void *) &consumerData);

    pthread_join(Producer, NULL);
    pthread_join(Consumer, NULL);

    return 0;
}

并读写线程:

void *read_thread(void *data)
{
    threadData *thread_data;
    thread_data = (threadData *) data;

    while((thread_data->buf.numBytes = slow_read(thread_data->fd, thread_data->buf.buf, BUFFER_SIZE)) != 0)
    {
        sem_post(&sem_full);
        sem_wait(&sem_empty);
    }

    pthread_exit(0);
}

void *write_thread(void *data)
{
    threadData *thread_data;
    thread_data = (threadData *) data;

    sem_wait(&sem_full);
    slow_write(thread_data->fd, thread_data->buf.buf, thread_data->buf.numBytes);
    sem_post(&sem_empty);

    pthread_exit(0);
}

所以我的问题是在main中分配给我的threadData变量,在读写线程中分配我的信号量逻辑。感谢您提供的任何帮助

2 个答案:

答案 0 :(得分:0)

您可以使用公共缓冲池,圆形阵列或链接列表。这是一个Windows示例的zip链接,它类似于您所要求的,使用链接列表作为线程间消息传递系统的一部分来缓冲数据。除了创建互斥锁,信号量和写入线程之外,这些函数既小又简单。 mtcopy.zip

答案 1 :(得分:0)

作为一个不使用文件描述符的windows家伙,我可能错了in和out,但我认为这需要在你的main中完成才能设置threadData结构。

producerData.fd = in;
consumerData.fd = out;

然后为两个结构声明类型为bufType的ONE SINGLE对象。例如,将threadData的定义更改为

struct threadData {
    int fd;
    bufType* buf;
};

在您的主页中,您可以写

bufType buffer;
producerData.buf = &buffer;
consumerData.buf = &buffer;

然后两个线程将使用公共缓冲区。否则你将写入producerData缓冲区,但consumerData缓冲区将保持为空(这是你的编写器线程正在寻找数据的地方)

然后你需要改变你的信号逻辑。现在你的程序不能接受超过BUFFER_SIZE的输入,因为你的写线程只会写一次。需要围绕它循环。然后你需要一些机制来通知作者线程不再发送数据。例如,你可以这样做

void *read_thread(void *data)
{
    threadData *thread_data;
    thread_data = (threadData *) data;

    while((thread_data->buf->numBytes = slow_read(thread_data->fd, thread_data->buf->buf, BUFFER_SIZE)) > 0)
    {
        sem_post(&sem_full);
        sem_wait(&sem_empty);
    }
    sem_post(&sem_full); // Note that thread_data->buf->numBytes <= 0 now

    pthread_exit(0);
}

void *write_thread(void *data)
{
    threadData *thread_data;
    thread_data = (threadData *) data;


    sem_wait(&sem_full);
    while (thread_data->buf->numBytes > 0)
    {
        slow_write(thread_data->fd, thread_data->buf->buf, thread_data->buf->numBytes);
        sem_post(&sem_empty);
        sem_wait(&sem_full);
    }
    pthread_exit(0);
}

希望没有更多的错误,没有测试解决方案。但这个概念应该是你所要求的。