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

// Safe Observer/Observable implementation.
//
// When using ObserverListThreadSafe, we were running into issues since there
// was no synchronization between getting the existing value, and registering
// as an observer. See go/cast-platform-design-synchronized-value for more
// details.
//
// To fix this issue, and to make observing values safer and simpler in general,
// use the Observable/Observer pattern in this file. When you have a value that
// other code wants to observe (ie, get the value of and receive any changes),
// wrap that value in an Observable<T>. The value type T must be copyable and
// copy-assignable. The Observable must be constructed with the initial observed
// value, and the value may be updated at any time from any thread by calling
// SetValue(). You can also get the value using GetValue(); but note that this
// is not threadsafe (the value is returned without locking), so the caller must
// ensure safety by other means. Calling GetValueThreadSafe() is threadsafe but
// involves a mutex lock.
//
// Code that wants to observe the value calls Observe() on it at any point when
// the value is alive. Note that Observe() may be called safely from any thread.
// Observe() returns an Observer<T> instance, which MUST be used and destroyed
// only on the thread that called Observe(). The Observer initially contains the
// value that the Observable had when Observe() was called, and that value will
// be updated asynchronously whenever the Observable's SetValue() method is
// is called. NOTE: the initial value of the Observer is the value known to the
// thread that created the Observer at the time; there may be an updated value
// from the Observable that hasn't been handled by the Observer's thread yet.
//
// The Observer's view of the observed value is returned by GetValue(); this is
// a low-cost call since there is no locking (the value is updated on the thread
// that constructed the Observer). Note that Observers are always updated
// asynchronously with PostTask(), even if they belong to the same thread that
// calls SetValue(). All Observers on the same thread have the same consistent
// view of the observed value.
//
// Observers may be copied freely; the copy also observes the original
// Observable, and belongs to the thread that created the copy. Copying is safe
// even when the original Observable has been destroyed.
//
// Code may register a callback that is called whenever an Observer's value is
// updated, by calling SetOnUpdateCallback(). If you get an Observer by calling
// Observe() and then immediately call SetOnUpdateCallback() to register a
// a callback, you are guaranteed to get every value of the Observable starting
// from when you called Observe() - you get the initial value by calling
// GetValue() on the returned Observer, and any subsequent updates will trigger
// the callback so you can call GetValue() to get the new value. You will not
// receive any extra callbacks (exactly one callback per value update).
//
// Note that Observers are not default-constructible, since there is no way to
// construct it in a default state. In cases where you need to instantiate an
// Observer after your constructor, you can use a std::unique_ptr<Observer>
// instead, and initialize it when needed.
//
// Example usage:
//
// class MediaManager {
//  public:
//   MediaManager() : volume_(0.0f) {}
//
//   Observer<float> ObserveVolume() { return volume_.Observe(); }
//
//   // ... other methods ...
//
//  private:
//   // Assume this is called from some other internal code when the volume is
//   // updated.
//   void OnUpdateVolume(float new_volume) {
//     volume_.SetValue(new_volume);  // All observers will get the new value.
//   }
//
//   Observable<float> volume_;
// }
//
// class VolumeFeedbackManager {
//  public:
//   VolumeFeedbackManager(MediaManager* media_manager)
//       : volume_observer_(media_manager->ObserveVolume()) {
//     volume_observer_.SetOnUpdateCallback(
//         base::BindRepeating(&VolumeFeedbackManager::OnVolumeChanged,
//                             base::Unretained(this)));
//   }
//
//  private:
//   void OnVolumeChanged() {
//     ShowVolumeFeedback(volume_observer_.GetValue());
//   }
//
//   void ShowVolumeFeedback(float volume) {
//     // ... some implementation ...
//   }
// };
//

#ifndef CHROMECAST_BASE_OBSERVER_H_
#define CHROMECAST_BASE_OBSERVER_H_

#include <stddef.h>
#include <stdint.h>

#include <memory>
#include <utility>
#include <vector>

#include "base/bind.h"
#include "base/callback.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/sequence_checker.h"
#include "base/sequenced_task_runner.h"
#include "base/stl_util.h"
#include "base/synchronization/lock.h"
#include "base/threading/sequenced_task_runner_handle.h"

