Update libjingle to 61168196

R=mallinath@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/8139004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@5502 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/talk/base/asyncinvoker-inl.h b/talk/base/asyncinvoker-inl.h
new file mode 100644
index 0000000..c4afd3a
--- /dev/null
+++ b/talk/base/asyncinvoker-inl.h
@@ -0,0 +1,101 @@
+/*
+ * libjingle
+ * Copyright 2014 Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright notice,
+ *     this list of conditions and the following disclaimer in the documentation
+ *     and/or other materials provided with the distribution.
+ *  3. The name of the author may not be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TALK_BASE_ASYNCINVOKER_INL_H_
+#define TALK_BASE_ASYNCINVOKER_INL_H_
+
+#include "talk/base/criticalsection.h"
+#include "talk/base/messagehandler.h"
+#include "talk/base/sigslot.h"
+#include "talk/base/thread.h"
+
+namespace talk_base {
+
+// Helper class for AsyncInvoker. Runs a functor on a message queue or thread
+// and doesn't execute the callback when finished if the calling thread ends.
+template <class ReturnT, class FunctorT>
+class AsyncFunctorMessageHandler
+    : public FunctorMessageHandler<ReturnT, FunctorT>,
+      public sigslot::has_slots<> {
+  typedef AsyncFunctorMessageHandler<ReturnT, FunctorT> ThisT;
+ public:
+  explicit AsyncFunctorMessageHandler(const FunctorT& functor)
+      : FunctorMessageHandler<ReturnT, FunctorT>(functor),
+        thread_(Thread::Current()),
+        shutting_down_(false) {
+    thread_->SignalQueueDestroyed.connect(this, &ThisT::OnThreadDestroyed);
+  }
+
+  virtual ~AsyncFunctorMessageHandler() {
+    CritScope cs(&running_crit_);
+    shutting_down_ = true;
+  }
+
+  virtual void OnMessage(Message* msg) {
+    CritScope cs(&running_crit_);
+    if (!shutting_down_) {
+      FunctorMessageHandler<ReturnT, FunctorT>::OnMessage(msg);
+    }
+  }
+
+  // Returns the thread that initiated the async call.
+  Thread* thread() const { return thread_; }
+
+  // Wraps a callback so that it won't execute if |thread_| goes away.
+  void WrapCallback(Callback0<void> cb) {
+    this->SetCallback(
+        Callback0<void>(Bind(&ThisT::MaybeRunCallback, this, cb)));
+  }
+
+ private:
+  void OnThreadDestroyed() {
+    CritScope cs(&thread_crit_);
+    thread_ = NULL;
+    this->SetCallback(Callback0<void>());  // Clear out the callback.
+  }
+
+  void MaybeRunCallback(Callback0<void> cb) {
+#ifdef _DEBUG
+    ASSERT(running_crit_.CurrentThreadIsOwner());
+#endif
+    CritScope cs(&thread_crit_);
+    if (thread_ && !shutting_down_) {
+      cb();
+    }
+  }
+
+  FunctorT functor_;
+  Thread* thread_;
+  CriticalSection thread_crit_;
+  CriticalSection running_crit_;
+  bool shutting_down_;
+};
+
+}  // namespace talk_base
+
+
+#endif  // TALK_BASE_ASYNCINVOKER_INL_H_
diff --git a/talk/base/asyncinvoker.cc b/talk/base/asyncinvoker.cc
new file mode 100644
index 0000000..63171be
--- /dev/null
+++ b/talk/base/asyncinvoker.cc
@@ -0,0 +1,78 @@
+/*
+ * libjingle
+ * Copyright 2014 Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright notice,
+ *     this list of conditions and the following disclaimer in the documentation
+ *     and/or other materials provided with the distribution.
+ *  3. The name of the author may not be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/base/asyncinvoker.h"
+
+namespace talk_base {
+
+// Synchronously execute all outstanding calls we own pending
+// on |thread|. Optionally filter by message id.
+void AsyncInvoker::Flush(Thread* thread, uint32 id /*= MQID_ANY*/) {
+  // Run this on |thread| to reduce the number of context switches.
+  if (Thread::Current() != thread) {
+    thread->Invoke<void>(Bind(&AsyncInvoker::Flush, this, thread, id));
+    return;
+  }
+
+  // Make a copy of handlers_, since it'll be modified by
+  // callbacks to RemoveHandler when each is done executing.
+  crit_.Enter();
+  std::vector<MessageHandler*> handlers(handlers_.collection());
+  crit_.Leave();
+  MessageList removed;
+  for (size_t i = 0; i < handlers.size(); ++i) {
+    removed.clear();
+    thread->Clear(handlers[i], id, &removed);
+    if (!removed.empty()) {
+      // Since each message gets its own handler with AsyncInvoker,
+      // we expect a maximum of one removed.
+      ASSERT(removed.size() == 1);
+      // This handler was pending on this thread, so run it now.
+      const Message& msg = removed.front();
+      thread->Send(msg.phandler,
+                   msg.message_id,
+                   msg.pdata);
+    }
+  }
+}
+
+void AsyncInvoker::InvokeHandler(Thread* thread, MessageHandler* handler,
+                                 uint32 id) {
+  {
+    CritScope cs(&crit_);
+    handlers_.PushBack(handler);
+  }
+  thread->Post(handler, id);
+}
+
+void AsyncInvoker::RemoveHandler(MessageHandler* handler) {
+  CritScope cs(&crit_);
+  handlers_.Remove(handler);
+  delete handler;
+}
+
+}  // namespace talk_base
diff --git a/talk/base/asyncinvoker.h b/talk/base/asyncinvoker.h
new file mode 100644
index 0000000..fabdbdc
--- /dev/null
+++ b/talk/base/asyncinvoker.h
@@ -0,0 +1,167 @@
+/*
+ * libjingle
+ * Copyright 2014 Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright notice,
+ *     this list of conditions and the following disclaimer in the documentation
+ *     and/or other materials provided with the distribution.
+ *  3. The name of the author may not be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TALK_BASE_ASYNCINVOKER_H_
+#define TALK_BASE_ASYNCINVOKER_H_
+
+#include "talk/base/asyncinvoker-inl.h"
+#include "talk/base/bind.h"
+#include "talk/base/scopedptrcollection.h"
+#include "talk/base/thread.h"
+
+namespace talk_base {
+
+// 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>(
+//           thread, Bind(&MyClass::AsyncTaskWithResult, this, x),
+//           &MyClass::OnTaskComplete, this);
+//     }
+//     void FireAnotherAsyncTask(Thread* thread) {
+//       // No callback specified means fire-and-forget.
+//       invoker_.AsyncInvoke<void>(
+//           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:
+  // Call |functor| asynchronously on |thread|, with no callback upon
+  // completion. Returns immediately.
+  template <class ReturnT, class FunctorT>
+  void AsyncInvoke(Thread* thread,
+                   const FunctorT& functor,
+                   uint32 id = 0) {
+    FunctorMessageHandler<ReturnT, FunctorT>* handler =
+        new FunctorMessageHandler<ReturnT, FunctorT>(functor);
+    handler->SetCallback(Bind(&AsyncInvoker::RemoveHandler, this, handler));
+    InvokeHandler(thread, handler, id);
+  }
+
+  // Call |functor| asynchronously on |thread|, calling |callback| when done.
+  template <class ReturnT, class FunctorT, class HostT>
+  void AsyncInvoke(Thread* thread,
+                   const FunctorT& functor,
+                   void (HostT::*callback)(ReturnT),
+                   HostT* callback_host,
+                   uint32 id = 0) {
+    AsyncFunctorMessageHandler<ReturnT, FunctorT>* handler =
+        new AsyncFunctorMessageHandler<ReturnT, FunctorT>(functor);
+    handler->WrapCallback(
+        Bind(&AsyncInvoker::OnAsyncCallCompleted<ReturnT, FunctorT, HostT>,
+             this, handler, callback, callback_host));
+    InvokeHandler(thread, handler, id);
+  }
+
+  // Call |functor| asynchronously on |thread|, calling |callback| when done.
+  // Overloaded for void return.
+  template <class ReturnT, class FunctorT, class HostT>
+  void AsyncInvoke(Thread* thread,
+                   const FunctorT& functor,
+                   void (HostT::*callback)(),
+                   HostT* callback_host,
+                   uint32 id = 0) {
+    AsyncFunctorMessageHandler<void, FunctorT>* handler =
+        new AsyncFunctorMessageHandler<ReturnT, FunctorT>(functor);
+    handler->WrapCallback(
+        Bind(&AsyncInvoker::OnAsyncVoidCallCompleted<FunctorT, HostT>,
+             this, handler, callback, callback_host));
+    InvokeHandler(thread, handler, 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 id = MQID_ANY);
+
+ private:
+  void InvokeHandler(Thread* thread, MessageHandler* handler, uint32 id);
+  void RemoveHandler(MessageHandler* handler);
+
+  template <class ReturnT, class FunctorT, class HostT>
+  void OnAsyncCallCompleted(
+      AsyncFunctorMessageHandler<ReturnT, FunctorT>* handler,
+      void (HostT::*callback)(ReturnT),
+      HostT* callback_host) {
+    AsyncInvoke<void>(handler->thread(),
+                Bind(callback, callback_host, handler->result()));
+    RemoveHandler(handler);
+  }
+
+  template <class FunctorT, class HostT>
+  void OnAsyncVoidCallCompleted(
+      AsyncFunctorMessageHandler<void, FunctorT>* handler,
+      void (HostT::*callback)(),
+      HostT* callback_host) {
+    AsyncInvoke<void>(handler->thread(), Bind(callback, callback_host));
+    RemoveHandler(handler);
+  }
+
+  CriticalSection crit_;
+  ScopedPtrCollection<MessageHandler> handlers_;
+};
+
+}  // namespace talk_base
+
+
+#endif  // TALK_BASE_ASYNCINVOKER_H_
diff --git a/talk/base/bind.h b/talk/base/bind.h
index 622cc67..5b4eaac 100644
--- a/talk/base/bind.h
+++ b/talk/base/bind.h
@@ -84,6 +84,18 @@
   ObjectT* object_;
 };
 
+template <class FunctorT, class R>
+class Functor0 {
+ public:
+  explicit Functor0(const FunctorT& functor)
+      : functor_(functor) {}
+  R operator()() const {
+    return functor_(); }
+ private:
+  FunctorT functor_;
+};
+
+
 #define FP_T(x) R (ObjectT::*x)()
 
 template <class ObjectT, class R>
@@ -104,6 +116,16 @@
 }
 
 #undef FP_T
+#define FP_T(x) R (*x)()
+
+template <class R>
+Functor0<FP_T(NONAME), R>
+Bind(FP_T(function)) {
+  return Functor0<FP_T(NONAME), R>(
+      function);
+}
+
+#undef FP_T
 
 template <class ObjectT, class MethodT, class R,
           class P1>
@@ -121,6 +143,21 @@
   P1 p1_;
 };
 
+template <class FunctorT, class R,
+          class P1>
+class Functor1 {
+ public:
+  Functor1(const FunctorT& functor, P1 p1)
+      : functor_(functor),
+      p1_(p1) {}
+  R operator()() const {
+    return functor_(p1_); }
+ private:
+  FunctorT functor_;
+  P1 p1_;
+};
+
+
 #define FP_T(x) R (ObjectT::*x)(P1)
 
 template <class ObjectT, class R,
@@ -145,6 +182,18 @@
 }
 
 #undef FP_T
+#define FP_T(x) R (*x)(P1)
+
+template <class R,
+          class P1>
+Functor1<FP_T(NONAME), R, P1>
+Bind(FP_T(function),
+     typename detail::identity<P1>::type p1) {
+  return Functor1<FP_T(NONAME), R, P1>(
+      function, p1);
+}
+
+#undef FP_T
 
 template <class ObjectT, class MethodT, class R,
           class P1,
@@ -166,6 +215,24 @@
   P2 p2_;
 };
 
+template <class FunctorT, class R,
+          class P1,
+          class P2>
+class Functor2 {
+ public:
+  Functor2(const FunctorT& functor, P1 p1, P2 p2)
+      : functor_(functor),
+      p1_(p1),
+      p2_(p2) {}
+  R operator()() const {
+    return functor_(p1_, p2_); }
+ private:
+  FunctorT functor_;
+  P1 p1_;
+  P2 p2_;
+};
+
+
 #define FP_T(x) R (ObjectT::*x)(P1, P2)
 
 template <class ObjectT, class R,
@@ -194,6 +261,20 @@
 }
 
 #undef FP_T
+#define FP_T(x) R (*x)(P1, P2)
+
+template <class R,
+          class P1,
+          class P2>
+Functor2<FP_T(NONAME), R, P1, P2>
+Bind(FP_T(function),
+     typename detail::identity<P1>::type p1,
+     typename detail::identity<P2>::type p2) {
+  return Functor2<FP_T(NONAME), R, P1, P2>(
+      function, p1, p2);
+}
+
+#undef FP_T
 
 template <class ObjectT, class MethodT, class R,
           class P1,
@@ -219,6 +300,27 @@
   P3 p3_;
 };
 
+template <class FunctorT, class R,
+          class P1,
+          class P2,
+          class P3>
+class Functor3 {
+ public:
+  Functor3(const FunctorT& functor, P1 p1, P2 p2, P3 p3)
+      : functor_(functor),
+      p1_(p1),
+      p2_(p2),
+      p3_(p3) {}
+  R operator()() const {
+    return functor_(p1_, p2_, p3_); }
+ private:
+  FunctorT functor_;
+  P1 p1_;
+  P2 p2_;
+  P3 p3_;
+};
+
+
 #define FP_T(x) R (ObjectT::*x)(P1, P2, P3)
 
 template <class ObjectT, class R,
@@ -251,6 +353,22 @@
 }
 
 #undef FP_T
+#define FP_T(x) R (*x)(P1, P2, P3)
+
+template <class R,
+          class P1,
+          class P2,
+          class P3>
+Functor3<FP_T(NONAME), R, P1, P2, P3>
+Bind(FP_T(function),
+     typename detail::identity<P1>::type p1,
+     typename detail::identity<P2>::type p2,
+     typename detail::identity<P3>::type p3) {
+  return Functor3<FP_T(NONAME), R, P1, P2, P3>(
+      function, p1, p2, p3);
+}
+
+#undef FP_T
 
 template <class ObjectT, class MethodT, class R,
           class P1,
@@ -280,6 +398,30 @@
   P4 p4_;
 };
 
+template <class FunctorT, class R,
+          class P1,
+          class P2,
+          class P3,
+          class P4>
+class Functor4 {
+ public:
+  Functor4(const FunctorT& functor, P1 p1, P2 p2, P3 p3, P4 p4)
+      : functor_(functor),
+      p1_(p1),
+      p2_(p2),
+      p3_(p3),
+      p4_(p4) {}
+  R operator()() const {
+    return functor_(p1_, p2_, p3_, p4_); }
+ private:
+  FunctorT functor_;
+  P1 p1_;
+  P2 p2_;
+  P3 p3_;
+  P4 p4_;
+};
+
+
 #define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4)
 
 template <class ObjectT, class R,
@@ -316,6 +458,24 @@
 }
 
 #undef FP_T
+#define FP_T(x) R (*x)(P1, P2, P3, P4)
+
+template <class R,
+          class P1,
+          class P2,
+          class P3,
+          class P4>
+Functor4<FP_T(NONAME), R, P1, P2, P3, P4>
+Bind(FP_T(function),
+     typename detail::identity<P1>::type p1,
+     typename detail::identity<P2>::type p2,
+     typename detail::identity<P3>::type p3,
+     typename detail::identity<P4>::type p4) {
+  return Functor4<FP_T(NONAME), R, P1, P2, P3, P4>(
+      function, p1, p2, p3, p4);
+}
+
+#undef FP_T
 
 template <class ObjectT, class MethodT, class R,
           class P1,
@@ -349,6 +509,33 @@
   P5 p5_;
 };
 
+template <class FunctorT, class R,
+          class P1,
+          class P2,
+          class P3,
+          class P4,
+          class P5>
+class Functor5 {
+ public:
+  Functor5(const FunctorT& functor, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
+      : functor_(functor),
+      p1_(p1),
+      p2_(p2),
+      p3_(p3),
+      p4_(p4),
+      p5_(p5) {}
+  R operator()() const {
+    return functor_(p1_, p2_, p3_, p4_, p5_); }
+ private:
+  FunctorT functor_;
+  P1 p1_;
+  P2 p2_;
+  P3 p3_;
+  P4 p4_;
+  P5 p5_;
+};
+
+
 #define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5)
 
 template <class ObjectT, class R,
@@ -389,6 +576,26 @@
 }
 
 #undef FP_T
+#define FP_T(x) R (*x)(P1, P2, P3, P4, P5)
+
+template <class R,
+          class P1,
+          class P2,
+          class P3,
+          class P4,
+          class P5>
+Functor5<FP_T(NONAME), R, P1, P2, P3, P4, P5>
+Bind(FP_T(function),
+     typename detail::identity<P1>::type p1,
+     typename detail::identity<P2>::type p2,
+     typename detail::identity<P3>::type p3,
+     typename detail::identity<P4>::type p4,
+     typename detail::identity<P5>::type p5) {
+  return Functor5<FP_T(NONAME), R, P1, P2, P3, P4, P5>(
+      function, p1, p2, p3, p4, p5);
+}
+
+#undef FP_T
 
 }  // namespace talk_base
 
diff --git a/talk/base/bind.h.pump b/talk/base/bind.h.pump
index 7f4c39e..2ebb895 100644
--- a/talk/base/bind.h.pump
+++ b/talk/base/bind.h.pump
@@ -91,6 +91,24 @@
 
 };
 
+template <class FunctorT, class R$for j [[,
+          class P$j]]>
+class Functor$i {
+ public:
+  $if i == 0 [[explicit ]]
+Functor$i(const FunctorT& functor$for j [[, P$j p$j]])
+      : functor_(functor)$for j [[,
+      p$(j)_(p$j)]] {}
+  R operator()() const {
+    return functor_($for j , [[p$(j)_]]); }
+ private:
+  FunctorT functor_;$for j [[
+
+  P$j p$(j)_;]]
+
+};
+
+
 #define FP_T(x) R (ObjectT::*x)($for j , [[P$j]])
 
 template <class ObjectT, class R$for j [[,
@@ -115,6 +133,18 @@
 }
 
 #undef FP_T
+#define FP_T(x) R (*x)($for j , [[P$j]])
+
+template <class R$for j [[,
+          class P$j]]>
+Functor$i<FP_T(NONAME), R$for j [[, P$j]]>
+Bind(FP_T(function)$for j [[,
+     typename detail::identity<P$j>::type p$j]]) {
+  return Functor$i<FP_T(NONAME), R$for j [[, P$j]]>(
+      function$for j [[, p$j]]);
+}
+
+#undef FP_T
 
 ]]
 
diff --git a/talk/base/bind_unittest.cc b/talk/base/bind_unittest.cc
index 81bbddd..78ac278 100644
--- a/talk/base/bind_unittest.cc
+++ b/talk/base/bind_unittest.cc
@@ -43,6 +43,10 @@
   mutable int call_count;
 };
 
+int Return42() { return 42; }
+int Negate(int a) { return -a; }
+int Multiply(int a, int b) { return a * b; }
+
 }  // namespace
 
 TEST(BindTest, BindToMethod) {
@@ -71,4 +75,10 @@
   EXPECT_EQ(8, object.call_count);
 }
 
+TEST(BindTest, BindToFunction) {
+  EXPECT_EQ(42, Bind(&Return42)());
+  EXPECT_EQ(3, Bind(&Negate, -3)());
+  EXPECT_EQ(56, Bind(&Multiply, 8, 7)());
+}
+
 }  // namespace talk_base
diff --git a/talk/base/callback.h b/talk/base/callback.h
new file mode 100644
index 0000000..e772768
--- /dev/null
+++ b/talk/base/callback.h
@@ -0,0 +1,291 @@
+// This file was GENERATED by command:
+//     pump.py callback.h.pump
+// DO NOT EDIT BY HAND!!!
+
+/*
+ * libjingle
+ * Copyright 2012 Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright notice,
+ *     this list of conditions and the following disclaimer in the documentation
+ *     and/or other materials provided with the distribution.
+ *  3. The name of the author may not be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// To generate callback.h from callback.h.pump, execute:
+// /home/build/google3/third_party/gtest/scripts/pump.py callback.h.pump
+
+// Callbacks are callable object containers. They can hold a function pointer
+// or a function object and behave like a value type. Internally, data is
+// reference-counted, making copies and pass-by-value inexpensive.
+//
+// Callbacks are typed using template arguments.  The format is:
+//   CallbackN<ReturnType, ParamType1, ..., ParamTypeN>
+// where N is the number of arguments supplied to the callable object.
+// Callbacks are invoked using operator(), just like a function or a function
+// object. Default-constructed callbacks are "empty," and executing an empty
+// callback does nothing. A callback can be made empty by assigning it from
+// a default-constructed callback.
+//
+// Callbacks are similar in purpose to std::function (which isn't available on
+// all platforms we support) and a lightweight alternative to sigslots. Since
+// they effectively hide the type of the object they call, they're useful in
+// breaking dependencies between objects that need to interact with one another.
+// Notably, they can hold the results of Bind(), std::bind*, etc, without
+// needing
+// to know the resulting object type of those calls.
+//
+// Sigslots, on the other hand, provide a fuller feature set, such as multiple
+// subscriptions to a signal, optional thread-safety, and lifetime tracking of
+// slots. When these features are needed, choose sigslots.
+//
+// Example:
+//   int sqr(int x) { return x * x; }
+//   struct AddK {
+//     int k;
+//     int operator()(int x) const { return x + k; }
+//   } add_k = {5};
+//
+//   Callback1<int, int> my_callback;
+//   cout << my_callback.empty() << endl;  // true
+//
+//   my_callback = Callback1<int, int>(&sqr);
+//   cout << my_callback.empty() << endl;  // false
+//   cout << my_callback(3) << endl;  // 9
+//
+//   my_callback = Callback1<int, int>(add_k);
+//   cout << my_callback(10) << endl;  // 15
+//
+//   my_callback = Callback1<int, int>();
+//   cout << my_callback.empty() << endl;  // true
+
+#ifndef TALK_BASE_CALLBACK_H_
+#define TALK_BASE_CALLBACK_H_
+
+#include "talk/base/logging.h"
+#include "talk/base/refcount.h"
+#include "talk/base/scoped_ref_ptr.h"
+
+namespace talk_base {
+
+template <class R>
+class Callback0 {
+ public:
+  // Default copy operations are appropriate for this class.
+  Callback0() {}
+  template <class T> Callback0(const T& functor)
+      : helper_(new RefCountedObject< HelperImpl<T> >(functor)) {}
+  R operator()() {
+    if (empty()) {
+      LOG_F(LS_WARNING) << "Tried to execute an empty callback.";
+      return R();
+    }
+    return helper_->Run();
+  }
+  bool empty() const { return !helper_; }
+
+ private:
+  struct Helper : RefCountInterface {
+    virtual ~Helper() {}
+    virtual R Run() = 0;
+  };
+  template <class T> struct HelperImpl : Helper {
+    explicit HelperImpl(const T& functor) : functor_(functor) {}
+    virtual R Run() {
+      return functor_();
+    }
+    T functor_;
+  };
+  scoped_refptr<Helper> helper_;
+};
+
+template <class R,
+          class P1>
+class Callback1 {
+ public:
+  // Default copy operations are appropriate for this class.
+  Callback1() {}
+  template <class T> Callback1(const T& functor)
+      : helper_(new RefCountedObject< HelperImpl<T> >(functor)) {}
+  R operator()(P1 p1) {
+    if (empty()) {
+      LOG_F(LS_WARNING) << "Tried to execute an empty callback.";
+      return R();
+    }
+    return helper_->Run(p1);
+  }
+  bool empty() const { return !helper_; }
+
+ private:
+  struct Helper : RefCountInterface {
+    virtual ~Helper() {}
+    virtual R Run(P1 p1) = 0;
+  };
+  template <class T> struct HelperImpl : Helper {
+    explicit HelperImpl(const T& functor) : functor_(functor) {}
+    virtual R Run(P1 p1) {
+      return functor_(p1);
+    }
+    T functor_;
+  };
+  scoped_refptr<Helper> helper_;
+};
+
+template <class R,
+          class P1,
+          class P2>
+class Callback2 {
+ public:
+  // Default copy operations are appropriate for this class.
+  Callback2() {}
+  template <class T> Callback2(const T& functor)
+      : helper_(new RefCountedObject< HelperImpl<T> >(functor)) {}
+  R operator()(P1 p1, P2 p2) {
+    if (empty()) {
+      LOG_F(LS_WARNING) << "Tried to execute an empty callback.";
+      return R();
+    }
+    return helper_->Run(p1, p2);
+  }
+  bool empty() const { return !helper_; }
+
+ private:
+  struct Helper : RefCountInterface {
+    virtual ~Helper() {}
+    virtual R Run(P1 p1, P2 p2) = 0;
+  };
+  template <class T> struct HelperImpl : Helper {
+    explicit HelperImpl(const T& functor) : functor_(functor) {}
+    virtual R Run(P1 p1, P2 p2) {
+      return functor_(p1, p2);
+    }
+    T functor_;
+  };
+  scoped_refptr<Helper> helper_;
+};
+
+template <class R,
+          class P1,
+          class P2,
+          class P3>
+class Callback3 {
+ public:
+  // Default copy operations are appropriate for this class.
+  Callback3() {}
+  template <class T> Callback3(const T& functor)
+      : helper_(new RefCountedObject< HelperImpl<T> >(functor)) {}
+  R operator()(P1 p1, P2 p2, P3 p3) {
+    if (empty()) {
+      LOG_F(LS_WARNING) << "Tried to execute an empty callback.";
+      return R();
+    }
+    return helper_->Run(p1, p2, p3);
+  }
+  bool empty() const { return !helper_; }
+
+ private:
+  struct Helper : RefCountInterface {
+    virtual ~Helper() {}
+    virtual R Run(P1 p1, P2 p2, P3 p3) = 0;
+  };
+  template <class T> struct HelperImpl : Helper {
+    explicit HelperImpl(const T& functor) : functor_(functor) {}
+    virtual R Run(P1 p1, P2 p2, P3 p3) {
+      return functor_(p1, p2, p3);
+    }
+    T functor_;
+  };
+  scoped_refptr<Helper> helper_;
+};
+
+template <class R,
+          class P1,
+          class P2,
+          class P3,
+          class P4>
+class Callback4 {
+ public:
+  // Default copy operations are appropriate for this class.
+  Callback4() {}
+  template <class T> Callback4(const T& functor)
+      : helper_(new RefCountedObject< HelperImpl<T> >(functor)) {}
+  R operator()(P1 p1, P2 p2, P3 p3, P4 p4) {
+    if (empty()) {
+      LOG_F(LS_WARNING) << "Tried to execute an empty callback.";
+      return R();
+    }
+    return helper_->Run(p1, p2, p3, p4);
+  }
+  bool empty() const { return !helper_; }
+
+ private:
+  struct Helper : RefCountInterface {
+    virtual ~Helper() {}
+    virtual R Run(P1 p1, P2 p2, P3 p3, P4 p4) = 0;
+  };
+  template <class T> struct HelperImpl : Helper {
+    explicit HelperImpl(const T& functor) : functor_(functor) {}
+    virtual R Run(P1 p1, P2 p2, P3 p3, P4 p4) {
+      return functor_(p1, p2, p3, p4);
+    }
+    T functor_;
+  };
+  scoped_refptr<Helper> helper_;
+};
+
+template <class R,
+          class P1,
+          class P2,
+          class P3,
+          class P4,
+          class P5>
+class Callback5 {
+ public:
+  // Default copy operations are appropriate for this class.
+  Callback5() {}
+  template <class T> Callback5(const T& functor)
+      : helper_(new RefCountedObject< HelperImpl<T> >(functor)) {}
+  R operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
+    if (empty()) {
+      LOG_F(LS_WARNING) << "Tried to execute an empty callback.";
+      return R();
+    }
+    return helper_->Run(p1, p2, p3, p4, p5);
+  }
+  bool empty() const { return !helper_; }
+
+ private:
+  struct Helper : RefCountInterface {
+    virtual ~Helper() {}
+    virtual R Run(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) = 0;
+  };
+  template <class T> struct HelperImpl : Helper {
+    explicit HelperImpl(const T& functor) : functor_(functor) {}
+    virtual R Run(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
+      return functor_(p1, p2, p3, p4, p5);
+    }
+    T functor_;
+  };
+  scoped_refptr<Helper> helper_;
+};
+}  // namespace talk_base
+
+
+#endif  // TALK_BASE_CALLBACK_H_
diff --git a/talk/base/callback.h.pump b/talk/base/callback.h.pump
new file mode 100644
index 0000000..ae9ab87
--- /dev/null
+++ b/talk/base/callback.h.pump
@@ -0,0 +1,123 @@
+/*
+ * libjingle
+ * Copyright 2012 Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright notice,
+ *     this list of conditions and the following disclaimer in the documentation
+ *     and/or other materials provided with the distribution.
+ *  3. The name of the author may not be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// To generate callback.h from callback.h.pump, execute:
+// /home/build/google3/third_party/gtest/scripts/pump.py callback.h.pump
+
+// Callbacks are callable object containers. They can hold a function pointer
+// or a function object and behave like a value type. Internally, data is
+// reference-counted, making copies and pass-by-value inexpensive.
+//
+// Callbacks are typed using template arguments.  The format is:
+//   CallbackN<ReturnType, ParamType1, ..., ParamTypeN>
+// where N is the number of arguments supplied to the callable object.
+// Callbacks are invoked using operator(), just like a function or a function
+// object. Default-constructed callbacks are "empty," and executing an empty
+// callback does nothing. A callback can be made empty by assigning it from
+// a default-constructed callback.
+//
+// Callbacks are similar in purpose to std::function (which isn't available on
+// all platforms we support) and a lightweight alternative to sigslots. Since
+// they effectively hide the type of the object they call, they're useful in
+// breaking dependencies between objects that need to interact with one another.
+// Notably, they can hold the results of Bind(), std::bind*, etc, without needing
+// to know the resulting object type of those calls.
+//
+// Sigslots, on the other hand, provide a fuller feature set, such as multiple
+// subscriptions to a signal, optional thread-safety, and lifetime tracking of
+// slots. When these features are needed, choose sigslots.
+//
+// Example:
+//   int sqr(int x) { return x * x; }
+//   struct AddK {
+//     int k;
+//     int operator()(int x) const { return x + k; }
+//   } add_k = {5};
+//
+//   Callback1<int, int> my_callback;
+//   cout << my_callback.empty() << endl;  // true
+//
+//   my_callback = Callback1<int, int>(&sqr);
+//   cout << my_callback.empty() << endl;  // false
+//   cout << my_callback(3) << endl;  // 9
+//
+//   my_callback = Callback1<int, int>(add_k);
+//   cout << my_callback(10) << endl;  // 15
+//
+//   my_callback = Callback1<int, int>();
+//   cout << my_callback.empty() << endl;  // true
+
+#ifndef TALK_BASE_CALLBACK_H_
+#define TALK_BASE_CALLBACK_H_
+
+#include "talk/base/logging.h"
+#include "talk/base/refcount.h"
+#include "talk/base/scoped_ref_ptr.h"
+
+namespace talk_base {
+
+$var n = 5
+$range i 0..n
+$for i [[
+$range j 1..i
+
+template <class R$for j [[,
+          class P$j]]>
+class Callback$i {
+ public:
+  // Default copy operations are appropriate for this class.
+  Callback$i() {}
+  template <class T> Callback$i(const T& functor)
+      : helper_(new RefCountedObject< HelperImpl<T> >(functor)) {}
+  R operator()($for j , [[P$j p$j]]) {
+    if (empty()) {
+      LOG_F(LS_WARNING) << "Tried to execute an empty callback.";
+      return R();
+    }
+    return helper_->Run($for j , [[p$j]]);
+  }
+  bool empty() const { return !helper_; }
+
+ private:
+  struct Helper : RefCountInterface {
+    virtual ~Helper() {}
+    virtual R Run($for j , [[P$j p$j]]) = 0;
+  };
+  template <class T> struct HelperImpl : Helper {
+    explicit HelperImpl(const T& functor) : functor_(functor) {}
+    virtual R Run($for j , [[P$j p$j]]) {
+      return functor_($for j , [[p$j]]);
+    }
+    T functor_;
+  };
+  scoped_refptr<Helper> helper_;
+};
+
+]]
+}  // namespace talk_base
+
+#endif  // TALK_BASE_CALLBACK_H_
\ No newline at end of file
diff --git a/talk/base/callback_unittest.cc b/talk/base/callback_unittest.cc
new file mode 100644
index 0000000..c7ca00f
--- /dev/null
+++ b/talk/base/callback_unittest.cc
@@ -0,0 +1,98 @@
+/*
+ * libjingle
+ * Copyright 2004--2011, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright notice,
+ *     this list of conditions and the following disclaimer in the documentation
+ *     and/or other materials provided with the distribution.
+ *  3. The name of the author may not be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/base/bind.h"
+#include "talk/base/callback.h"
+#include "talk/base/gunit.h"
+
+namespace talk_base {
+
+namespace {
+
+void f() {}
+int g() { return 42; }
+int h(int x) { return x * x; }
+void i(int& x) { x *= x; }  // NOLINT: Testing refs
+
+struct BindTester {
+  int a() { return 24; }
+  int b(int x) const { return x * x; }
+};
+
+}  // namespace
+
+TEST(CallbackTest, VoidReturn) {
+  Callback0<void> cb;
+  EXPECT_TRUE(cb.empty());
+  cb();  // Executing an empty callback should not crash.
+  cb = Callback0<void>(&f);
+  EXPECT_FALSE(cb.empty());
+  cb();
+}
+
+TEST(CallbackTest, IntReturn) {
+  Callback0<int> cb;
+  EXPECT_TRUE(cb.empty());
+  cb = Callback0<int>(&g);
+  EXPECT_FALSE(cb.empty());
+  EXPECT_EQ(42, cb());
+  EXPECT_EQ(42, cb());
+}
+
+TEST(CallbackTest, OneParam) {
+  Callback1<int, int> cb1(&h);
+  EXPECT_FALSE(cb1.empty());
+  EXPECT_EQ(9, cb1(-3));
+  EXPECT_EQ(100, cb1(10));
+
+  // Try clearing a callback.
+  cb1 = Callback1<int, int>();
+  EXPECT_TRUE(cb1.empty());
+
+  // Try a callback with a ref parameter.
+  Callback1<void, int&> cb2(&i);
+  int x = 3;
+  cb2(x);
+  EXPECT_EQ(9, x);
+  cb2(x);
+  EXPECT_EQ(81, x);
+}
+
+TEST(CallbackTest, WithBind) {
+  BindTester t;
+  Callback0<int> cb1 = Bind(&BindTester::a, &t);
+  EXPECT_EQ(24, cb1());
+  EXPECT_EQ(24, cb1());
+  cb1 = Bind(&BindTester::b, &t, 10);
+  EXPECT_EQ(100, cb1());
+  EXPECT_EQ(100, cb1());
+  cb1 = Bind(&BindTester::b, &t, 5);
+  EXPECT_EQ(25, cb1());
+  EXPECT_EQ(25, cb1());
+}
+
+}  // namespace talk_base
diff --git a/talk/base/messagehandler.h b/talk/base/messagehandler.h
index 913edf8..8b9e5f6 100644
--- a/talk/base/messagehandler.h
+++ b/talk/base/messagehandler.h
@@ -28,6 +28,7 @@
 #ifndef TALK_BASE_MESSAGEHANDLER_H_
 #define TALK_BASE_MESSAGEHANDLER_H_
 
+#include "talk/base/callback.h"
 #include "talk/base/constructormagic.h"
 
 namespace talk_base {
@@ -38,16 +39,52 @@
 
 class MessageHandler {
  public:
+  virtual ~MessageHandler();
   virtual void OnMessage(Message* msg) = 0;
 
  protected:
   MessageHandler() {}
-  virtual ~MessageHandler();
 
  private:
   DISALLOW_COPY_AND_ASSIGN(MessageHandler);
 };
 
+// Helper class to facilitate executing a functor on a thread.
+template <class ReturnT, class FunctorT>
+class FunctorMessageHandler : public MessageHandler {
+ public:
+  explicit FunctorMessageHandler(const FunctorT& functor)
+      : functor_(functor) {}
+  virtual void OnMessage(Message* msg) {
+    result_ = functor_();
+    if (!callback_.empty()) callback_();
+  }
+  const ReturnT& result() const { return result_; }
+  void SetCallback(const Callback0<void>& callback) { callback_ = callback; }
+ private:
+  FunctorT functor_;
+  ReturnT result_;
+  Callback0<void> callback_;
+};
+
+// Specialization for ReturnT of void.
+template <class FunctorT>
+class FunctorMessageHandler<void, FunctorT> : public MessageHandler {
+ public:
+  explicit FunctorMessageHandler(const FunctorT& functor)
+      : functor_(functor) {}
+  virtual void OnMessage(Message* msg) {
+    functor_();
+    if (!callback_.empty()) callback_();
+  }
+  void result() const {}
+  void SetCallback(const Callback0<void>& callback) { callback_ = callback; }
+ private:
+  FunctorT functor_;
+  Callback0<void> callback_;
+};
+
+
 } // namespace talk_base
 
 #endif // TALK_BASE_MESSAGEHANDLER_H_
diff --git a/talk/base/scopedptrcollection.h b/talk/base/scopedptrcollection.h
new file mode 100644
index 0000000..ec2726e
--- /dev/null
+++ b/talk/base/scopedptrcollection.h
@@ -0,0 +1,77 @@
+/*
+ * libjingle
+ * Copyright 2014 Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright notice,
+ *     this list of conditions and the following disclaimer in the documentation
+ *     and/or other materials provided with the distribution.
+ *  3. The name of the author may not be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Stores a collection of pointers that are deleted when the container is
+// destructed.
+
+#ifndef TALK_BASE_SCOPEDPTRCOLLECTION_H_
+#define TALK_BASE_SCOPEDPTRCOLLECTION_H_
+
+#include <algorithm>
+#include <vector>
+
+#include "talk/base/basictypes.h"
+#include "talk/base/constructormagic.h"
+
+namespace talk_base {
+
+template<class T>
+class ScopedPtrCollection {
+ public:
+  typedef std::vector<T*> VectorT;
+
+  ScopedPtrCollection() { }
+  ~ScopedPtrCollection() {
+    for (typename VectorT::iterator it = collection_.begin();
+         it != collection_.end(); ++it) {
+      delete *it;
+    }
+  }
+
+  const VectorT& collection() const { return collection_; }
+  void Reserve(size_t size) {
+    collection_.reserve(size);
+  }
+  void PushBack(T* t) {
+    collection_.push_back(t);
+  }
+
+  // Remove |t| from the collection without deleting it.
+  void Remove(T* t) {
+    collection_.erase(std::remove(collection_.begin(), collection_.end(), t),
+                      collection_.end());
+  }
+
+ private:
+  VectorT collection_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedPtrCollection);
+};
+
+}  // namespace talk_base
+
+#endif  // TALK_BASE_SCOPEDPTRCOLLECTION_H_
diff --git a/talk/base/scopedptrcollection_unittest.cc b/talk/base/scopedptrcollection_unittest.cc
new file mode 100644
index 0000000..dd9002e
--- /dev/null
+++ b/talk/base/scopedptrcollection_unittest.cc
@@ -0,0 +1,90 @@
+/*
+ * libjingle
+ * Copyright 2014 Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright notice,
+ *     this list of conditions and the following disclaimer in the documentation
+ *     and/or other materials provided with the distribution.
+ *  3. The name of the author may not be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/base/scopedptrcollection.h"
+#include "talk/base/gunit.h"
+
+namespace talk_base {
+
+namespace {
+
+class InstanceCounter {
+ public:
+  explicit InstanceCounter(int* num_instances)
+      : num_instances_(num_instances) {
+    ++(*num_instances_);
+  }
+  ~InstanceCounter() {
+    --(*num_instances_);
+  }
+
+ private:
+  int* num_instances_;
+
+  DISALLOW_COPY_AND_ASSIGN(InstanceCounter);
+};
+
+}  // namespace
+
+class ScopedPtrCollectionTest : public testing::Test {
+ protected:
+  ScopedPtrCollectionTest()
+      : num_instances_(0),
+      collection_(new ScopedPtrCollection<InstanceCounter>()) {
+  }
+
+  int num_instances_;
+  scoped_ptr<ScopedPtrCollection<InstanceCounter> > collection_;
+};
+
+TEST_F(ScopedPtrCollectionTest, PushBack) {
+  EXPECT_EQ(0u, collection_->collection().size());
+  EXPECT_EQ(0, num_instances_);
+  const int kNum = 100;
+  for (int i = 0; i < kNum; ++i) {
+    collection_->PushBack(new InstanceCounter(&num_instances_));
+  }
+  EXPECT_EQ(static_cast<size_t>(kNum), collection_->collection().size());
+  EXPECT_EQ(kNum, num_instances_);
+  collection_.reset();
+  EXPECT_EQ(0, num_instances_);
+}
+
+TEST_F(ScopedPtrCollectionTest, Remove) {
+  InstanceCounter* ic = new InstanceCounter(&num_instances_);
+  collection_->PushBack(ic);
+  EXPECT_EQ(1u, collection_->collection().size());
+  collection_->Remove(ic);
+  EXPECT_EQ(1, num_instances_);
+  collection_.reset();
+  EXPECT_EQ(1, num_instances_);
+  delete ic;
+  EXPECT_EQ(0, num_instances_);
+}
+
+
+}  // namespace talk_base
diff --git a/talk/base/thread.h b/talk/base/thread.h
index 4dc09f6..316f041 100644
--- a/talk/base/thread.h
+++ b/talk/base/thread.h
@@ -223,33 +223,6 @@
   void Join();
 
  private:
-  // Helper class to facilitate executing a functor on a thread.
-  template <class ReturnT, class FunctorT>
-  class FunctorMessageHandler : public MessageHandler {
-   public:
-    explicit FunctorMessageHandler(const FunctorT& functor)
-        : functor_(functor) {}
-    virtual void OnMessage(Message* msg) {
-      result_ = functor_();
-    }
-    const ReturnT& result() const { return result_; }
-   private:
-    FunctorT functor_;
-    ReturnT result_;
-  };
-
-  // Specialization for ReturnT of void.
-  template <class FunctorT>
-  class FunctorMessageHandler<void, FunctorT> : public MessageHandler {
-   public:
-    explicit FunctorMessageHandler(const FunctorT& functor)
-        : functor_(functor) {}
-    virtual void OnMessage(Message* msg) { functor_(); }
-    void result() const {}
-   private:
-    FunctorT functor_;
-  };
-
   static void *PreRun(void *pv);
 
   // ThreadManager calls this instead WrapCurrent() because
diff --git a/talk/base/thread_unittest.cc b/talk/base/thread_unittest.cc
index 896fbab..ddf6326 100644
--- a/talk/base/thread_unittest.cc
+++ b/talk/base/thread_unittest.cc
@@ -25,6 +25,7 @@
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include "talk/base/asyncinvoker.h"
 #include "talk/base/asyncudpsocket.h"
 #include "talk/base/event.h"
 #include "talk/base/gunit.h"
@@ -150,16 +151,22 @@
 };
 
 // Function objects to test Thread::Invoke.
-struct Functor1 {
+struct FunctorA {
   int operator()() { return 42; }
 };
-class Functor2 {
+class FunctorB {
  public:
-  explicit Functor2(bool* flag) : flag_(flag) {}
+  explicit FunctorB(bool* flag) : flag_(flag) {}
   void operator()() { if (flag_) *flag_ = true; }
  private:
   bool* flag_;
 };
+struct FunctorC {
+  int operator()() {
+    Thread::Current()->ProcessMessages(50);
+    return 24;
+  }
+};
 
 // See: https://code.google.com/p/webrtc/issues/detail?id=2409
 TEST(ThreadTest, DISABLED_Main) {
@@ -289,9 +296,9 @@
   Thread thread;
   thread.Start();
   // Try calling functors.
-  EXPECT_EQ(42, thread.Invoke<int>(Functor1()));
+  EXPECT_EQ(42, thread.Invoke<int>(FunctorA()));
   bool called = false;
-  Functor2 f2(&called);
+  FunctorB f2(&called);
   thread.Invoke<void>(f2);
   EXPECT_TRUE(called);
   // Try calling bare functions.
@@ -303,6 +310,152 @@
   thread.Invoke<void>(&LocalFuncs::Func2);
 }
 
+class AsyncInvokeTest : public testing::Test {
+ public:
+  void IntCallback(int value) {
+    EXPECT_EQ(expected_thread_, Thread::Current());
+    int_value_ = value;
+  }
+  void AsyncInvokeIntCallback(AsyncInvoker* invoker, Thread* thread) {
+    expected_thread_ = thread;
+    invoker->AsyncInvoke(thread, FunctorC(),
+                         &AsyncInvokeTest::IntCallback,
+                         static_cast<AsyncInvokeTest*>(this));
+    invoke_started_.Set();
+  }
+  void SetExpectedThreadForIntCallback(Thread* thread) {
+    expected_thread_ = thread;
+  }
+
+ protected:
+  enum { kWaitTimeout = 1000 };
+  AsyncInvokeTest()
+      : int_value_(0),
+        invoke_started_(true, false),
+        expected_thread_(NULL) {}
+
+  int int_value_;
+  Event invoke_started_;
+  Thread* expected_thread_;
+};
+
+TEST_F(AsyncInvokeTest, FireAndForget) {
+  AsyncInvoker invoker;
+  // Create and start the thread.
+  Thread thread;
+  thread.Start();
+  // Try calling functor.
+  bool called = false;
+  invoker.AsyncInvoke<void>(&thread, FunctorB(&called));
+  EXPECT_TRUE_WAIT(called, kWaitTimeout);
+}
+
+TEST_F(AsyncInvokeTest, WithCallback) {
+  AsyncInvoker invoker;
+  // Create and start the thread.
+  Thread thread;
+  thread.Start();
+  // Try calling functor.
+  SetExpectedThreadForIntCallback(Thread::Current());
+  invoker.AsyncInvoke(&thread, FunctorA(),
+                      &AsyncInvokeTest::IntCallback,
+                      static_cast<AsyncInvokeTest*>(this));
+  EXPECT_EQ_WAIT(42, int_value_, kWaitTimeout);
+}
+
+TEST_F(AsyncInvokeTest, CancelInvoker) {
+  // Create and start the thread.
+  Thread thread;
+  thread.Start();
+  // Try destroying invoker during call.
+  {
+    AsyncInvoker invoker;
+    invoker.AsyncInvoke(&thread, FunctorC(),
+                        &AsyncInvokeTest::IntCallback,
+                        static_cast<AsyncInvokeTest*>(this));
+  }
+  // With invoker gone, callback should be cancelled.
+  Thread::Current()->ProcessMessages(kWaitTimeout);
+  EXPECT_EQ(0, int_value_);
+}
+
+TEST_F(AsyncInvokeTest, CancelCallingThread) {
+  AsyncInvoker invoker;
+  { // Create and start the thread.
+    Thread thread;
+    thread.Start();
+    // Try calling functor.
+    thread.Invoke<void>(Bind(&AsyncInvokeTest::AsyncInvokeIntCallback,
+                             static_cast<AsyncInvokeTest*>(this),
+                             &invoker, Thread::Current()));
+    // Wait for the call to begin.
+    ASSERT_TRUE(invoke_started_.Wait(kWaitTimeout));
+  }
+  // Calling thread is gone. Return message shouldn't happen.
+  Thread::Current()->ProcessMessages(kWaitTimeout);
+  EXPECT_EQ(0, int_value_);
+}
+
+TEST_F(AsyncInvokeTest, KillInvokerBeforeExecute) {
+  Thread thread;
+  thread.Start();
+  {
+    AsyncInvoker invoker;
+    // Try calling functor.
+    thread.Invoke<void>(Bind(&AsyncInvokeTest::AsyncInvokeIntCallback,
+                             static_cast<AsyncInvokeTest*>(this),
+                             &invoker, Thread::Current()));
+    // Wait for the call to begin.
+    ASSERT_TRUE(invoke_started_.Wait(kWaitTimeout));
+  }
+  // Invoker is destroyed. Function should not execute.
+  Thread::Current()->ProcessMessages(kWaitTimeout);
+  EXPECT_EQ(0, int_value_);
+}
+
+TEST_F(AsyncInvokeTest, Flush) {
+  AsyncInvoker invoker;
+  bool flag1 = false;
+  bool flag2 = false;
+  // Queue two async calls to the current thread.
+  invoker.AsyncInvoke<void>(Thread::Current(),
+                            FunctorB(&flag1));
+  invoker.AsyncInvoke<void>(Thread::Current(),
+                            FunctorB(&flag2));
+  // Because we haven't pumped messages, these should not have run yet.
+  EXPECT_FALSE(flag1);
+  EXPECT_FALSE(flag2);
+  // Force them to run now.
+  invoker.Flush(Thread::Current());
+  EXPECT_TRUE(flag1);
+  EXPECT_TRUE(flag2);
+}
+
+TEST_F(AsyncInvokeTest, FlushWithIds) {
+  AsyncInvoker invoker;
+  bool flag1 = false;
+  bool flag2 = false;
+  // Queue two async calls to the current thread, one with a message id.
+  invoker.AsyncInvoke<void>(Thread::Current(),
+                            FunctorB(&flag1),
+                            5);
+  invoker.AsyncInvoke<void>(Thread::Current(),
+                            FunctorB(&flag2));
+  // Because we haven't pumped messages, these should not have run yet.
+  EXPECT_FALSE(flag1);
+  EXPECT_FALSE(flag2);
+  // Execute pending calls with id == 5.
+  invoker.Flush(Thread::Current(), 5);
+  EXPECT_TRUE(flag1);
+  EXPECT_FALSE(flag2);
+  flag1 = false;
+  // Execute all pending calls. The id == 5 call should not execute again.
+  invoker.Flush(Thread::Current());
+  EXPECT_FALSE(flag1);
+  EXPECT_TRUE(flag2);
+}
+
+
 #ifdef WIN32
 class ComThreadTest : public testing::Test, public MessageHandler {
  public: