雙緩衝區實現


#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;
};

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章