Независимо от того, можно ли использовать STD :: Atomic для контроля доступа к структуре данных таким образом?C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Независимо от того, можно ли использовать STD :: Atomic для контроля доступа к структуре данных таким образом?

Сообщение Anonymous »

Я играю с бесклассовым программированием C ++, и я придумал метод безопасного (?) Передача собственности на непревзойденную структуру данных (безопасная.std::unordered_map в моем тривиальном примере) из потока производителя в потребительский поток, используя только общую std :: atomic для синхронизации. Похоже, что это должно быть безопасным, но интуиция, как известно, ненадежна в программировании без блокировки, поэтому я ищу любые причины, почему этот подход может быть не безопасен на практике. итерации над содержимым возвращенного std :: unoromeded_map . Это может сделать это безопасно, потому что возвращаемый std :: unoromeded_map (_consumerThreadUpdatesTable) доступен только для потребительского потока; Поток производителя никогда не касается его._producerThreadUpdatesTable), а затем он может вызвать продюсерупюпдиатстоконсосуммер () , чтобы попытаться переместить содержимое своей частной таблицы в таблицу общего доступа (_bridgeUpdatesTable). Поток продюсера также вызывает продюсерпсупдиатстоконсосуммер () периодически, на случай, если предыдущий вызов не смог успешно продвинуть обновления. std :: atomic . Если эта переменная верна, то только только потребительский поток может получить доступ к _bridgeupdateStable , или если эта переменная является ложной, то только поток производителя может получить доступ к _bridgeupdatable .
Причина (я думаю), что это должно быть потоком, что каждая нить будет только относиться к _bridgeupdate-stempate-stemptable
#include
#include

// This object lets us safely transport sets of key-value pair updates from a single ProducerThread to a single ConsumerThread without requiring any Mutex locking
class KeyedParameterBridge
{
public:
KeyedParameterBridge() : _consumerOwnsBridgeUpdatesTable(false)
{
// empty
}

/** Called by the producer thread; places a pending update into the producer-thread's local pending-update-table. */
void ProducerPutUpdate(int parameterID, float parameterValue) {_producerThreadUpdatesTable[parameterID] = parameterValue;}

/** Called by the producer thread; attempts to push all of the updates currently placed (via ProducerPutUpdate()) to
* the _bridgeUpdatesTable where the consumer thread will be able to access them
* @returns true if we were able to push some updates in this call, or false if didn't push any updates
*/
bool ProducerPushUpdatesToConsumer()
{
if (_producerThreadUpdatesTable.size() == 0) return false; // no updates to push
if (_consumerOwnsBridgeUpdatesTable.load()) return false; // can't safely do anything yet; we'll have to wait until the ConsumerThread consumes _bridgeUpdatesTable's current contents

_bridgeUpdatesTable = std::move(_producerThreadUpdatesTable); // O(1) pointer-move from _producerThreadUpdatesTable to _bridgeUpdatesTable
_consumerOwnsBridgeUpdatesTable = true; // so the ConsumerThread will know the _bridgeUpdatesTable is safe for him to access now
_producerThreadUpdatesTable.clear(); // make sure our producer-side table is in a known-empty state
return true;
}

/** Called periodically by the consumer thread; returns any available updates for the consumer thread to apply to its local data structure */
const std::unordered_map & ConsumerConsumeUpdates()
{
_consumerThreadUpdatesTable.clear(); // make sure our consumer-side table is in a known-empty state

if (_consumerOwnsBridgeUpdatesTable.load()) // see if we have access
{
_consumerThreadUpdatesTable = std::move(_bridgeUpdatesTable); // O(1) pointer-move from _bridgeUpdatesTable to _consumerThreadUpdatesTable
_consumerOwnsBridgeUpdatesTable = false; // so the ProducerThread will know we already grabbed the update and he can push again now
}
return _consumerThreadUpdatesTable;
}

private:
std::atomic _consumerOwnsBridgeUpdatesTable; // true iff the _bridgeUpdatesTable currently contains data for the consumer thread to consume

std::unordered_map _producerThreadUpdatesTable; // populated by the producer-thread, never accessed by the consumer thread
std::unordered_map _bridgeUpdatesTable; // access to this table is governed by the state of (_consumerOwnsBridgeUpdatesTable)
std::unordered_map _consumerThreadUpdatesTable; // read by the consumer-thread, never accessed by the producer thread
};


Подробнее здесь: https://stackoverflow.com/questions/797 ... -structure
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»