我試圖想出一個解決以下問題的快速方法:這是線程間對象共享策略的聲音嗎?
我有一個線程產生數據,並有幾個線程使用它。我不需要對生成的數據進行排隊,因爲數據的生成速度比消耗的要慢得多(即使偶爾出現這種情況,如果偶爾跳過數據點也不會有問題)。所以,基本上,我有一個封裝了「最近狀態」的對象,它只允許生產者線程更新。
我的策略如下(請讓我知道如果我完全把我的搖桿):
我創建三類這個例子:Thing
(實際狀態對象),SharedObject<Thing>
(對象可以是每個線程本地的,並且可以讓該線程訪問底層的Thing)和SharedObjectManager<Thing>
,它包含shared_ptr
以及mutex
。
SharedObjectManager
(SOM)的實例是一個全局變量。 當製片人開始時,它實例化一個Thing,並告訴全局SOM。然後製作一份副本,並完成所有更新該副本的工作。當它準備提交對Thing的更改時,它會將新Thing傳遞給全局SOM,這會鎖定它的互斥鎖,更新它保留的共享指針,然後釋放該鎖。
同時,消費者線程全部內核化SharedObject<Thing>
。這些對象每個都保持一個指向全局SOM的指針,以及由SOM保存的shared_ptr
的緩存副本......它保持該緩存直到明確調用update()
。
我相信這是越來越難走,所以這裏的一些代碼:
#include <mutex>
#include <iostream>
#include <memory>
class Thing
{
private:
int _some_member = 10;
public:
int some_member() const { return _some_member; }
void some_member(int val) {_some_member = val; }
};
// one global instance
template<typename T>
class SharedObjectManager
{
private:
std::shared_ptr<T> objPtr;
std::mutex objLock;
public:
std::shared_ptr<T> get_sptr()
{
std::lock_guard<std::mutex> lck(objLock);
return objPtr;
}
void commit_new_object(std::shared_ptr<T> new_object)
{
std::lock_guard<std::mutex> lck (objLock);
objPtr = new_object;
}
};
// one instance per consumer thread.
template<typename T>
class SharedObject
{
private:
SharedObjectManager<T> * som;
std::shared_ptr<T> cache;
public:
SharedObject(SharedObjectManager<T> * backend) : som(backend)
{update();}
void update()
{
cache = som->get_sptr();
}
T & operator *()
{
return *cache;
}
T * operator->()
{
return cache.get();
}
};
// no actual threads in this test, just a quick sanity check.
SharedObjectManager<Thing> glbSOM;
int main(void)
{
glbSOM.commit_new_object(std::make_shared<Thing>());
SharedObject<Thing> myobj(&glbSOM);
std::cout<<myobj->some_member()<<std::endl;
// prints "10".
}
由生產者線程使用的理念是:
// initialization - on startup
auto firstStateObj = std::make_shared<Thing>();
glbSOM.commit_new_object(firstStateObj);
// main loop
while (1)
{
// invoke copy constructor to copy the current live Thing object
auto nextState = std::make_shared<Thing>(*(glbSOM.get_sptr()));
// do stuff to nextState, gradually filling out it's new value
// based on incoming data from other sources, etc.
...
// commit the changes to the shared memory location
glbSOM.commit_new_object(nextState);
}
受到消費者的使用將是:
SharedObject<Thing> thing(&glbSOM);
while(1)
{
// think about the data contained in thing, and act accordingly...
doStuffWith(thing->some_member());
// re-cache the thing
thing.update();
}
謝謝!
'std :: shared_ptr objPtr;'有我害怕在那裏有某個地方有另一方使用'* objPtr'沒有適當的保護。怕我不得不說。 –
user4581301
聽起來很複雜。取而代之的是在限制大小的生產者中使用一個隊列,只保存有效的(提交)對象並允許丟棄元素。這可能會更簡單(擺脫無用的經理)。 –