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