Я ищу что-то похожее на CopyOnWriteSet в Java, набор, который поддерживает add
, remove
и некоторый тип iterators
из нескольких потоков.Thread safe C++ std :: set, который поддерживает добавление, удаление и итераторы из многопоточных потоков
ответ
есть не один, что я знаю, ближайший находится в резьбовых строительных блоках, имеет concurrent_unordered_map
В STL контейнеры позволяют concurrent read access from multiple threads до тех пор, пока вы не не делать одновременное изменение. Часто не нужно итерации при добавлении/удалении.
Руководство по обеспечению простого класса обертки является нормальным, я бы начал с чего-то вроде фрагмента кода ниже, защищая методы, которым вам действительно нужен одновременный доступ, а затем предоставляя «небезопасный» доступ к базе std :: set так люди могут выбрать другие методы, которые небезопасны. При необходимости вы можете защитить доступ, а также к приобретению итераторов и возврату их, но это сложно (тем не менее, чем писать собственный набор блокировки или собственный полностью синхронизированный набор).
Я работаю на параллельной библиотеке шаблонов поэтому я использую CRITICAL_SECTION из VS2010 бета повышения :: мьютекс работает слишком большой и RAII модель использования lock_guard почти необходимо независимо от того, как вы решите сделать это:
template <class T>
class synchronized_set
{
//boost::mutex is good here too
critical_section cs;
public:
typedef set<T> std_set_type;
set<T> unsafe_set;
bool try_insert(...)
{
//boost has a lock_guard
lock_guard<critical_section> guard(cs);
}
};
Все, что я могу придумать, это использовать OpenMP для распараллеливания, вывести класс set из std и поместить оболочку вокруг каждой операции критического набора, которая объявляет эту операцию критической, используя #pragma omp критический.
Qt класс QSet использует неявный обмен данными (копирование на семантику записи) и аналогичные методы с помощью std :: set, вы можете посмотреть его реализацию, Qt - lgpl.
Вы также можете ознакомиться с библиотекой ACE, в которой есть все контейнеры, защищенные потоками, которые вам когда-либо понадобится.
Почему бы не использовать общий мьютекс для защиты одновременного доступа? Обязательно используйте RAII для блокировки и разблокировки мьютекса:
{
Mutex::Lock lock(mutex);
// std::set manipulation goes here
}
где Mutex :: Замок является классом, который блокирует мьютекс в конструкторе и отпирает его в деструкторе, и мьютекс объект мьютекса, который совместно по всем темам. Mutex - это только класс-оболочка, который скрывает любой конкретный примитив ОС, который вы используете.
Я всегда думал, что параллелизм и заданное поведение являются ортогональными понятиями, поэтому лучше иметь их в отдельных классах. По моему опыту, классы, которые пытаются быть потокобезопасными, не очень гибки или полезны.
Безопасность нитей и копирование на семантику написания - это не одно и то же. Это сказано ...
Если вы действительно используете семантику копирования на запись, то в библиотеках источников Adobe есть шаблон copy_on_write
, который добавляет эту семантику к тому, с чем вы его создаете.
Вам не нужна внутренняя блокировка, так как ваши инварианты часто требуют нескольких операций над структурой данных, а внутренняя блокировка предотвращает одновременное выполнение шагов, тогда как вам необходимо сохранить шаги от разных макроопераций от чередования.
Я не думаю, что вы должны выходить из std-контейнеров. У них нет виртуальных деструкторов. В этом случае композиция была бы лучше. –