#pragma once #include #include #include #include #include #include #include #include namespace DB { class RWLockImpl; using RWLock = std::shared_ptr; /// Implements shared lock with FIFO service /// Can be acquired recursively (several calls from the same thread) in Read mode class RWLockImpl : public std::enable_shared_from_this { public: enum Type { Read, Write, }; static RWLock create() { return RWLock(new RWLockImpl); } /// Just use LockHandler::reset() to release the lock class LockHandlerImpl; friend class LockHandlerImpl; using LockHandler = std::shared_ptr; /// Waits in the queue and returns appropriate lock LockHandler getLock(Type type); private: RWLockImpl() = default; struct Group; using GroupsContainer = std::list; using ClientsContainer = std::list; using ThreadToHandler = std::map>; /// Group of clients that should be executed concurrently /// i.e. a group could contain several readers, but only one writer struct Group { // FIXME: there is only redundant |type| information inside |clients|. const Type type; ClientsContainer clients; std::condition_variable cv; /// all clients of the group wait group condvar explicit Group(Type type) : type{type} {} }; mutable std::mutex mutex; GroupsContainer queue; ThreadToHandler thread_to_handler; }; }