namespace chromecast {

namespace subtle {
template <typename T>
class ObservableInternals;
}  // namespace subtle

template <typename T>
class Observable;

template <typename T>
class Observer {
 public:
  Observer(const Observer& other);

  ~Observer();

  void SetOnUpdateCallback(base::RepeatingClosure callback) {
    on_update_callback_ = std::move(callback);
  }

  const T& GetValue() const {
    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
    return value_;
  }

 private:
  friend class subtle::ObservableInternals<T>;
  friend class Observable<T>;

  explicit Observer(scoped_refptr<subtle::ObservableInternals<T>> internals);

  void OnUpdate();

  const scoped_refptr<subtle::ObservableInternals<T>> internals_;
  // Note: value_ is a const ref to the value copy for this sequence, stored in
  // SequenceOwnedInfo.
  const T& value_;
  base::RepeatingClosure on_update_callback_;
  SEQUENCE_CHECKER(sequence_checker_);

  DISALLOW_ASSIGN(Observer);
};

template <typename T>
class Observable {
  static_assert(std::is_copy_constructible<T>::value,
                "Observable values must be copyable");
  static_assert(std::is_copy_assignable<T>::value,
                "Observable values must be copy-assignable");

 public:
  explicit Observable(const T& initial_value);
  Observer<T> Observe();

  void SetValue(const T& new_value);
  const T& GetValue() const;  // NOT threadsafe!
  T GetValueThreadSafe() const;

 private:
  // By using a refcounted object to store the value and observer list, we can
  // avoid tying the lifetime of Observable to its Observers or vice versa.
  const scoped_refptr<subtle::ObservableInternals<T>> internals_;

