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