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 に答える