  DISALLOW_COPY_AND_ASSIGN(Observable);
};

namespace subtle {

template <typename T>
class ObservableInternals
    : public base::RefCountedThreadSafe<ObservableInternals<T>> {
 public:
  explicit ObservableInternals(const T& initial_value)
      : value_(initial_value) {}

  void SetValue(const T& new_value) {
    base::AutoLock lock(lock_);
    value_ = new_value;

    for (auto& item : per_sequence_) {
      item.SetValue(new_value);
    }
  }

  const T& GetValue() const { return value_; }

  T GetValueThreadSafe() const {
    base::AutoLock lock(lock_);
    return value_;
  }

  const T& AddObserver(Observer<T>* observer) {
    DCHECK(observer);
    DCHECK(base::SequencedTaskRunnerHandle::IsSet());
    auto task_runner = base::SequencedTaskRunnerHandle::Get();

    base::AutoLock lock(lock_);
    auto it = per_sequence_.begin();
    while (it != per_sequence_.end() && it->task_runner() != task_runner) {
      ++it;
    }
    if (it == per_sequence_.end()) {
      per_sequence_.emplace_back(std::move(task_runner), value_);
      it = --per_sequence_.end();
    }
    it->AddObserver(observer);
    return it->value();
  }

  void RemoveObserver(Observer<T>* observer) {
    DCHECK(observer);
    DCHECK(base::SequencedTaskRunnerHandle::IsSet());
    auto task_runner = base::SequencedTaskRunnerHandle::Get();

    base::AutoLock lock(lock_);
    for (size_t i = 0; i < per_sequence_.size(); ++i) {
      if (per_sequence_[i].task_runner() == task_runner) {
        per_sequence_[i].RemoveObserver(observer);

        if (per_sequence_[i].Empty()) {
          per_sequence_[i].Swap(per_sequence_.back());
          per_sequence_.pop_back();
        }
        return;
      }
    }

    NOTREACHED() << "Tried to remove observer from unknown task runner";
  }

 private:
  // Information owned by a particular sequence. Must be only accessed on that
  // sequence, and must be deleted by posting a task to that sequence.
  // This class MUST NOT contain a scoped_refptr to the task_runner, since if it
  // did, there would be a reference cycle during cleanup, when the task to
  // Destroy() is posted.
  class SequenceOwnedInfo {
   public:
    explicit SequenceOwnedInfo(const T& value) : value_(value) {}

    const T& value() const {
      DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
      return value_;
    }

    void AddObserver(Observer<T>* observer) {
      DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
      DCHECK(observer);
      DCHECK(!base::ContainsValue(observers_, observer));
      observers_.push_back(observer);
    }

    void RemoveObserver(Observer<T>* observer) {
      DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
      DCHECK(observer);
      DCHECK(base::ContainsValue(observers_, observer));
      observers_.erase(
          std::remove(observers_.begin(), observers_.end(), observer),
          observers_.end());
    }

    bool Empty() const {
      DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
      return observers_.empty();
    }

    void SetValue(const T& value) {
      DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
      value_ = value;
      for (auto* obs : observers_) {
        obs->OnUpdate();
      }
    }

    static void Destroy(std::unique_ptr<SequenceOwnedInfo> self) {
      // The unique_ptr deletes automatically.
    }

   private:
    std::vector<Observer<T>*> observers_;
    T value_;
    SEQUENCE_CHECKER(sequence_checker_);

    DISALLOW_COPY_AND_ASSIGN(SequenceOwnedInfo);
  };

  class PerSequenceInfo {
   public:
    PerSequenceInfo(scoped_refptr<base::SequencedTaskRunner> task_runner,
                    const T& value)
        : task_runner_(std::move(task_runner)),
          owned_info_(std::make_unique<SequenceOwnedInfo>(value)) {}

    PerSequenceInfo(PerSequenceInfo&& other) = default;

    ~PerSequenceInfo() {
      if (!owned_info_) {
        // Members have been moved out via move constructor.
        return;
      }

      DCHECK(Empty());
      // Must post a task to delete the owned info, since there may still be a
      // pending task to call SequenceOwnedInfo::SetValue().
      // Use manual PostNonNestableTask(), since DeleteSoon() does not
      // guarantee deletion.
      task_runner_->PostNonNestableTask(
          FROM_HERE,
          base::BindOnce(&SequenceOwnedInfo::Destroy, std::move(owned_info_)));
    }

    const T& value() const { return owned_info_->value(); }

    const base::SequencedTaskRunner* task_runner() const {
      return task_runner_.get();
    }

    void AddObserver(Observer<T>* observer) {
      owned_info_->AddObserver(observer);
    }

    void RemoveObserver(Observer<T>* observer) {
      owned_info_->RemoveObserver(observer);
    }

    bool Empty() const { return owned_info_->Empty(); }

    void Swap(PerSequenceInfo& other) {
      std::swap(task_runner_, other.task_runner_);
      std::swap(owned_info_, other.owned_info_);
    }

    void SetValue(const T& value) {
      task_runner_->PostTask(
          FROM_HERE,
          base::BindOnce(&SequenceOwnedInfo::SetValue,
                         base::Unretained(owned_info_.get()), value));
    }

   private:
    // Operations on |owned_info| do not need to be synchronized with a lock,
    // since all operations must occur on |task_runner|.
    scoped_refptr<base::SequencedTaskRunner> task_runner_;
    std::unique_ptr<SequenceOwnedInfo> owned_info_;
  };

  friend class base::RefCountedThreadSafe<ObservableInternals>;
  ~ObservableInternals() {}

  mutable base::Lock lock_;
  T value_;
  std::vector<PerSequenceInfo> per_sequence_;

  DISALLOW_COPY_AND_ASSIGN(ObservableInternals);
};

}  // namespace subtle

template <typename T>
Observer<T>::Observer(scoped_refptr<subtle::ObservableInternals<T>> internals)
    : internals_(std::move(internals)), value_(internals_->AddObserver(this)) {}

template <typename T>
Observer<T>::Observer(const Observer& other) : Observer(other.internals_) {}

template <typename T>
Observer<T>::~Observer() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  internals_->RemoveObserver(this);
}

template <typename T>
void Observer<T>::OnUpdate() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  if (on_update_callback_) {
    on_update_callback_.Run();
  }
}

template <typename T>
Observable<T>::Observable(const T& initial_value)
    : internals_(base::WrapRefCounted(
          new subtle::ObservableInternals<T>(initial_value))) {}

template <typename T>
Observer<T> Observable<T>::Observe() {
  return Observer<T>(internals_);
}

template <typename T>
void Observable<T>::SetValue(const T& new_value) {
  internals_->SetValue(new_value);
}

template <typename T>
const T& Observable<T>::GetValue() const {
  return internals_->GetValue();
}

template <typename T>
T Observable<T>::GetValueThreadSafe() const {
  return internals_->GetValueThreadSafe();
}

}  // namespace chromecast

#endif  // CHROMECAST_BASE_OBSERVER_H_
