class alignas()

in cachelib/allocator/nvmcache/InFlightPuts.h [35:166]


class alignas(folly::hardware_destructive_interference_size) InFlightPuts {
  using LockGuard = std::lock_guard<std::mutex>;
  using UniqueLock = std::unique_lock<std::mutex>;

 public:
  class PutToken;
  // inserts an in-flight put into the map if none exists and acquires a
  // token. Caller can check if the token is valid to determine if they can
  // use it to complete the operation.
  PutToken tryAcquireToken(folly::StringPiece key) {
    UniqueLock l(mutex_, std::try_to_lock);
    if (!l.owns_lock()) {
      return PutToken{};
    }

    auto ret = keys_.emplace(key, true);
    // record for same key being inflight written to nvmcache should be rare.
    // In that case, fail the latter one.
    if (ret.second) {
      return PutToken{key, *this};
    }
    return PutToken{};
  }

  // marks the token as invalidated. This will ensure that we dont execute any
  // function on this token and simply remove the token when the token gets
  // destroyed.
  void invalidateToken(folly::StringPiece key) {
    LockGuard l(mutex_);
    auto it = keys_.find(key);
    if (it != keys_.end()) {
      it->second = false;
    }
  }

  // Represents an insertion into the inflight map. this token can be used to
  // execute some action if the token was not invalidated in the mean time.
  class PutToken {
   public:
    PutToken() noexcept {}
    ~PutToken() {
      if (puts_) {
        puts_->removeToken(key_);
      }
    }

    // disallow copying
    PutToken(const PutToken&) = delete;
    PutToken& operator=(const PutToken&) = delete;

    // moving is okay
    PutToken(PutToken&& other) noexcept : key_(other.key_), puts_(other.puts_) {
      other.reset();
    }

    PutToken& operator=(PutToken&& other) noexcept {
      if (this != &other) {
        this->~PutToken();
        new (this) PutToken(std::move(other));
      }
      return *this;
    }

    // returns true if the token was valid one upon construction. Does not
    // reflect if the token was invalidated after construction.
    bool isValid() const noexcept { return puts_ != nullptr; }

    // executes the fn if the token is valid and the there has been no
    // invalidation. destroys the token state accordingly.
    template <typename F>
    bool executeIfValid(F&& fn) {
      if (isValid() &&
          puts_->executeIfValid(key_, std::forward<decltype(fn)>(fn))) {
        // successfully executed, reset the token.
        reset();
        return true;
      }
      return false;
    }

   private:
    void reset() noexcept {
      puts_ = nullptr;
      key_.clear();
      XDCHECK(!isValid());
    }

    friend InFlightPuts;
    PutToken(folly::StringPiece key, InFlightPuts& puts)
        : key_(key), puts_(&puts) {}

    // key corresponding to the token
    folly::StringPiece key_{};

    // map holding the state
    InFlightPuts* puts_{nullptr};
  };

 private:
  // execute only if the token is present and was not invalidated.
  //  @param key the item key
  //  @param fn  function to execute
  //
  //  @return  true if the function was executed and token was destroyed
  //          appropriately
  //  @throw    if fn throws, token is preserved.
  template <typename F>
  bool executeIfValid(folly::StringPiece key, F&& fn) {
    LockGuard l(mutex_);
    auto it = keys_.find(key);
    const bool valid = it != keys_.end() && it->second;
    if (valid) {
      fn();
      keys_.erase(it);
      return true;
    }
    return false;
  }

  // erases the record from inflight map.
  void removeToken(folly::StringPiece key) {
    LockGuard l(mutex_);
    auto res = keys_.erase(key);
    XDCHECK_EQ(res, 1u);
  }

  // map storing the presence of a token  and its validity
  std::unordered_map<folly::StringPiece, bool, folly::Hash> keys_;

  // mutex protecting the map.
  std::mutex mutex_;
};