生产者消费者

#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <deque>
#include <objbase.h>
#define GUID_LEN 64

using namespace std;

static int kItemsToProduce = 1;
static bool g_go_on_push_flag = true;
static bool g_go_on_send_flag = true;

std::mutex stdoutMutex;//多线程标准输出 同步锁

struct FrameRepository
{
    deque<std::string> frame_queue;   // 这里用队列代表仓库缓冲区
    int MaxSize = 10;       // 仓库所容纳的产品最大个数
    std::mutex mtx;         // 互斥量,保护产品缓冲区
    std::condition_variable repository_notFull;     // 条件变量, 指产品仓库缓冲区不为满
    std::condition_variable repository_notEmpty;    // 条件变量, 指产品仓库缓冲区不为空
}gItemRepository;   // 产品库全局变量,生产者和消费者操作该变量.

typedef struct FrameRepository FrameRepository;


std::string generateUUID()
{
    char buffer[GUID_LEN] = { 0 };
    GUID guid;
    if (CoCreateGuid(&guid))
    {
        fprintf(stderr, "create guid error\n");
        return std::string();
    }
    _snprintf_s(buffer, sizeof(buffer),
        "%08X-%04X-%04x-%02X%02X-%02X%02X%02X%02X%02X%02X",
        guid.Data1, guid.Data2, guid.Data3,
        guid.Data4[0], guid.Data4[1], guid.Data4[2],
        guid.Data4[3], guid.Data4[4], guid.Data4[5],
        guid.Data4[6], guid.Data4[7]);
    return std::string(buffer);
}

// 生产 产品
void PushFrameItem(FrameRepository &itemRepo, std::string frame_info)
{
    std::unique_lock<std::mutex> lock(itemRepo.mtx);
    //while (itemRepo.itemQueue.size() >= itemRepo.MaxSize) // 判断当前仓库满了
    //{
    //    {
    //        std::lock_guard<std::mutex> lock(stdoutMutex);
    //        cout << "仓库满了,生产者等待中..." << "thread id = " << std::this_thread::get_id() << endl;
    //    }
    //    itemRepo.repository_notFull.wait(lock); // 等待信号量释放锁 生产者等待"仓库缓冲区不为满"这一条件发生(将会跳出循环).
    //}

    itemRepo.repository_notFull.wait(lock, [&itemRepo] {
        bool full = itemRepo.frame_queue.size() >= itemRepo.MaxSize;
        if (full) {
            std::lock_guard<std::mutex> lock(stdoutMutex);
            itemRepo.frame_queue.pop_front();

            if (itemRepo.frame_queue.size() < itemRepo.MaxSize)
                cout << "clear" << endl;
            cout << "仓库满了,生产者等待中..." << "thread id = " << std::this_thread::get_id() << endl;
        }
        return !full;
    });

    itemRepo.frame_queue.push_back(frame_info);         // 仓库放入产品
    itemRepo.repository_notEmpty.notify_all();  // 通知消费者仓库不为空
    lock.unlock();  // 释放锁
}

// 消费 产品
std::string SendFrameItem(FrameRepository &itemRepo)
{
    std::string frame_info;
    std::unique_lock<std::mutex> lock(itemRepo.mtx);
    //while (itemRepo.itemQueue.empty())  // 判断当前仓库空了,等待
    //{
    //    {
    //        std::lock_guard<std::mutex> lock(stdoutMutex);
    //        cout << "仓库空了,消费者等待中..." << "thread id = " << std::this_thread::get_id() << endl;
    //    }
    //    itemRepo.repository_notEmpty.wait(lock);// 消费者等待"仓库缓冲区不为空"这一条件发生.(等待信号跳出循环)
    //}

    // 等待信号不为空的通知,wait 第二参数为true时 向下执行,否则一直等待
    itemRepo.repository_notEmpty.wait(lock, [&itemRepo] {
        bool empty = itemRepo.frame_queue.empty();
        if (empty) {
            std::lock_guard<std::mutex> lock(stdoutMutex);
            cout << "仓库空了,消费者等待中..." << "thread id = " << std::this_thread::get_id() << endl;
        }
        return !empty;
    });

    frame_info = itemRepo.frame_queue.front();
    itemRepo.frame_queue.pop_front();
    itemRepo.repository_notFull.notify_all();
    lock.unlock();
    return frame_info;
}

// 生产者任务
void PushFrameTask()
{
    while (g_go_on_push_flag)
    {
        //std::this_thread::sleep_for(std::chrono::milliseconds(500));


        std::string uuid = generateUUID();
        if (uuid.empty())
            return;

        PushFrameItem(gItemRepository, uuid);    // 生产产品
        {
            std::lock_guard<std::mutex> lock(stdoutMutex);
            cout << "生产: " << kItemsToProduce << "    UUID:" << uuid << endl;
        }
        kItemsToProduce++;
    }
}

// 消费者任务
void SendFrameTask()
{
    static int consume_cnt = 0;
    while (true)
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(20));

        if (!g_go_on_send_flag)
            if (consume_cnt == kItemsToProduce)
                break;
        //this_thread::sleep_for(std::chrono::seconds(1));
        std::string item = SendFrameItem(gItemRepository);    // 消费产品
        {
            std::lock_guard<std::mutex> lock(stdoutMutex);
            cout << "消费: " << consume_cnt + 1 << "    UUID:" << item << endl;
        }
        consume_cnt++;
    }
}

int main()
{

    std::thread push(PushFrameTask);
    std::thread send(SendFrameTask);

    push.detach();
    send.detach();
    std::this_thread::sleep_for(std::chrono::seconds(20));
    g_go_on_push_flag = false;
    g_go_on_send_flag = false;
    system("pause");
    return 0;
}

 

posted @ 2018-09-15 18:03  O1dCat  阅读(104)  评论(0编辑  收藏  举报