// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COBALT_SRC_LIB_UTIL_PROTECTED_FIELDS_H_
#define COBALT_SRC_LIB_UTIL_PROTECTED_FIELDS_H_

#include <mutex>
#include <shared_mutex>

// ProtectedFields is a useful abstraction for having a set of fields that are protected by a mutex.
// Using protected fields instead of a plain mutex has several advantages including:
//
//   1. The only way to access the protected fields is by locking the mutex, thereby ensuring that
//      any places that read/write to the fields are safe. (This increases confidence in code
//      correctness for the author, and reduces the burden on the code reviewer)
//   2. The mutex locks use RAII semantics, and as such the fields can be locked, accessed, and
//      re-locked in a single line.
//   3. The ProtectedFields can be locked mutably (using lock()) or immutably (using const_lock())
//      which allows reading protected fields in const functions (without needing to declare your
//      ProtectedFields as mutable.
//
// Simple example usage:
//
//  struct SafeField {
//    int protected_int;
//  };
//  ProtectedFields<SafeField> protected_fields;
//  protected_fields.lock()->protected_int = 100;
//  LOG(INFO) << "Current protected_int: " <<
//               protected_fields.const_lock()->protected_int;
//
// Example that holds the lock for multiple lines:
//
//  struct SafeFields {
//    int protected_int;
//    char protected_char;
//  };
//  ProtectedFields<SafeField> protected_fields;
//  auto fields = protected_fields.lock();
//  fields->protected_int = 100;
//  fields->protected_char = 'a';
//
// Example of taking locked fields as an argument:
//
//  struct SafeFields {
//    int protected_int;
//    char protected_char;
//  };
//  void SetFieldsLocked(ProtectedFields<SafeFields>::LockedFieldsPtr *fields) {
//   auto &f = *fields;
//   f->protected_int = 100;
//   f->protected_char = 'a';
//  }
//
// Example using RWProtectedFields:
//
//  RWProtectedFields<int> rw_protected_int(10);
//  auto reader_lock = rw_protected_int.const_lock();
//  std::thread([&rw_protected_int]() {
//    // This works, since any number of reader locks can be taken at once.
//    rw_protected_int.const_lock();
//  }).join();
//
// Example using LockedFieldsPtr with a condition variable:
//
//  struct SafeFields {
//    std::condition_variable_any shutdown_notifier;
//    bool shutdown;
//  }
//  ProtectedFields<SafeFields> protected_fields;
//  auto fields = protected_fields.lock();
//  // Wait until shutdown is true.
//  fields->shutdown_notifier.wait(fields, [&fields]() { return fields->shutdown; });

namespace cobalt::util {

// BaseProtectedFields is a template class and is specialized into ProtectedFields and
// RWProtectedFields. (See below).
//
// Template types:
// |Fields| can be any type, and is the object that will be protected.
// |Mutex| is any type that implements the *Mutex* named requirement. (See:
//         https://en.cppreference.com/w/cpp/named_req/Mutex)
// |ConstLock| is the lock type used for const_lock(). E.g. for ProtectedFields, it will be
//             std::unique_lock<std::mutex>, and for RWProtectedFields it will be
//             std::shared_lock<std::shared_mutex>.
template <class Fields, class Mutex, class ConstLock>
class BaseProtectedFields {
 public:
  // BaseLockedFieldsPtr holds a pointer to Fields, as well a
  // unique_lock<mutex>.
  //
  // Variables of this type are accessed using pointer syntax.
  //
  // Implements:
  // - *BasicLockable*: This allows ProtectedFields objects to be used as the lock value in the wait
  //                    methods of std::condition_variable_any. (See:
  //                    https://en.cppreference.com/w/cpp/named_req/BasicLockable)
  //
  //                    N.B. std::condition_variable may be more performant in some cases, and may
  //                    be preferred in performance critical situations. In those cases, raw
  //                    std::unique_lock<std::mutex> should be used.
  //
  // Template types:
  // |InnerFields| is either the same as Fields above, or in the case of a ConstLockedFieldsPtr, it
  //               is `const Fields`.
  // |LockType| The lock type to hold. (e.g. std::unique_lock<std::mutex>)
  template <class InnerFields, class LockType>
  class BaseLockedFieldsPtr {
   public:
    InnerFields* operator->() { return fields_; }
    InnerFields& operator*() { return *fields_; }

