buffers-C++高级编程之缓冲区管理
2023.06.20
来源:
浏览:18次
1、缓冲区 MyBuffer.h
MyBuffer类中演示了使用模板编程知识点、运用队列、锁、condition_variable(条件变量,来控制多线程的并发操作)技术来构建一个缓冲区。
#pragma once#ifndef MYBUFFER_H_#define MYBUFFER_H_#include <queue>#include <mutex>#include <memory>// 禁用拷贝构造和赋值操作符以及其移动语义#define OF_DISALLOW_COPY(ClassName) ClassName(const ClassName&) = delete; ClassName& operator=(const ClassName&) = delete#define OF_DISALLOW_MOVE(ClassName) ClassName(ClassName&&) = delete; ClassName& operator=(ClassName&&) = delete#define OF_DISALLOW_COPY_AND_MOVE(ClassName) OF_DISALLOW_COPY(ClassName); OF_DISALLOW_MOVE(ClassName)// 缓冲区的几种状态enum BufferStatus{ kBufferStatusSuccess = 0, kBufferStatusErrorClosed, kBufferStatusEmpty,};template<typename T>class MyBuffer final {public: // 禁用拷贝和移动语义 OF_DISALLOW_COPY_AND_MOVE(MyBuffer); MyBuffer(size_t max_len) :max_len_(max_len), is_closed_(false) {} ~MyBuffer() = default; /* * 向队列中添加内容 **/ BufferStatus Push(const T& item); /* * 获取队列中的内容 **/ BufferStatus Pull(T* item); BufferStatus TryReceive(T* item); // 关闭队列的操作 void Close(); private: std::queue<T> queue_; // 队列 mutable std::mutex mutex_; // mutex size_t max_len_; // 队列最大的个数 bool is_closed_; // 是否可以对队列进行操作 std::condition_variable cond_; // 条件变量,控制多线程并发};template<typename T>BufferStatus MyBuffer<T>::Push(const T& item) { // 加锁,锁住当前线程 std::unique_lock<std::mutex> lock(mutex_); // 判断lambda表达式是否为TRUE,为TRUE不阻塞,为FALSE阻塞 cond_.wait(lock, [this]() {return queue_.size() < max_len_ || is_closed_; }); // 如果表示已经不允许操作缓冲队列,则返回状态错误 if (is_closed_) { return kBufferStatusErrorClosed; } queue_.push(item); // 唤醒当前线程 // 解除阻塞当前正在等待此条件的线程之一。 // 如果没有线程在等待,则还函数不执行任何操作。如果超过一个,不会指定具体哪一线程。 cond_.notify_one(); return kBufferStatusSuccess;}template<typename T>BufferStatus MyBuffer<T>::Pull(T* item) { std::unique_lock<std::mutex> lock(mutex_); cond_.wait(lock, [this]() {return (!queue_.empty()) || is_closed_; }); if (queue_.empty()) { return kBufferStatusErrorClosed; } *item = queue_.front(); queue_.pop(); // 如果当前队列小于最大的队列长度,则唤醒所有的线程 if (queue_.size() < max_len_) { cond_.notify_all(); } return kBufferStatusSuccess;}template<typename T>BufferStatus MyBuffer<T>::TryReceive(T* item) { std::unique_lock<std::mutex> lock(mutex_); if (queue_.empty()) { return is_closed_ ? kBufferStatusErrorClosed : kBufferStatusEmpty; } *item = queue_.front(); queue_.pop(); if (queue_.size() < max_len_) { cond_.notify_all(); } return kBufferStatusSuccess;}template<typename T>void MyBuffer<T>::Close() { std::unique_lock<std::mutex> lock(mutex_); is_closed_ = true; cond_.notify_all();}#endif
2、缓冲区管理 BufferManager.h
BufferManager类演示如何对上述缓冲区进行管理,采用unordered_map容器来容纳穿冲区,通过给缓冲区起一个名字来索引到具体的缓冲区,使用unique_ptr指针来独占当前缓冲区。
#pragma once#include "MyBuffer.h"#include "Global.hpp"#include <unordered_map>#include <string>// 为unordered_map取别名为HashMaptemplate<typename Key,typename T,typename Hash = std::hash<Key>>using HashMap = std::unordered_map<Key, T, Hash>;// 缓冲区管理template<typename T>class BufferManager final {public: OF_DISALLOW_COPY_AND_MOVE(BufferManager); ~BufferManager() = default; // 创建一个新的缓冲区对象 void NewBuffer(const std::string& buffer_name, size_t buffer_size) { name2Buffer_.emplace(buffer_name, std::make_unique<MyBuffer<T>>(buffer_size)).second; } // 获取缓冲区的指针 MyBuffer<T>* Get(const std::string& buffer_name)const { const auto& iter = name2Buffer_.find(buffer_name); return iter->second.get(); }private: friend class Global<BufferManager>; BufferManager() = default; // 缓冲区管理对象 HashMap<std::string, std::unique_ptr<MyBuffer<T>>> name2Buffer_;};
3、单例 Global.h
工业级单例程序,用来创建一个单例。
#pragma once// 单例 工业级template<typename T>class Global final {public: // 获取单例对象 static T* Get() { return *GetPPtr(); } // 创建单例对象 template<typename... Args> static void New(Args&&... args) { assert(Get() == nullptr); *GetPPtr() = new T(std::forward<Args>(args)...); } // 删除单例对象 static void Delete() { if (Get() != nullptr) { delete Get(); *GetPPtr() = nullptr; //std::cout << "删除对象" << std::endl; } }private: static T** GetPPtr() { static T* ptr = nullptr; return &ptr; }};
4、测试类 job_instance.h
用来测试缓冲区的测试类。
#pragma once#include <string>// 测试类class JobInstance {public: JobInstance() = default; virtual ~JobInstance() = default; virtual std::string job_name()const { return "undefined"; }};class PyJobInstance : public JobInstance {public: using JobInstance::JobInstance; std::string job_name() const override { return "job_name"; }};
5、测试例子
测试例子,先构建一个缓冲区管理的单例,根据单例获取缓冲区管理的指针,用缓冲区管理的指针创建一个指定名称和大小的缓冲区。
创建一个测试类的对象,将测试类的对象放入缓冲区中。
通过名称来获取缓冲区的对象,将测试类的对象从缓冲区中拿出来。
关闭缓冲区。
删除单例。
#include "job_instance.h"#include "BufferManager.h"inline std::string GetSourceTickBufferName(const std::string& job_name) { static const std::string prefix = "SourceTick-"; return prefix + job_name;}void test_my_buffers(){ size_t nSize = 10; std::string name = "Account"; // 创建一个单例 Global<BufferManager<std::shared_ptr<JobInstance>>>::New(); // 获取单例的指针 auto* buffer_mgr = Global<BufferManager<std::shared_ptr<JobInstance>>>::Get(); // 用单例创建一个名称为Account,大小为nSize的缓冲队列 buffer_mgr->NewBuffer(GetSourceTickBufferName(name), nSize); // 创建一个对象 std::shared_ptr<JobInstance> cb(new PyJobInstance); // 将对象放入缓冲队列中 BufferStatus status1 = buffer_mgr->Get(GetSourceTickBufferName(name))->Push(cb); // 成功的话 if (status1 == kBufferStatusSuccess) { // 获取缓冲队列中的内容 std::shared_ptr<JobInstance> foreign_job_instance; BufferStatus status2 = buffer_mgr->Get(GetSourceTickBufferName(name))->TryReceive(&foreign_job_instance); // 从缓冲队列中获取数据成功,调用对象的方法进行输出信息 if (status2 == kBufferStatusSuccess) { std::cout << foreign_job_instance.get()->job_name() << std::endl; } } // 关闭缓冲 buffer_mgr->Get(GetSourceTickBufferName(name))->Close(); // 删除单例 Global<BufferManager<std::shared_ptr<JobInstance>>>::Delete();}int main() { test_my_buffers();}
6、总结
此例子演示了C++高级编程缓冲区管理示例,以及我们如何使用C++的一些高级特性,例如模板类、模板函数、unique_lock、unique_ptr、shared_ptr、锁、临界区、队列、unordered_map等相关知识点,希望这些知识点的综合运用能帮助到各位朋友。
Tags:
相关阅读
- 青岛保时捷销冠牟倩文!买车就给上!一年业绩170辆!360天全年无休!
- 许昌职业学院大二学妹许佳园上午陪学长上课 晚上陪学弟上床!堪称时间管理大师
- 【黑料】独家吃瓜爆料,江山市场监管局换妻事件!超级骚的母狗熟女人妻!
- 极品露出 大爷这鞋能修吗 多少钱 大姐闹市街边修鞋 边唠嗑边露出鲍鱼还紫薇
- 香港40岁辣妈“晒胸”成瘾,走遍公共场所拍120多张“裸照”,警方已拘捕
- 极品稀缺重磅 癖好特殊专攻TS大神【BJ大佬】私拍,记录各地9位顶级露脸TS美好性瞬间
- 山东真实母狗老师 林萌萌 白天为人师表的老师晚上是个精盆,只做内啡肽的忠诚信徒!
- 全网疯传 青岛奥斯卡酒吧 妹子当众给一个胖子口交 后被围观者制止
- 独家曝光!天津工程职粉技术学院造价18-3班王昕旭(已毕业)私密视频外泄(附生活照)
- 江苏响水城管局副局长苏阳与小学教师王海平偷情车震中毒死亡事件
- 某工程项目方经理请包工头吃饭,说只要你亲我女秘书的逼,这个工程就交给你做,还温馨提示刚刚内射了
- 高校情侣厕所门口当众啪啪视频遭全校疯传 洗手台上敞开腿给男子轻柔轻插
推荐阅读
-
青岛保时捷销冠牟倩文!买车就给上!一年业绩170辆!360天全年无休!
2015.12.16 -
许昌职业学院大二学妹许佳园上午陪学长上课 晚上陪学弟上床!堪称时间管理大师
2015.12.16 -
【黑料】独家吃瓜爆料,江山市场监管局换妻事件!超级骚的母狗熟女人妻!
2015.12.16 -
极品露出 大爷这鞋能修吗 多少钱 大姐闹市街边修鞋 边唠嗑边露出鲍鱼还紫薇
2015.12.16