种族条件:更新结构可以返回一半的旧指针和一半的新指针
void ZMDAggregator::getMZMap(DataModel::MZMap &mZM)
{
LOGGER_EVENT("ZMDAggregator getMZMap()");
std::unique_lock<std::mutex> lockSlot(internalStateMutex);
mZM.clear();
mZM = this->mZM;
}
void ZMDAggregator::Roscallback(const ros::MZMap msgMZMap)
{
std::unique_lock<std::mutex> lockSlot(internalStateMutex);
MZMap map;
for( auto const & entry : msgMZMap.m_z_e)
{
mzEntry.clear();
mzEntry.mID = entry.mID;
mzEntry.tMode = entry.tMode;
mzEntry.areaID = entry.areaID;
mzEntry.oZone = entry.oZone;
mzEntry.authZ = entry.authZ;
mzEntry.blockZ = entry.blockZ;
map.mzEntry.push_back(mzEntry);
}
}
上述功能每秒被调用约30倍。这在我的程序中引起了较高的CPU利用率。
struct MZEntry
{
uint32_t mID;
bool tMode;
uint32_t areaID;
uint32_t oZone;
using ZList = std::vector<uint32_t>;
ZList authZ;
ZList blockZ;
};
struct MZMap
{
std::vector<MZEntry> mzEntry;
}
Class ZMDAggregator {
mutable std::mutex internalStateMutex;
MZMap mzMap;
}
我的问题是,我是否将getMzmap()
转换为接受共享_ptr而不是参考,并且还将成员变量的类型更改为mzmap
,如下所示。
void ZMDAggregator::getMZMap(std::shared_ptr<DataModel::MZMap> &mZM)
{
LOGGER_EVENT("ZMDAggregator getMZMap()");
std::unique_lock<std::mutex> lockSlot(internalStateMutex);
mZM = this->mZM;
}
Class ZMDAggregator {
mutable std::mutex internalStateMutex;
std::shared_ptr<DataModel::MZMap> mzMap;
}
我的问题如下。
我的类zmdaggregator
每50毫秒一次更新结构一次,因此每秒大约20倍,您可以看到这发生在unique_lock
中。 调用的线程,getMzmap()每秒将其调用约20倍。
通过将初始结构修改为shared_ptr
,我应该能够放下CPU周期,因为现在避免了结构副本。但是,现在由于在呼叫者线程中访问了相同的指针(读取器) 当功能roscallback
更新结构时,我的风险可能会得到一半旧的指针和一半的新指针。
如果不使用Mutex,(这两个功能是两个单独的类)是否可以确保上述方案不会出现?
根据@freakish的建议,我返回了shared_ptr。请在下面找到代码。
#include <iostream>
#include <memory>
#include <vector>
struct MZEntry
{
uint32_t mID;
bool tMode;
uint32_t areaID;
uint32_t oZone;
using ZList = std::vector<uint32_t>;
ZList authZ;
ZList blockZ;
};
struct MZMap
{
std::vector<MZEntry> mzEntry;
};
class A
{
public:
void populate()
{
std::cout << "A populate()" << std::endl;
MZEntry mzEntry;
mzEntry.mID = 55;
mzEntry.tMode = true;
mzEntry.areaID = 55;
mzEntry.oZone = 55;
mzEntry.authZ = {1,2,3};
mzEntry.blockZ = {4,5,6};
l->mzEntry.push_back(mzEntry);
}
std::shared_ptr<MZMap> assign() const
{
return l;
}
std::shared_ptr<MZMap> l;
A()
{
std::cout << "A constructor()" << std::endl;
l = std::make_shared<MZMap>();
populate();
}
};
class B
{
public:
B()
{
std::cout << "B constructor" << std::endl;
a = new A();
}
void getValue()
{
std::cout << "B getValue()" << std::endl;
p3 = a->assign();
}
void print()
{
std::cout << "machineID: " << p3->mzEntry[0].mID << std::endl;
}
std::shared_ptr<MZMap> p3;
A *a;
};
int main() {
B *b = new B();
b->getValue();
b->print();
return 0;
}
那么您在行中说的是
p3 = a->assign();
它不做结构副本,而只是增加了参考计数吗?我的理解正确吗?
void ZMDAggregator::getMZMap(DataModel::MZMap &mZM)
{
LOGGER_EVENT("ZMDAggregator getMZMap()");
std::unique_lock<std::mutex> lockSlot(internalStateMutex);
mZM.clear();
mZM = this->mZM;
}
void ZMDAggregator::Roscallback(const ros::MZMap msgMZMap)
{
std::unique_lock<std::mutex> lockSlot(internalStateMutex);
MZMap map;
for( auto const & entry : msgMZMap.m_z_e)
{
mzEntry.clear();
mzEntry.mID = entry.mID;
mzEntry.tMode = entry.tMode;
mzEntry.areaID = entry.areaID;
mzEntry.oZone = entry.oZone;
mzEntry.authZ = entry.authZ;
mzEntry.blockZ = entry.blockZ;
map.mzEntry.push_back(mzEntry);
}
}
The above function gets called around 30 times a second.This is causing a high cpu utilization in my program.
struct MZEntry
{
uint32_t mID;
bool tMode;
uint32_t areaID;
uint32_t oZone;
using ZList = std::vector<uint32_t>;
ZList authZ;
ZList blockZ;
};
struct MZMap
{
std::vector<MZEntry> mzEntry;
}
Class ZMDAggregator {
mutable std::mutex internalStateMutex;
MZMap mzMap;
}
My question is if I convert getMZMap()
to accept a shared_ptr instead of a reference and also change the type of the member variable mzMap
to a shared_ptr as shown below.
void ZMDAggregator::getMZMap(std::shared_ptr<DataModel::MZMap> &mZM)
{
LOGGER_EVENT("ZMDAggregator getMZMap()");
std::unique_lock<std::mutex> lockSlot(internalStateMutex);
mZM = this->mZM;
}
Class ZMDAggregator {
mutable std::mutex internalStateMutex;
std::shared_ptr<DataModel::MZMap> mzMap;
}
My question is as follows.
My class ZMDAggregator
updates the structure once every 50 milliseconds, so around 20 times a second As you can see this happens inside the unique_lock
.
The Thread that calls, getMZMap() calls it around 20 times a second.
By modifying initial structure to a shared_ptr
, I should be able to bring down CPU cycles, as a struct copy is now avoided. However now since the same pointer is being accessed in the caller thread (Reader)
there is a risk that I can get half an old pointer and half a new pointer when the function Roscallback
updates the structure.
Without using a mutex, (These two functions are two separate classes) is there a way to ensure that the above scenario doesn't occour ?
As per the suggestion of @freakish, I have returned shared_ptr by value. Please find the code below.
#include <iostream>
#include <memory>
#include <vector>
struct MZEntry
{
uint32_t mID;
bool tMode;
uint32_t areaID;
uint32_t oZone;
using ZList = std::vector<uint32_t>;
ZList authZ;
ZList blockZ;
};
struct MZMap
{
std::vector<MZEntry> mzEntry;
};
class A
{
public:
void populate()
{
std::cout << "A populate()" << std::endl;
MZEntry mzEntry;
mzEntry.mID = 55;
mzEntry.tMode = true;
mzEntry.areaID = 55;
mzEntry.oZone = 55;
mzEntry.authZ = {1,2,3};
mzEntry.blockZ = {4,5,6};
l->mzEntry.push_back(mzEntry);
}
std::shared_ptr<MZMap> assign() const
{
return l;
}
std::shared_ptr<MZMap> l;
A()
{
std::cout << "A constructor()" << std::endl;
l = std::make_shared<MZMap>();
populate();
}
};
class B
{
public:
B()
{
std::cout << "B constructor" << std::endl;
a = new A();
}
void getValue()
{
std::cout << "B getValue()" << std::endl;
p3 = a->assign();
}
void print()
{
std::cout << "machineID: " << p3->mzEntry[0].mID << std::endl;
}
std::shared_ptr<MZMap> p3;
A *a;
};
int main() {
B *b = new B();
b->getValue();
b->print();
return 0;
}
So what you are saying is in the line
p3 = a->assign();
It doesn't do a struct copy, instead it just increments the reference count? Is my understanding correct?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论