Create ReadHolder::unlock
Summary: Currently you need to depend on the destructor of `ReadHolder` (using closures as in code block #1 below or empty assignment as in code block #2 below) to ensure that a `ReadHolder` goes out of scope (and unlocks) in order to subsequently acquire a write lock via `WriteHolder` without deadlocking. This diff introduces a way of unlocking a `ReadHolder` while it's still in scope such that a `WriteHolder` can be acquired. This makes the code more straight forward (reducing the risk of deadlock due to a programmer's misunderstanding of how `SharedMutex` / the holder framework works) => see code block # 3 below Also add some documentation about why `WriteHolder::WriteHolder(ReadHolder&&)` doesn't exist Code Block #1 : Use of closures ``` class foo { public: std::string getMemoizedData() { { folly::SharedMutex::ReadHolder readHolder(lock_); if (!data_.empty()) { // important to return by value, otherwise caller might access // data_ after we release the read lock return data_; } } { // try again with a write lock folly::SharedMutex::WriteHolder writeHolder(lock_); if (data_.empty()) { data_ = "my awesome string"; } return data_; } } private: folly::SharedMutex lock_; std::string data_; }; ``` Code Block #2 : Use of empty assignment ``` class foo { public: std::string getMemoizedData() { folly::SharedMutex::ReadHolder readHolder(lock_); if (!data_.empty()) { // important to return by value, otherwise caller might access // data_ after we release the read lock return data_; } readHolder = {}; // try again with a write lock folly::SharedMutex::WriteHolder writeHolder(lock_); if (data_.empty()) { data_ = "my awesome string"; } return data_; } private: folly::SharedMutex lock_; std::string data_; }; ``` Code Block #3 : Use of unlock() ``` class foo { public: std::string getMemoizedData() { folly::SharedMutex::ReadHolder readHolder(lock_); if (!data_.empty()) { // important to return by value, otherwise caller might access // data_ after we release the read lock return data_; } readHolder->unlock(); // try again with a write lock folly::SharedMutex::WriteHolder writeHolder(lock_); if (data_.empty()) { data_ = "my awesome string"; } return data_; } private: folly::SharedMutex lock_; std::string data_; }; ``` Reviewed By: yfeldblum Differential Revision: D3176025 fb-gh-sync-id: c7d47ca71df08673c7c1f1fd5ed9e01a663c1797 fbshipit-source-id: c7d47ca71df08673c7c1f1fd5ed9e01a663c1797
Showing
Please register or sign in to comment