1

我使用映射作为特定于线程的缓存来跟踪失败的 LDAP 搜索。我使用 pthread_setspecific 动态分配映射并存储指针。在检查缓存或增加失败计数时,我使用 pthred_getspecific 来检索 void* 指针和 static_cast 将指针返回到我的映射类型。使用 [] 运算符调用地图似乎不会影响地图的状态,并且对 map->size() 的调用总是返回 0。感觉我可能错误地使用了 pthread_getspecific 但从我的示例中看着我的代码看起来不错。

代码:

typedef std::map<std::string, int>  FailedSearchCacheMap;

/**
 * Create the keyserver failed search cache key. Only called 
 * internally and may only be called once per thread.
 */
static void
sCreateKeyserverFailedSearchCache(void)
{
    // Create the key used in refrencing the cache.  
    // sFreeKeyserverFailedSearch called against the pointer when the thread exits
    pthread_key_create(&sFailedSearchCacheKey, sFreeFailedSearchCache);
}

/**
 * Get the keyserver failed search cache (also create one if it doesn't exist)
 */
static FailedSearchCacheMap *
sGetKeyserverFailedSearch(void)
{
    // Initializes the failed search cache key.  
    // pthread_once guarantees that the create key routine is only called once
    static pthread_once_t sKeyserverFailedSearchOnce = PTHREAD_ONCE_INIT;
    pthread_once(&sKeyserverFailedSearchOnce, sCreateKeyserverFailedSearchCache);

    FailedSearchCacheMap* cache = static_cast<FailedSearchCacheMap *>(pthread_getspecific(sFailedSearchCacheKey));
    if (IsNull(cache))
    {
        cache = new FailedSearchCacheMap();
        pthread_setspecific(sFailedSearchCacheKey, cache);
    }

    return cache;
}

测试代码:

FailedSearchCacheMap* map_ptr1 = sGetKeyserverFailedSearch();
FailedSearchCacheMap* map_ptr2 = sGetKeyserverFailedSearch();

std::string ks("hostname");
FailedSearchCacheMap map1 = *map_ptr1;
FailedSearchCacheMap map2 = *map_ptr2;

int numFailedSearches = map1[ks] + 1;
map1[ks] = numFailedSearches;

std::cout << "numFailedSearches: "  << numFailedSearches << std::endl;

std::cout << "map_ptr1 address: "   << map_ptr1 << std::endl;
std::cout << "map_ptr2 address: "   << map_ptr2 << std::endl;

std::cout << "map_ptr1->size(): "   << map_ptr1->size() << std::endl;
std::cout << "map_ptr2->size(): "   << map_ptr2->size() << std::endl;

std::cout << "map1.size(): "        << map1.size() << std::endl;
std::cout << "map2.size(): "        << map2.size() << std::endl;

FailedSearchCacheMap::iterator i = map1.begin();
for(; i != map1.end(); i++)
    std::cout << (*i).first << ":" << (*i).second << std::endl;

测试代码输出:

numFailedSearches: 1
map_ptr1 address: 0x909ce88
map_ptr2 address: 0x909ce88
map_ptr1->size(): 0
map_ptr2->size(): 0
map1.size(): 1
map2.size(): 0
hostname:1
4

1 回答 1

2

当您的测试代码调用 sGetKeyserverFailedSearch() 时,它会将指针分配给本地地图变量,从而制作地图内容的副本。您对这些变量所做的任何更改都不会反映在您使用 pthread_setspecific() 存储的原始映射中,正如您的日志记录所表明的那样(map1 的大小增加了但 map_ptr1 的大小没有增加)。您想要对原始地图进行的任何修改都必须使用 sGetKeyserverFailedSearch() 返回的指针来完成,例如:

FailedSearchCacheMap* map_ptr = sGetKeyserverFailedSearch();
std::string ks("hostname");

int numFailedSearches = (*map_ptr)[ks] + 1;
(*map_ptr)[ks] = numFailedSearches;

std::cout << "numFailedSearches: " << numFailedSearches << std::endl;
std::cout << "map_ptr address: " << map_ptr << std::endl;
std::cout << "map_ptr->size(): " << map_ptr->size() << std::endl;

FailedSearchCacheMap::iterator i = map_ptr->begin();
for(; i != map_ptr->end(); i++)
    std::cout << (*i).first << ":" << (*i).second << std::endl;
于 2009-06-03T01:00:22.490 回答