双缓冲区实现

来源:互联网 发布:用c语言打印出杨辉三角 编辑:程序博客网 时间:2024/06/05 19:10


#include <iostream>
#include <boost/thread.hpp>
#include <boost/interprocess/sync/interprocess_semaphore.hpp>

using namespace boost::interprocess;

const int size = 5;

struct Data_buff
{
    Data_buff()
        :putSemaphore(2), getSemaphore(0), getMutex(1)
    {
        put  = buf1;
        nput = buf2;
        get  = 0;
    }

    int buf1[size];
    int buf2[size];

    int *put;
    int *nput;
    int *get;

    interprocess_semaphore putSemaphore,    // 是否可以进行数据的添加
                           getSemaphore,    // 是否可以进行数据的读取
                           getMutex;        // 是否可以进行指针的更改
};

struct MutexBuf
{
    boost::mutex dataMutex;                  // 数据访问的互斥变量
    boost::condition_variable_any putCond;   // 是否可以进行数据添加,如果没有缓冲区则不能,添加完一个缓冲区的数据,但是read没有释放get
    boost::condition_variable_any getCond;   // 是否可以进行数据读取,如果get为0,则不能

    int buf1[size];
    int buf2[size];

    int *put;
    int *nput;
    int *get;

    MutexBuf()
    {
        put  = buf1;
        nput = buf2;
        get  = 0;
    }
};


const int total = 4*size;
int putcount = 0;
int getcount = 0;
Data_buff buf;
MutexBuf mutexBuf;

void MutexPut()
{
    while(true)
    {
        if (putcount >= total)
            return;
      
        for( int i = 0; i < size; ++i )
            mutexBuf.put[i] = putcount + i;

        putcount += size;

        {
            boost::mutex::scoped_lock lock(mutexBuf.dataMutex);
            // 如果表征不能在缓冲区中添加数据:添加完一个缓冲区中的数据,但是get没有释放掉,则不能添加
            while(mutexBuf.get)
                mutexBuf.putCond.wait(mutexBuf.dataMutex);

            mutexBuf.get = mutexBuf.put;
            mutexBuf.put = mutexBuf.nput;

            // 通知读者,可以进行数据的操作
            mutexBuf.getCond.notify_one();
        }
    }
}

void MutexRead()
{
    while(true)
    {
        if(getcount >= total)
            return;

        {
            boost::mutex::scoped_lock lock(mutexBuf.dataMutex);
            // 判断是否可以进行数据读
            while(!mutexBuf.get)
                mutexBuf.getCond.wait(mutexBuf.dataMutex);
        }

        std::cout << "addr = " << mutexBuf.get << "\n";
        for( int i = 0; i < size; ++i )
            std::cout << "value = " << mutexBuf.get[i] << ",";
        std::cout << "\n";
        getcount += size;

        {
            boost::mutex::scoped_lock lock(mutexBuf.dataMutex);
            // 释放get的读操作区域
            mutexBuf.nput = mutexBuf.get;
            mutexBuf.get  = 0;
            mutexBuf.putCond.notify_one();
        }
    }
}

void put()
{
    while(true)
    {
        if (putcount >= total)
            return;

        buf.putSemaphore.wait();

        for( int i = 0; i < size; ++i )
            buf.put[i] = putcount + i;
        putcount += size;

        // 判断get是否被read用了,如果用了才可以在重新设置
        buf.getMutex.wait();
        buf.get = buf.put;
        buf.put = buf.nput;

        // get可用,通知get
        buf.getSemaphore.post();
    }
}

void read()
{
    while(true)
    {
        if (getcount >= total)
            return;

        buf.getSemaphore.wait();

        std::cout << "addr = " << buf.get << "\n";
        for( int i = 0; i < size; ++i )
            std::cout << "value = " << buf.get[i] << ",";
        std::cout << "\n";

        getcount += size;

        buf.nput = buf.get;
        buf.getMutex.post();      // get被read用完,那么可以进行改写
        buf.putSemaphore.post();  // 可以进行数据的put
    }
}

int main(int argc, char *argv[])
{
    boost::thread_group gr;
    gr.create_thread(MutexPut);
    boost::this_thread::sleep(boost::posix_time::seconds(5));


    for( int i = 0 ; i < size; ++i )
    {
        std::cout << "buf1["<< i << "] = " << mutexBuf.buf1[i] << ",";
    }
    std::cout << "\n";

    for( int i = 0 ; i < size; ++i )
    {
        std::cout<< "buf2["<< i << "] = " << mutexBuf.buf2[i] << ",";
    }
    std::cout << "\n";

    boost::this_thread::sleep(boost::posix_time::seconds(5));

    gr.create_thread(MutexRead);


    gr.join_all();

    return 0;
};

原创粉丝点击