В настоящее время я работаю над одним незакрепленным списком в C++ 11, и у меня проблема с моей функцией popFront()
. Или я должен хотя бы сказать, что знаю, что в некоторых случаях у него будут проблемы.Как предотвратить неопределенное поведение и проблему ABA в этой функции стека блокировки?
В любом случае, это то, что я в настоящее время:
std::shared_ptr<T> popFront(void)
{
auto p = atomic_load(&head);
while(p && !atomic_compare_exchange_weak(&head, &p, p->next))
{}
return p ? p->data : std::shared_ptr<T>();
}
Обратите внимание, что head
имеет тип shared_ptr
.
Однако, я предвижу несколько вопросов. Первым из них является ситуация, когда два потока выполняются popFront()
, они оба читают то же самое head
, и один поток заканчивается первым. Перед завершением второго потока вызывающий объект удаляет объект, на который указали, поэтому второй поток теперь работает с удаленной памятью. Вторая проблема - классическая проблема ABA.
Идея этого связанного списка состоит в том, чтобы он был заблокирован, поэтому я хочу избежать наложения блокировки внутри этой функции. К сожалению, я не уверен, как решить эти проблемы. Мы ценим любые предложения.
Вместо того, фиксируя этот код, [дон 't исправить этот код] (https://www.youtube.com/watch?v=CZ69OFLlBCk), напишите лучший код. Зачем вам это делать? Даже если вы исправите все это, он не будет работать лучше, чем простой замок, и он будет хрупким, трудно понятным и невозможным изменить. –
Достаточно честный. Есть две причины, почему я хотел бы это исправить: (1) Я хотел бы узнать, как изменить код для решения проблем, и (2) существующие реализации не включают необходимые мне возможности. – Mlagma
Затем используйте замок. Гораздо проще писать, понимать и поддерживать. В большинстве случаев он работает лучше. И вы действительно можете убедиться, что это правильно и не будет навсегда беспокоиться о том, что вы пропустили какой-то причудливый край, в котором он может потерпеть неудачу. –