/*
 *  Copyright 2014 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#ifndef WEBRTC_BASE_ASYNCINVOKER_H_
#define WEBRTC_BASE_ASYNCINVOKER_H_

#include <memory>
#include <utility>

#include "webrtc/base/asyncinvoker-inl.h"
#include "webrtc/base/bind.h"
#include "webrtc/base/constructormagic.h"
#include "webrtc/base/event.h"
#include "webrtc/base/sigslot.h"
#include "webrtc/base/thread.h"

namespace rtc {

// Invokes function objects (aka functors) asynchronously on a Thread, and
// owns the lifetime of calls (ie, when this object is destroyed, calls in
// flight are cancelled). AsyncInvoker can optionally execute a user-specified
// function when the asynchronous call is complete, or operates in
// fire-and-forget mode otherwise.
//
// AsyncInvoker does not own the thread it calls functors on.
//
// A note about async calls and object lifetimes: users should
// be mindful of object lifetimes when calling functions asynchronously and
// ensure objects used by the function _cannot_ be deleted between the
// invocation and execution of the functor. AsyncInvoker is designed to
// help: any calls in flight will be cancelled when the AsyncInvoker used to
// make the call is destructed, and any calls executing will be allowed to
// complete before AsyncInvoker destructs.
//
// The easiest way to ensure lifetimes are handled correctly is to create a
// class that owns the Thread and AsyncInvoker objects, and then call its
// methods asynchronously as needed.
//
// Example:
//   class MyClass {
//    public:
//     void FireAsyncTaskWithResult(Thread* thread, int x) {
//       // Specify a callback to get the result upon completion.
//       invoker_.AsyncInvoke<int>(RTC_FROM_HERE,
//           thread, Bind(&MyClass::AsyncTaskWithResult, this, x),
//           &MyClass::OnTaskComplete, this);
//     }
//     void FireAnotherAsyncTask(Thread* thread) {
//       // No callback specified means fire-and-forget.
//       invoker_.AsyncInvoke<void>(RTC_FROM_HERE,
//           thread, Bind(&MyClass::AnotherAsyncTask, this));
//
//    private:
//     int AsyncTaskWithResult(int x) {
//       // Some long running process...
//       return x * x;
//     }
//     void AnotherAsyncTask() {
//       // Some other long running process...
//     }
//     void OnTaskComplete(int result) { result_ = result; }
//
//     AsyncInvoker invoker_;
//     int result_;
//   };
class AsyncInvoker : public MessageHandler {
 public:
  AsyncInvoker();
  ~AsyncInvoker() override;

  // Call |functor| asynchronously on |thread|, with no callback upon
  // completion. Returns immediately.
  template <class ReturnT, class FunctorT>
  void AsyncInvoke(const Location& posted_from,
                   Thread* thread,
                   const FunctorT& functor,
                   uint32_t id = 0) {
    std::unique_ptr<AsyncClosure> closure(
        new FireAndForgetAsyncClosure<FunctorT>(this, functor));
    DoInvoke(posted_from, thread, std::move(closure), id);
  }

  // Call |functor| asynchronously on |thread| with |delay_ms|, with no callback
  // upon completion. Returns immediately.
  template <class ReturnT, class FunctorT>
  void AsyncInvokeDelayed(const Location& posted_from,
                          Thread* thread,
                          const FunctorT& functor,
                          uint32_t delay_ms,
                          uint32_t id = 0) {
    std::unique_ptr<AsyncClosure> closure(
        new FireAndForgetAsyncClosure<FunctorT>(this, functor));
    DoInvokeDelayed(posted_from, thread, std::move(closure), delay_ms, id);
  }

  // Call |functor| asynchronously on |thread|, calling |callback| when done.
  // Uses a separate Location for |callback_posted_from| so that the functor
  // invoke and the callback invoke can be differentiated.
  template <class ReturnT, class FunctorT, class HostT>
  void AsyncInvoke(const Location& posted_from,
                   const Location& callback_posted_from,
                   Thread* thread,
                   const FunctorT& functor,
                   void (HostT::*callback)(ReturnT),
                   HostT* callback_host,
                   uint32_t id = 0) {
    std::unique_ptr<AsyncClosure> closure(
        new NotifyingAsyncClosure<ReturnT, FunctorT, HostT>(
            this, callback_posted_from, Thread::Current(), functor, callback,
            callback_host));
    DoInvoke(posted_from, thread, std::move(closure), id);
  }

  // Call |functor| asynchronously on |thread|, calling |callback| when done.
  // Uses a separate Location for |callback_posted_from| so that the functor
  // invoke and the callback invoke can be differentiated.
  // Overloaded for void return.
  template <class ReturnT, class FunctorT, class HostT>
  void AsyncInvoke(const Location& posted_from,
                   const Location& callback_posted_from,
                   Thread* thread,
                   const FunctorT& functor,
                   void (HostT::*callback)(),
                   HostT* callback_host,
                   uint32_t id = 0) {
    std::unique_ptr<AsyncClosure> closure(
        new NotifyingAsyncClosure<void, FunctorT, HostT>(
            this, callback_posted_from, Thread::Current(), functor, callback,
            callback_host));
    DoInvoke(posted_from, thread, std::move(closure), id);
  }

  // Synchronously execute on |thread| all outstanding calls we own
  // that are pending on |thread|, and wait for calls to complete
  // before returning. Optionally filter by message id.
  // The destructor will not wait for outstanding calls, so if that
  // behavior is desired, call Flush() before destroying this object.
  void Flush(Thread* thread, uint32_t id = MQID_ANY);

  // Signaled when this object is destructed.
  sigslot::signal0<> SignalInvokerDestroyed;

 private:
  void OnMessage(Message* msg) override;
  void DoInvoke(const Location& posted_from,
                Thread* thread,
                std::unique_ptr<AsyncClosure> closure,
                uint32_t id);
  void DoInvokeDelayed(const Location& posted_from,
                       Thread* thread,
                       std::unique_ptr<AsyncClosure> closure,
                       uint32_t delay_ms,
                       uint32_t id);
  volatile int pending_invocations_ = 0;
  Event invocation_complete_;
  bool destroying_ = false;
  friend class AsyncClosure;

  RTC_DISALLOW_COPY_AND_ASSIGN(AsyncInvoker);
};

// Similar to AsyncInvoker, but guards against the Thread being destroyed while
// there are outstanding dangling pointers to it. It will connect to the current
// thread in the constructor, and will get notified when that thread is
// destroyed. After GuardedAsyncInvoker is constructed, it can be used from
// other threads to post functors to the thread it was constructed on. If that
// thread dies, any further calls to AsyncInvoke() will be safely ignored.
class GuardedAsyncInvoker : public sigslot::has_slots<> {
 public:
  GuardedAsyncInvoker();
  ~GuardedAsyncInvoker() override;

  // Synchronously execute all outstanding calls we own, and wait for calls to
  // complete before returning. Optionally filter by message id. The destructor
  // will not wait for outstanding calls, so if that behavior is desired, call
  // Flush() first. Returns false if the thread has died.
  bool Flush(uint32_t id = MQID_ANY);

  // Call |functor| asynchronously with no callback upon completion. Returns
  // immediately. Returns false if the thread has died.
  template <class ReturnT, class FunctorT>
  bool AsyncInvoke(const Location& posted_from,
                   const FunctorT& functor,
                   uint32_t id = 0) {
    rtc::CritScope cs(&crit_);
    if (thread_ == nullptr)
      return false;
    invoker_.AsyncInvoke<ReturnT, FunctorT>(posted_from, thread_, functor, id);
    return true;
  }

  // Call |functor| asynchronously with |delay_ms|, with no callback upon
  // completion. Returns immediately. Returns false if the thread has died.
  template <class ReturnT, class FunctorT>
  bool AsyncInvokeDelayed(const Location& posted_from,
                          const FunctorT& functor,
                          uint32_t delay_ms,
                          uint32_t id = 0) {
    rtc::CritScope cs(&crit_);
    if (thread_ == nullptr)
      return false;
    invoker_.AsyncInvokeDelayed<ReturnT, FunctorT>(posted_from, thread_,
                                                   functor, delay_ms, id);
    return true;
  }

  // Call |functor| asynchronously, calling |callback| when done. Returns false
  // if the thread has died.
  template <class ReturnT, class FunctorT, class HostT>
  bool AsyncInvoke(const Location& posted_from,
                   const Location& callback_posted_from,
                   const FunctorT& functor,
                   void (HostT::*callback)(ReturnT),
                   HostT* callback_host,
                   uint32_t id = 0) {
    rtc::CritScope cs(&crit_);
    if (thread_ == nullptr)
      return false;
    invoker_.AsyncInvoke<ReturnT, FunctorT, HostT>(
        posted_from, callback_posted_from, thread_, functor, callback,
        callback_host, id);
    return true;
  }

  // Call |functor| asynchronously calling |callback| when done. Overloaded for
  // void return. Returns false if the thread has died.
  template <class ReturnT, class FunctorT, class HostT>
  bool AsyncInvoke(const Location& posted_from,
                   const Location& callback_posted_from,
                   const FunctorT& functor,
                   void (HostT::*callback)(),
                   HostT* callback_host,
                   uint32_t id = 0) {
    rtc::CritScope cs(&crit_);
    if (thread_ == nullptr)
      return false;
    invoker_.AsyncInvoke<ReturnT, FunctorT, HostT>(
        posted_from, callback_posted_from, thread_, functor, callback,
        callback_host, id);
    return true;
  }

 private:
  // Callback when |thread_| is destroyed.
  void ThreadDestroyed();

  CriticalSection crit_;
  Thread* thread_ GUARDED_BY(crit_);
  AsyncInvoker invoker_ GUARDED_BY(crit_);
};

}  // namespace rtc

#endif  // WEBRTC_BASE_ASYNCINVOKER_H_
