我的程序中有一個緩存系統。我有一個單獨的靜態類來維護這個緩存,並且同時在多個線程中使用緩存。我遇到了正確維護緩存系統的問題。這裏是一些示例代碼。如何正確移動/從shared_ptr讀取
class db_cache
{
public:
typdef std::map<int, int> map_t;
static void update_cache();
static boost::shared_ptr< const map_t > get_cache();
private:
db_cache();
static void run_update();
static boost::shared_ptr< const map_t > cur_cache_;
static boost::shared_ptr< const map_t > old_cache_;
};
void db_cache::update_cache()
{
cur_cache_ = boost::make_shared<map_t>();
old_cache_ = boost::make_sahred<map_t>();
//
//Setup connection to server that sends updates
//
//Initialize cache
run_update();
while(true)
{
if(recv().compare("update") == 0)
{
//Update cache if update message recieved
run_update();
}
}
}
void db_cache::run_update()
{
//Create new cache to swap with current cache
auto new_cache = boost:make_shared<map_t>();
//
//Put data in new cache
//
boost::atomic_store(&old_cache_, boost::move(cur_cache_));
boost::atomic_store(&cur_cache_, boost::shared_ptr< const map_t >(boost::move(new_cache)));
}
auto db_cache::get_cache() -> boost::shared_ptr< const map_t >
{
return boost::atomic_load(&cur_cache_);
}
我目前在boost::atomic_store(&old_cache_, boost::move(cur_cache_));
發生崩潰。崩潰似乎是因爲old_cache_
爲空。這似乎在第二次收到更新消息時發生。我假設發生了什麼(不是100%肯定,但我能想到的只有一條路),是:
- 第一時間收到消息,
cur_cache_
被複制到old_cache_
。 cur_cache_
被替換爲new_cache
,導致舊的cur_cache_
(old_cache_
當前也指向的)爲空。old_cache_
因boost::atomic_store
由於爲空而再次被調用時會導致崩潰。
我的問題是,爲什麼boost::atomic_store(&old_cache_, boost::move(cur_cache_));
不會導致參考計數器cur_cache_
增加。我能做到這一點嗎?
其他說明:
我之所以old_cache_
是因爲我相信從緩存中,這是最有可能也是一個問題讀書時,我有一個問題。當我嘗試從get_cache()
返回的地圖中讀取元素時,我的程序似乎崩潰了,所以爲了確保它們保持在範圍內,直到所有當前有副本的線程都完成爲止,我保存最後一個版本的緩存。我想如果我有正確的方法來做到這一點,我可以擺脫old_cache_
一起,這應該解決上述問題。
編輯:
下面是使用緩存的代碼:
//Vector big, don't want to copy
const std::vector *selected_vec = &(*db_cache::get_cache()).at(get_string);
for(std::vector<std::string>::iterator it = selected_vec->begin(), e = selected_vec->end(); it != e; ++it)
{
//String can be big, don't want to copy
const std::string *cur_string = &(*it);
if(cur_string == nullptr || cur_string->size() == 0)
{
continue;
}
char a = cur_string->at(0); //Crash here
//Do Stuff
}
我的實際map_t
類型是std::map<std::string,std::vector<std::string>>
類型不是std::map<int,int>
。在調用get_cache()
後,我得到我想要的矢量,並在矢量上進行迭代。對於每個字符串,我嘗試獲取第一個字符。當我嘗試獲取字符時,程序崩潰。我唯一能想到的就是selected_vec
已被刪除。
大,謝謝你的'atomic_exchange'功能。至於第二部分,那原本就是我的,但我遇到了一個問題。我將用我的程序正在做的一些示例代碼更新原始帖子。我想我的問題是,是否有任何理由可以想到,在使用'cur_cache'的線程完成運行之前,緩存將被刪除。每次調用get_cache()時,我的'get_cache()'函數是否應該不增加'shared_ptr'的use_count? – Eumcoz 2015-02-24 14:14:29
@Eumcoz'get_cache'返回'shared_ptr'的一個副本,它*增加了'use_count'。客戶端代碼中的問題是,它會刪除'shared_ptr'的副本 - 在訪問'shared_ptr'指向的對象的內部之前,減少'use_count' - * *。 – Casey 2015-02-24 16:54:47
真棒,謝謝你的幫助,很有道理! – Eumcoz 2015-02-24 21:52:06