Merge pull request #497 from yandex/fix-invalidated-iterator-usage

fix usage of possibly invalidated iterator [#CLICKHOUSE-2]
This commit is contained in:
alexey-milovidov 2017-02-15 23:47:37 +04:00 committed by GitHub
commit 272b88183c
2 changed files with 11 additions and 10 deletions

View File

@ -320,21 +320,22 @@ private:
}; };
/** Кладёт элемент в map, в деструкторе - удаляет. /// Puts an element into the map, erases it in the destructor.
* Если элемент уже есть - кидает исключение. /// If the element already exists in the map, throws an exception containing provided message.
*/
class DDLGuard class DDLGuard
{ {
/// Имя объекта -> сообщение. public:
using Map = std::unordered_map<String, String>; /// Element name -> message.
/// NOTE: using std::map here (and not std::unordered_map) to avoid iterator invalidation on insertion.
using Map = std::map<String, String>;
DDLGuard(Map & map_, std::mutex & mutex_, std::unique_lock<std::mutex> && lock, const String & elem, const String & message);
~DDLGuard();
private:
Map & map; Map & map;
Map::iterator it; Map::iterator it;
std::mutex & mutex; std::mutex & mutex;
public:
DDLGuard(Map & map_, std::mutex & mutex_, std::unique_lock<std::mutex> && lock, const String & elem, const String & message);
~DDLGuard();
}; };
} }

View File

@ -140,7 +140,7 @@ struct ContextShared
/// database -> table -> exception_message /// database -> table -> exception_message
/// На время выполнения операции, сюда помещается элемент, и возвращается объект, который в деструкторе удаляет элемент. /// На время выполнения операции, сюда помещается элемент, и возвращается объект, который в деструкторе удаляет элемент.
/// В случае, если элемент уже есть - кидается исключение. См. class DDLGuard ниже. /// В случае, если элемент уже есть - кидается исключение. См. class DDLGuard ниже.
using DDLGuards = std::unordered_map<String, std::unordered_map<String, String>>; using DDLGuards = std::unordered_map<String, DDLGuard::Map>;
DDLGuards ddl_guards; DDLGuards ddl_guards;
/// Если вы захватываете mutex и ddl_guards_mutex, то захватывать их нужно строго в этом порядке. /// Если вы захватываете mutex и ddl_guards_mutex, то захватывать их нужно строго в этом порядке.
mutable std::mutex ddl_guards_mutex; mutable std::mutex ddl_guards_mutex;