    // Blocks until a lock can be obtained for the current execution agent (thread, process, task).
    // If an exception is thrown, no lock is obtained. Additionally, after the lock is obtained, the
    // inner fields become available again.
    void lock() {
      lock_.lock();
      // Make the inner fields_ accessible again.
      std::swap(fields_, hidden_fields_);
    }

    // Releases the lock held by the execution agent. Throws no exceptions. Additionally, after the
    // lock is released, the inner fields are no longer accessible.
    //
    // Requires: The current execution agent should hold the lock.
    void unlock() {
      // Make the inner fields_ inaccessible. When the lock is not held, accessing the fields using
      // * or -> is undefined behavior.
      std::swap(fields_, hidden_fields_);
      lock_.unlock();
    }

   private:
    friend class BaseProtectedFields;
    BaseLockedFieldsPtr(Mutex* mutex, InnerFields* fields) : lock_(*mutex), fields_(fields) {}

    LockType lock_;
    InnerFields* fields_;
    InnerFields* hidden_fields_;

   public:
    // Disable copy/assign. Only allow move.
    BaseLockedFieldsPtr(BaseLockedFieldsPtr&&) noexcept = default;
    BaseLockedFieldsPtr& operator=(BaseLockedFieldsPtr&&) noexcept = default;
    BaseLockedFieldsPtr& operator=(const BaseLockedFieldsPtr&) = delete;
    BaseLockedFieldsPtr(const BaseLockedFieldsPtr&) = delete;
  };

  // Alias LockedFieldsPtrImpl for const and non-const variants.
  using LockedFieldsPtr = BaseLockedFieldsPtr<Fields, std::unique_lock<Mutex>>;
  using ConstLockedFieldsPtr = BaseLockedFieldsPtr<const Fields, ConstLock>;

  LockedFieldsPtr lock() { return LockedFieldsPtr(&mutex_, &fields_); }
  ConstLockedFieldsPtr const_lock() const { return ConstLockedFieldsPtr(&mutex_, &fields_); }

 private:
  mutable Mutex mutex_;
  Fields fields_;

 public:
  // Forward whatever arguments passed to BaseProtectedFields onto the constructor for Fields.
  template <class... Args>
  explicit BaseProtectedFields(Args&&... args) : fields_(std::forward<Args>(args)...) {}

  BaseProtectedFields& operator=(const BaseProtectedFields&) = delete;
  BaseProtectedFields(const BaseProtectedFields&) = delete;
  BaseProtectedFields() = default;

  // Make BaseProtectedFields Move constructible/assignable
  BaseProtectedFields& operator=(BaseProtectedFields&& other) noexcept {
    std::unique_lock<Mutex> lock(other.mutex_);
    fields_ = std::move(other.fields_);
    return *this;
  }
  BaseProtectedFields(BaseProtectedFields&& other) noexcept { *this = other; }
};

// The default implementation of ProtectedFields. Uses standard mutexes.
template <class Fields>
using ProtectedFields = BaseProtectedFields<Fields, std::mutex, std::unique_lock<std::mutex>>;

// A ProtectedFields implementation that supports Reader/Writer semantics. (const_lock is a reader
// lock, lock is a writer lock)
template <class Fields>
using RWProtectedFields =
    BaseProtectedFields<Fields, std::shared_mutex, std::shared_lock<std::shared_mutex>>;

}  // namespace cobalt::util

#endif  // COBALT_SRC_LIB_UTIL_PROTECTED_FIELDS_H_
