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
{
/// Имя объекта -> сообщение.
using Map = std::unordered_map<String, String>;
public:
/// 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::iterator it;
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
/// На время выполнения операции, сюда помещается элемент, и возвращается объект, который в деструкторе удаляет элемент.
/// В случае, если элемент уже есть - кидается исключение. См. class DDLGuard ниже.
using DDLGuards = std::unordered_map<String, std::unordered_map<String, String>>;
using DDLGuards = std::unordered_map<String, DDLGuard::Map>;
DDLGuards ddl_guards;
/// Если вы захватываете mutex и ddl_guards_mutex, то захватывать их нужно строго в этом порядке.
mutable std::mutex ddl_guards_mutex;