Я думаю, что идея mcmcc была не слишком далека, но вместо универсального std :: swap (), который будет выполнять векторное копирование, вы должны иметь возможность использовать std :: vector :: swap ().Функционально векторная своп-функция работает аналогично универсальной, но она намного быстрее, поскольку просто обменивается несколькими переменными указателя / размера и фактически не делает копий элементов.Таким образом, ваша блокировка будет доступна только для нескольких инструкций по сборке.
Если это все еще слишком долго (в этот момент вы, возможно, захотите пересмотреть свой дизайн), другой альтернативой является создание кругового списка векторов, которые никогда не заменяются.друг с другом.Вместо этого есть другой указатель, который ссылается на «активный» вектор.Когда вам нужно изменить эту коллекцию, инициализируйте следующий вектор в круге, а когда инициализация будет завершена, обновите указатель.С этим решением нет никаких замков вообще.В одно мгновение ваши читатели используют один вектор, а в следующий момент они используют другой вектор.
Недостатком второго решения является то, что оно определенно потребует больше памяти, и это немного непредсказуемо.Я полагаю, вы могли бы объявить свой «активный» векторный указатель volatile , который заставлял бы ЦП синхронизировать кэш при каждом чтении значения указателя, в противном случае есть некоторый недетерминированный элемент, в котором может быть несколько ядер ЦП.глядя на разные снимки основной памяти.Кроме того, без какой-либо синхронизации, как вы гарантируете, что другие потоки выполняются с вектором, который собирается сдуться?И если вы делаете какую-либо синхронизацию, вы возвращаетесь к блокировке RW.
Хотя я думаю, что вы могли бы получить вторую альтернативу для работы и с некоторой относительно стабильной настройкой ... вероятно.Моим первым инстинктом было бы использовать RW lock и vector :: swap ().
UPDATE: На самом деле, я просто перечитал спецификации и, похоже, STL специализируется на глобальном std :: swap.специально для контейнеров, включая std :: vector.Таким образом, даже при вызове глобальной функции сложность равна O (1).Ответ mcmcc работает.
Итак, мы остановили это предположение, я просто написал немного кода и прошел через него с помощью отладчика.Вот мой код приложения:
std::vector< int > a, b;
for( int i = 0; i < 10; i++ )
{
a.push_back( i );
b.push_back( i * 10 );
}
std::swap( a, b );
и вот что находится внутри вызова глобальной универсальной версии std :: swap:
template<class _Ty,
class _Alloc> inline
void swap(vector<_Ty, _Alloc>& _Left, vector<_Ty, _Alloc>& _Right)
{ // swap _Left and _Right vectors
_Left.swap(_Right);
}
Как вы можете увидеть шаблон std :: swapФункция, которая в универсальном режиме выполняет функцию конструктора копирования, была специально предназначена для векторов.А внутри он просто делегирует всю работу std :: vector :: swap (), что, как мы установили, является более быстрым вариантом.