Использование pthread_setspecific и pthread_getspecific для хранения указателя на экземпляр std :: map - PullRequest
1 голос
/ 03 июня 2009

Я использую карту в качестве отдельного кеша для отслеживания неудачных поисков 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

1 Ответ

2 голосов
/ 03 июня 2009

Когда ваш тестовый код вызывает 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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...