今天在项目中遇到了一个新的优化方案,算记录个人成长吧
代码大概如下:
// 实现通用库定义函数
//后面的类很多都是继承自这些虚基类
/*
* @brief 设备操作回调接口
*/
class IDeviceOperCB
{
public:
/*! IDeviceOperCB::OnReadResult
* @brief 读回调数据
* @param nHandle 操作句柄,确定任务唯一性 主动操作返回非0值,代码内部自动添加返回默认值0
* @param nErrCode 操作结果 0 表示成功 其他为错误码
* @param pBuff 数据地址
* @param nLen 数据长度
* @return 成功返回0
*/
virtual int onReadData(int nHandle, int nErrCode, char* pBuff, long nLen) = 0;
......
};
/*
* @brief 设备操作接口
*/
class IDeviceOper
{
public:
/*! IDeviceOper::setCallback
* @brief 操作回调接口
*/
virtual bool setCallback(IDeviceOperCB *pCB) = 0;
......
};
/*
* @brief 设备接口
*/
class IDevice
{
public:
/*! IDevice::open
* @brief 打开设备
* @param szAddr 设备地址连接字符串
* @return 成功返回0,失败返回错误码
*/
virtual int open(const char* szAddr) = 0;
};
//实现类CDevConnBE.h
//优化前代码
#include <vector>
using std::vector;
#include <deque>
class IDevice;
class IDeviceOper;
class IDeviceOperCB;
namespace std { class mutex; }
class CDevOperCallback;
class CDevConnBE
{
...
public:
/*! CDevConnBE::pushData
* @brief 写入数据
* @param data 传入数据
*/
void pushData(vector<unsigned char> &data);
private:
IDevice* m_pDevice; // 设备接口
CDevOperCallback* m_pDevOperCB; // 用于实现函数回调的类
std::deque<vector<unsigned char> > m_qDevData;
std::mutex* m_pMutex;
}
//实现类CDevConnBE.cpp
#include "CDevConnBE.h"
#include "devimpif.h" //最上面那个通用库定义文件名称
#include <mutex>
#include <string>
class CDevOperCallback :public GCSoft::IDeviceOperCB
{
public:
CDevOperCallback(CDevConnBE *DevConnBE) { m_pDevConnBE = DevConnBE; }
public:
virtual int onReadData(int nHandle, int nErrCode, char* pBuff, long nLen)
{
std::string data = string(pBuff,nLen); // 此处进行了第一次拷贝
vector<unsigned char> vData;
vData.assign(data.begin(), data.end()); // 第二次拷贝
m_pDevConnBE->pushData(vData); // 进行了第三次拷贝
return 0;
}
virtual int onWriteData(int nHandle, int nErrCode) { return 0; }
private:
CDevConnBE *m_pDevConnBE;
};
//CDevConnBE的类实现
CDevConnBE::CDevConnBE(const string& sConnInfo)
: m_pDevice(0)
, m_pDevOperCB(NULL)
, m_pDevOper(NULL)
, m_pMutex(0)
{
m_pMutex = new std::mutex;
....
start();
}
void CDevConnBE::start()
{
if (NULL != m_pDevice){ // 构造函数中进行了赋值实现
m_pDevOper = m_pDevice->devOper();
m_pDevOperCB = new CDevOperCallback(this);
m_pDevOper->setCallback(m_pDevOperCB);
m_pDevice->open(m_sConnInfo.c_str());// 使用连接信息Open
}
}
void CDevConnBE::pushData(vector<unsigned char> &data)
{
std::lock_guard<std::mutex> iLocker(*m_pMutex);
if (data.size() > 0) {
m_qDevData.push_back(data); // 第四次拷贝
}
}
负责与CDevConnBE模块实现对接的子模块
CSerialDevice .h
class CSerialDevice : public IDevice
{
public:
CSerialDevice(void);
~CSerialDevice(void);
public:
virtual int open(const char* szAddr); // 继承接口,负责打开设备(串口)
....
};
CSerialOper .h
class CSerialOper : public IDeviceOper
{
public:
CSerialOper(CSerialDevice *device);
~CSerialOper();
public:
/*! CDeviceOper::EventCallback
* @brief 注册异步事件回调
*/
virtual bool setCallback(IDeviceOperCB *pCB);
....
private:
IDeviceOperCB *m_pCB; // 事件回调接口
....
};
CSerialOper .cpp
....
bool CSerialOper::setCallback(IDeviceOperCB *pCB)
{
if (m_pCB != NULL)
return false;
m_pCB = pCB;
return true;
}
int CSerialOper::performRead(unsigned int size)
{
...
m_pCB->onReadData(m_iHandle, FAILCODE, (char*)reMSG.c_str(), reMSG.size()); // 此处进行调用,使数据回调到CDevConnBE的CDevOperCallback ,使onReadData被触发
...
}
....
上面代码是工作写的代码,下面的优化代码是导师给我提醒的,说拷贝太多的话,数据量一多代码效率会变得很低。算工作中的成长吧.
CDevConnBE 优化代码
CDevConnBE.h
class CDevConnBE
{
public:
CDevConnBE(const string& sConnInfo);
~CDevConnBE();
public:
/*! CDevConnBE::pushData
* @brief 写入数据
* @param data 传入数据
*/
void pushData(vector<unsigned char>&& data); // 使用右值引用
....
};
CDevConnBE.cpp
#include "CDevConnBE.h"
#include "devimpif.h" //最上面那个通用库定义文件名称
#include <mutex>
#include <string>
class CDevOperCallback :public GCSoft::IDeviceOperCB
{
public:
CDevOperCallback(CDevConnBE *DevConnBE) { m_pDevConnBE = DevConnBE; }
public:
virtual int onReadData(int nHandle, int nErrCode, char* pBuff, long nLen)
{
// 拷贝次数会大大减少
vector<unsigned char> vData;
vData.insert(vData.end(), pBuff, pBuff + nLen);
m_pDevConnBE->pushData(std::move(vData));
return 0;
}
virtual int onWriteData(int nHandle, int nErrCode) { return 0; }
private:
CDevConnBE *m_pDevConnBE;
};
//CDevConnBE的类实现
void CDevConnBE::CDevConnBE(const string& sConnInfo)
: m_pDevice(0)
, m_pDevOperCB(NULL)
, m_pDevOper(NULL)
, m_pMutex(0)
{
m_pMutex = new std::mutex;
....
start();
}
void CDevConnBE::start()
{
if (NULL != m_pDevice){ // 构造函数中进行了赋值实现
m_pDevOper = m_pDevice->devOper();
m_pDevOperCB = new CDevOperCallback(this);
m_pDevOper->setCallback(m_pDevOperCB);
m_pDevice->open(m_sConnInfo.c_str());// 使用连接信息Open
}
}
void CDevConnBE::pushData(vector<unsigned char> &data)
{
std::lock_guard<std::mutex> iLocker(*m_pMutex);
if (data.size() > 0) {
m_qDevData.push_back(std::move(data)); // 使用move代替拷贝
}
}
大概就是这样,懒得细化了。大概的简化示例就是这样了。