2013-05-25 4 views
3

Я искал параллельный ассоциативный контейнер, и я нашел concurrent_unordered_map от Thead Building Blocks, который, кажется, подходит всем моим потребностям. Несмотря на то, что я прочитал документацию, я не нашел ни одного примера о том, как работает стирание.удаление из параллельного ассоциативного контейнера (concurrent_unordered_map)

A concurrent_unordered_map supports concurrent insertion and traversal, but not concurrent erasure. The interface has no visible locking. It may hold locks internally, but never while calling user-defined code. It has semantics similar to the C++11 std::unordered_map except as follows: 

Что это значит? Можно ли стереть с этой карты, пока я делаю это только из одного потока? Если нет, как я могу это сделать?

+0

(http://msdn.microsoft.com/en-us/library/vstudio/hh750089.aspx) – BoBTFish

+0

Цитата [Для ленивых.]: «Методы стирания начинаются с unsafe_, чтобы указать, что они не являются безопасными для параллелизма ». Это имеет место как для реализации TBB, так и для ms. –

+0

@ ZamfirKerlukson Я думаю, что искатель понимает, что эти методы небезопасны, но не понимают, как их следует использовать таким образом, чтобы сделать их безопасными. И, глядя на документацию, я не уверен сам. Я думаю, вы просто не можете этого сделать, пока какой-либо другой поток может выполнять какую-либо операцию (безопасно или иначе) с контейнером. то есть только тогда, когда ни одна другая нить не использует его. Который кажется глупым, поскольку вы должны ввести замок вокруг использования в любом случае, не так ли? Я полагаю, что эти контейнеры эффективны, если вам не нужны небезопасные операции в течение параллельной фазы вашей программы. – BoBTFish

ответ

4

proposal for standardization of concurrent maps объясняет, почему в параллельных контейнерах нет erase. (Искать раздел «Почему параллельное стирание не поддерживается».)

Контейнеры в стандартной библиотеке C++ несут ответственность за удаление их содержимого. Содержимое «находится» в контейнере, подобно тому, как элемент находится в «массиве». operator[] возвращает ссылку на содержащийся объект и после возврата ссылки контейнер не знает, как долго запрашивающий поток «зависает» по ссылке. Поэтому, если другой поток приходит с просьбой о стирании элемента, контейнер не имеет понятия, безопасен ли элемент для удаления.

Я пытался думать о чем-то вы могли бы работать вокруг ограничения, но объяснение проблемы стирания вызывает еще больший вопрос: это всегда абонентов ответственности за защиту одновременного доступа к элементы, хранящиеся на карте.

Например: предположим, что у вас есть одновременное отображение из int в float и вы это делаете:

thread A     thread B 
the_map[99] = 0.0; 
        ... 
the_map[99] = 1.0;   if (the_map[99] == 1.0) ... // data race!!! 

Причиной этого является гонка данных, что даже если выражение the_map[99] защищена, она возвращает ссылка, доступ к которой не защищен. Так как обращения к ссылке не защищены, в память, на которую ссылаются эта точка, разрешено только чтение. (Или вам нужно заблокировать все обращения к этой памяти).

Вот мере дорогая альтернатива я могу думать (и это действительно дорого):

typedef concurrent_unordered_map<MyKey_t, atomic<MyMapped_t*> > MyContainer_t; 

Теперь, глядя вверх пункт означает:

MyMapped_t* x = the_map[a_key].load(); 

вставив элемент :

the_map[a_key].store(ptr_to_new_value); 

удаление элемента является:

the_map[a_key].store(0); 

и тестирование ли элемент на самом деле в карте есть:

if (the_map[a_key].load() != 0) ... 

Наконец, если вы собираетесь делать какие-либо условного стирания (или модификации) имеет чтобы быть что-то более сложным, чем: (. выше неправильно, потому что он страдает от the ABA problem)

MyMapped_t* x; 
do { 
    x = the_map[a_key].load(); 
} while (condition_for_erasing(x) && !the_map[a_key].compare_exchange_strong(x, 0)); 

Несмотря на это: это по-прежнему не защищает вас от одновременных изменений в базовом MyMapped_t и требует, чтобы вы выполняли всю конструкцию, управление хранением и уничтожение MyMapped_t.

:(
+0

Это было замечательно! Спасибо! – TheBlackTiger

Смежные вопросы