147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/*
247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  Copyright 2014 The WebRTC Project Authors. All rights reserved.
347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *
447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  Use of this source code is governed by a BSD-style license
547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  that can be found in the LICENSE file in the root of the source
647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  tree. An additional intellectual property rights grant can be found
747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  in the file PATENTS.  All contributing project authors may
847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org */
1047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#ifndef WEBRTC_BASE_ASYNCINVOKER_INL_H_
1247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#define WEBRTC_BASE_ASYNCINVOKER_INL_H_
1347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/bind.h"
1547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/callback.h"
1647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/criticalsection.h"
1747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/messagehandler.h"
1847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/refcount.h"
1947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/scoped_ref_ptr.h"
2047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/sigslot.h"
2147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/thread.h"
2247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
2347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgnamespace rtc {
2447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
2547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgclass AsyncInvoker;
2647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
2747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Helper class for AsyncInvoker. Runs a task and triggers a callback
2847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// on the calling thread if necessary. Instances are ref-counted so their
2947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// lifetime can be independent of AsyncInvoker.
3047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgclass AsyncClosure : public RefCountInterface {
3147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org public:
3247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual ~AsyncClosure() {}
3347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Runs the asynchronous task, and triggers a callback to the calling
3447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // thread if needed. Should be called from the target thread.
3547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual void Execute() = 0;
3647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org};
3747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
3847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Simple closure that doesn't trigger a callback for the calling thread.
3947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgtemplate <class FunctorT>
4047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgclass FireAndForgetAsyncClosure : public AsyncClosure {
4147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org public:
4247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  explicit FireAndForgetAsyncClosure(const FunctorT& functor)
4347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      : functor_(functor) {}
4447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual void Execute() {
4547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    functor_();
4647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
4747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org private:
4847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  FunctorT functor_;
4947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org};
5047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
5147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Base class for closures that may trigger a callback for the calling thread.
5247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Listens for the "destroyed" signals from the calling thread and the invoker,
5347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// and cancels the callback to the calling thread if either is destroyed.
5447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgclass NotifyingAsyncClosureBase : public AsyncClosure,
5547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                  public sigslot::has_slots<> {
5647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org public:
5747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual ~NotifyingAsyncClosureBase() { disconnect_all(); }
5847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
5947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org protected:
6047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  NotifyingAsyncClosureBase(AsyncInvoker* invoker, Thread* calling_thread);
6147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  void TriggerCallback();
6247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  void SetCallback(const Callback0<void>& callback) {
6347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    CritScope cs(&crit_);
6447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    callback_ = callback;
6547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
6647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  bool CallbackCanceled() const { return calling_thread_ == NULL; }
6747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
6847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org private:
6947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  Callback0<void> callback_;
7047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  CriticalSection crit_;
7147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  AsyncInvoker* invoker_;
7247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  Thread* calling_thread_;
7347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
7447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  void CancelCallback();
7547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org};
7647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
7747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Closures that have a non-void return value and require a callback.
7847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgtemplate <class ReturnT, class FunctorT, class HostT>
7947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgclass NotifyingAsyncClosure : public NotifyingAsyncClosureBase {
8047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org public:
8147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  NotifyingAsyncClosure(AsyncInvoker* invoker,
8247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                        Thread* calling_thread,
8347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                        const FunctorT& functor,
8447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                        void (HostT::*callback)(ReturnT),
8547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                        HostT* callback_host)
8647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      :  NotifyingAsyncClosureBase(invoker, calling_thread),
8747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org         functor_(functor),
8847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org         callback_(callback),
8947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org         callback_host_(callback_host) {}
9047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual void Execute() {
9147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ReturnT result = functor_();
9247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (!CallbackCanceled()) {
9347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      SetCallback(Callback0<void>(Bind(callback_, callback_host_, result)));
9447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      TriggerCallback();
9547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
9647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
9747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
9847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org private:
9947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  FunctorT functor_;
10047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  void (HostT::*callback_)(ReturnT);
10147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  HostT* callback_host_;
10247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org};
10347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
10447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Closures that have a void return value and require a callback.
10547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgtemplate <class FunctorT, class HostT>
10647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgclass NotifyingAsyncClosure<void, FunctorT, HostT>
10747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    : public NotifyingAsyncClosureBase {
10847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org public:
10947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  NotifyingAsyncClosure(AsyncInvoker* invoker,
11047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                        Thread* calling_thread,
11147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                        const FunctorT& functor,
11247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                        void (HostT::*callback)(),
11347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                        HostT* callback_host)
11447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      : NotifyingAsyncClosureBase(invoker, calling_thread),
11547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        functor_(functor) {
11647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    SetCallback(Callback0<void>(Bind(callback, callback_host)));
11747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
11847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual void Execute() {
11947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    functor_();
12047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    TriggerCallback();
12147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
12247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
12347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org private:
12447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  FunctorT functor_;
12547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org};
12647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
12747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}  // namespace rtc
12847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
12947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif  // WEBRTC_BASE_ASYNCINVOKER_INL_H_
130