История изменений
Исправление red75prim, (текущая версия) :
Итого: нужен атомарный лок сразу нескольких объектов из коллекции, рекурсивные локи коллекции должны быть запрещены.
Стандартными средствами этого не сделать. Да и эти требования больше напоминают работу с базой данных, а не примитив синхронизации. Можно так и сделать: Мutex<(Vec<UnsafeCell<Item>>, LockedAreasList)>
, проверять есть ли запрошенный диапазон в списке залоченных, если есть, то добавлять thread::current() в список потоков, которые проснутся при разблокировании этого (или охватывающего, или пересекающегося диапазона), делать thread::park() и ждать.
Но производительность скорее всего будет хреновая. И из-за локов, которые не особо быстрые, и из-за поиска в базе залоченных диапазонов, и из-за возможного false sharing у разных потоков, работающих над соседними чанками.
По-моему, будет быстрее и проще использовать два массива: предыдущее состояние (только чтение) и новое состояние (только запись). Делим новое состояние на куски, раздаём нескольким потокам и они обновляют свои части без всякой синхронизации.
Исправление red75prim, :
Итого: нужен атомарный лок сразу нескольких объектов из коллекции, рекурсивные локи коллекции должны быть запрещены.
Стандартными средствами этого не сделать. Да и эти требования больше напоминают работу с базой данных, а не примитив синхронизации. Можно так и сделать: Мutex<(Vec<UnsafeCell<Item>>, LockedAreasList)>
, проверять есть ли запрошенный диапазон в списке залоченных, если есть, то добавлять thread::current() в список потоков, которые проснутся при разблокировании этого (или охватывающего, или пересекающегося диапазона), делать thread::park() и ждать.
Но производительность скорее всего будет хреновая. И из-за локов, которые не особо быстрые, и из-за возможного false sharing у разных потоков, работающих над соседними чанками.
По-моему, будет быстрее и проще использовать два массива: предыдущее состояние (только чтение) и новое состояние (только запись). Делим новое состояние на куски, раздаём нескольким потокам и они обновляют свои части без всякой синхронизации.
Исправление red75prim, :
Итого: нужен атомарный лок сразу нескольких объектов из коллекции, рекурсивные локи коллекции должны быть запрещены.
Стандартными средствами этого не сделать. Да и эти требования больше напоминают работу с базой данных, а не примитив синхронизации. Можно так и сделать: Мutex<(Vec<UnsafeCell<Item>>, LockedAreasList)>
, проверять есть ли запрошенный диапазон в списке залоченных, если есть, то добавлять thread::current() в список потоков, которые проснутся при разблокировании этого (или охватывающего диапазона), делать thread::park() и ждать.
Но производительность скорее всего будет хреновая. И из-за локов, которые не особо быстрые, и из-за возможного false sharing у разных потоков, работающих над соседними чанками.
По-моему, будет быстрее и проще использовать два массива: предыдущее состояние (только чтение) и новое состояние (только запись). Делим новое состояние на куски, раздаём нескольким потокам и они обновляют свои части без всякой синхронизации.
Исходная версия red75prim, :
Итого: нужен атомарный лок сразу нескольких объектов из коллекции, рекурсивные локи коллекции должны быть запрещены.
Стандартными средствами этого не сделать. Да и эти требования больше напоминают работу с базой данных, а не примитив синхронизации. Можно так и сделать: Мutex<(Vec<UnsafeCell<Item>>, LockedAreasList)>
, проверять есть-ли запрошенный диапазон в списке залоченных, если есть, то добавлять thread::current() в список потоков, которые проснутся при разблокировании этого (или охватывающего диапазона), делать thread::park() и ждать.
Но производительность скорее всего будет хреновая. И из-за локов, которые не особо быстрые, и из-за возможного false sharing у разных потоков, работающих над соседними чанками.
По-моему, будет быстрее и проще использовать два массива: предыдущее состояние (только чтение) и новое состояние (только запись). Делим новое состояние на куски, раздаём нескольким потокам и они обновляют свои части без всякой синхронизации.