/*
 * Copyright 2015 Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

namespace folly {

template <class T>
SharedPromise<T>::SharedPromise(SharedPromise<T>&& other) noexcept {
  *this = std::move(other);
}

template <class T>
SharedPromise<T>& SharedPromise<T>::operator=(
    SharedPromise<T>&& other) noexcept {
  if (this == &other) {
    return *this;
  }

  // std::lock will perform deadlock avoidance, in case
  // Thread A: p1 = std::move(p2)
  // Thread B: p2 = std::move(p1)
  // race each other
  std::lock(mutex_, other.mutex_);
  std::lock_guard<std::mutex> g1(mutex_, std::adopt_lock);
  std::lock_guard<std::mutex> g2(other.mutex_, std::adopt_lock);

  std::swap(size_, other.size_);
  std::swap(hasValue_, other.hasValue_);
  std::swap(try_, other.try_);
  std::swap(promises_, other.promises_);

  return *this;
}

template <class T>
size_t SharedPromise<T>::size() {
  std::lock_guard<std::mutex> g(mutex_);
  return size_;
}

template <class T>
Future<T> SharedPromise<T>::getFuture() {
  std::lock_guard<std::mutex> g(mutex_);
  size_++;
  if (hasValue_) {
    return makeFuture<T>(Try<T>(try_));
  } else {
    promises_.emplace_back();
    return promises_.back().getFuture();
  }
}

template <class T>
template <class E>
typename std::enable_if<std::is_base_of<std::exception, E>::value>::type
SharedPromise<T>::setException(E const& e) {
  setTry(Try<T>(e));
}

template <class T>
void SharedPromise<T>::setException(std::exception_ptr const& ep) {
  setTry(Try<T>(ep));
}

template <class T>
void SharedPromise<T>::setException(exception_wrapper ew) {
  setTry(Try<T>(std::move(ew)));
}

template <class T>
void SharedPromise<T>::setInterruptHandler(
    std::function<void(exception_wrapper const&)> fn) {
  std::lock_guard<std::mutex> g(mutex_);
  if (hasValue_) {
    return;
  }
  for (auto& p : promises_) {
    p.setInterruptHandler(fn);
  }
}

template <class T>
template <class M>
void SharedPromise<T>::setValue(M&& v) {
  setTry(Try<T>(std::forward<M>(v)));
}

template <class T>
template <class F>
void SharedPromise<T>::setWith(F&& func) {
  setTry(makeTryFunction(std::forward<F>(func)));
}

template <class T>
void SharedPromise<T>::setTry(Try<T>&& t) {
  std::vector<Promise<T>> promises;

  {
    std::lock_guard<std::mutex> g(mutex_);
    if (hasValue_) {
      throw PromiseAlreadySatisfied();
    }
    hasValue_ = true;
    try_ = std::move(t);
    promises.swap(promises_);
  }

  for (auto& p : promises) {
    p.setTry(Try<T>(try_));
  }
}

}
