Skip to content

Commit

Permalink
[RFC] Implement c10::Synchronized<T>, a basic error-avoiding synchron…
Browse files Browse the repository at this point in the history
…ization wrapper for data (pytorch#73407)

Summary:
Pull Request resolved: pytorch#73407

After adding mutex/lock in a previous change, I realized that `folly::Synchronized<T>` exists for this reason. However, we can't use it, so I have implemented a basic version for use in `c10` in this change.

Reviewers, please check if this looks reasonable as a minimal first step to enforce that data that is supposed to be used in a multi-threaded context ends up being locked before use. i.e. don't rely on the developer to do the right thing, instead enforce it using this abstraction.
ghstack-source-id: 150327548

Test Plan: See the next diff in this stack for the text plan.

Reviewed By: pavithranrao

Differential Revision: D34465420

fbshipit-source-id: 76c921e9b78ff2dfc82a0bfc83ffc8fb232e2f21
(cherry picked from commit 5882fe2)
  • Loading branch information
dhruvbird authored and pytorchmergebot committed Mar 2, 2022
1 parent 74fe570 commit 154f0ac
Showing 1 changed file with 61 additions and 0 deletions.
61 changes: 61 additions & 0 deletions c10/util/Synchronized.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#pragma once

#include <mutex>

namespace c10 {

/**
* A very simple Synchronization class for error-free use of data
* in a multi-threaded context. See folly/docs/Synchronized.md for
* the inspiration of this class.
*
* Full URL:
* https://github.com/facebook/folly/blob/main/folly/docs/Synchronized.md
*
* This class implements a small subset of the generic functionality
* implemented by folly:Synchronized<T>. Specifically, only withLock<T>
* is implemeted here since it's the smallest possible API that is
* able to cover a large surface area of functionality offered by
* folly::Synchronized<T>.
*/
template <typename T>
class Synchronized final {
mutable std::mutex mutex_;
T data_;

public:
Synchronized() = default;
Synchronized(T const& data) : data_(data) {}
Synchronized(T&& data) : data_(data) {}

// Don't permit copy construction, move, assignment, or
// move assignment, since the underlying std::mutex
// isn't necessarily copyable/moveable.
Synchronized(Synchronized const&) = delete;
Synchronized(Synchronized&&) = delete;
Synchronized operator=(Synchronized const&) = delete;
Synchronized operator=(Synchronized&&) = delete;

/**
* To use, call withLock<T> with a callback that accepts T either
* by copy or by reference. Use the protected variable in the
* provided callback safely.
*/
template <typename CB>
void withLock(CB cb) {
std::lock_guard<std::mutex> guard(this->mutex_);
cb(this->data_);
}

/**
* To use, call withLock<T> with a callback that accepts T either
* by copy or by const reference. Use the protected variable in
* the provided callback safely.
*/
template <typename CB>
void withLock(CB cb) const {
std::lock_guard<std::mutex> guard(this->mutex_);
cb(this->data_);
}
};
} // end namespace c10

0 comments on commit 154f0ac

Please sign in to comment.