(Auto)update libjingle 61549749-> 61608469
git-svn-id: http://webrtc.googlecode.com/svn/trunk@5555 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/talk/base/asyncinvoker-inl.h b/talk/base/asyncinvoker-inl.h
index c4afd3a..b6be175 100644
--- a/talk/base/asyncinvoker-inl.h
+++ b/talk/base/asyncinvoker-inl.h
@@ -28,74 +28,119 @@
#ifndef TALK_BASE_ASYNCINVOKER_INL_H_
#define TALK_BASE_ASYNCINVOKER_INL_H_
+#include "talk/base/bind.h"
+#include "talk/base/callback.h"
#include "talk/base/criticalsection.h"
#include "talk/base/messagehandler.h"
+#include "talk/base/refcount.h"
+#include "talk/base/scoped_ref_ptr.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;
+class AsyncInvoker;
+
+// Helper class for AsyncInvoker. Runs a task and triggers a callback
+// on the calling thread if necessary. Instances are ref-counted so their
+// lifetime can be independent of AsyncInvoker.
+class AsyncClosure : public RefCountInterface {
public:
- explicit AsyncFunctorMessageHandler(const FunctorT& functor)
- : FunctorMessageHandler<ReturnT, FunctorT>(functor),
- thread_(Thread::Current()),
- shutting_down_(false) {
- thread_->SignalQueueDestroyed.connect(this, &ThisT::OnThreadDestroyed);
- }
+ virtual ~AsyncClosure() {}
+ // Runs the asynchronous task, and triggers a callback to the calling
+ // thread if needed. Should be called from the target thread.
+ virtual void Execute() = 0;
+};
- virtual ~AsyncFunctorMessageHandler() {
- CritScope cs(&running_crit_);
- shutting_down_ = true;
+// Simple closure that doesn't trigger a callback for the calling thread.
+template <class FunctorT>
+class FireAndForgetAsyncClosure : public AsyncClosure {
+ public:
+ explicit FireAndForgetAsyncClosure(const FunctorT& functor)
+ : functor_(functor) {}
+ virtual void Execute() {
+ functor_();
}
+ private:
+ FunctorT functor_;
+};
- virtual void OnMessage(Message* msg) {
- CritScope cs(&running_crit_);
- if (!shutting_down_) {
- FunctorMessageHandler<ReturnT, FunctorT>::OnMessage(msg);
+// Base class for closures that may trigger a callback for the calling thread.
+// Listens for the "destroyed" signals from the calling thread and the invoker,
+// and cancels the callback to the calling thread if either is destroyed.
+class NotifyingAsyncClosureBase : public AsyncClosure,
+ public sigslot::has_slots<> {
+ public:
+ virtual ~NotifyingAsyncClosureBase() { disconnect_all(); }
+
+ protected:
+ NotifyingAsyncClosureBase(AsyncInvoker* invoker, Thread* calling_thread);
+ void TriggerCallback();
+ void SetCallback(const Callback0<void>& callback) {
+ CritScope cs(&crit_);
+ callback_ = callback;
+ }
+ bool CallbackCanceled() const { return calling_thread_ == NULL; }
+
+ private:
+ Callback0<void> callback_;
+ CriticalSection crit_;
+ AsyncInvoker* invoker_;
+ Thread* calling_thread_;
+
+ void CancelCallback();
+};
+
+// Closures that have a non-void return value and require a callback.
+template <class ReturnT, class FunctorT, class HostT>
+class NotifyingAsyncClosure : public NotifyingAsyncClosureBase {
+ public:
+ NotifyingAsyncClosure(AsyncInvoker* invoker,
+ Thread* calling_thread,
+ const FunctorT& functor,
+ void (HostT::*callback)(ReturnT),
+ HostT* callback_host)
+ : NotifyingAsyncClosureBase(invoker, calling_thread),
+ functor_(functor),
+ callback_(callback),
+ callback_host_(callback_host) {}
+ virtual void Execute() {
+ ReturnT result = functor_();
+ if (!CallbackCanceled()) {
+ SetCallback(Callback0<void>(Bind(callback_, callback_host_, result)));
+ TriggerCallback();
}
}
- // 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_;
+ void (HostT::*callback_)(ReturnT);
+ HostT* callback_host_;
+};
+
+// Closures that have a void return value and require a callback.
+template <class FunctorT, class HostT>
+class NotifyingAsyncClosure<void, FunctorT, HostT>
+ : public NotifyingAsyncClosureBase {
+ public:
+ NotifyingAsyncClosure(AsyncInvoker* invoker,
+ Thread* calling_thread,
+ const FunctorT& functor,
+ void (HostT::*callback)(),
+ HostT* callback_host)
+ : NotifyingAsyncClosureBase(invoker, calling_thread),
+ functor_(functor) {
+ SetCallback(Callback0<void>(Bind(callback, callback_host)));
+ }
+ virtual void Execute() {
+ functor_();
+ TriggerCallback();
+ }
+
+ private:
+ FunctorT functor_;
};
} // namespace talk_base
-
#endif // TALK_BASE_ASYNCINVOKER_INL_H_
diff --git a/talk/base/asyncinvoker.cc b/talk/base/asyncinvoker.cc
index 63171be..a57eb7b 100644
--- a/talk/base/asyncinvoker.cc
+++ b/talk/base/asyncinvoker.cc
@@ -29,50 +29,80 @@
namespace talk_base {
-// Synchronously execute all outstanding calls we own pending
-// on |thread|. Optionally filter by message id.
+AsyncInvoker::AsyncInvoker() : destroying_(false) {}
+
+AsyncInvoker::~AsyncInvoker() {
+ destroying_ = true;
+ SignalInvokerDestroyed();
+ // Messages for this need to be cleared *before* our destructor is complete.
+ MessageQueueManager::Clear(this);
+}
+
+void AsyncInvoker::OnMessage(Message* msg) {
+ // Get the AsyncClosure shared ptr from this message's data.
+ ScopedRefMessageData<AsyncClosure>* data =
+ static_cast<ScopedRefMessageData<AsyncClosure>*>(msg->pdata);
+ scoped_refptr<AsyncClosure> closure = data->data();
+ delete msg->pdata;
+ msg->pdata = NULL;
+
+ // Execute the closure and trigger the return message if needed.
+ closure->Execute();
+}
+
void AsyncInvoker::Flush(Thread* thread, uint32 id /*= MQID_ANY*/) {
+ if (destroying_) return;
+
// 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);
- }
+ thread->Clear(this, id, &removed);
+ for (MessageList::iterator it = removed.begin(); it != removed.end(); ++it) {
+ // This message was pending on this thread, so run it now.
+ thread->Send(it->phandler,
+ it->message_id,
+ it->pdata);
}
}
-void AsyncInvoker::InvokeHandler(Thread* thread, MessageHandler* handler,
- uint32 id) {
- {
- CritScope cs(&crit_);
- handlers_.PushBack(handler);
+void AsyncInvoker::DoInvoke(Thread* thread, AsyncClosure* closure,
+ uint32 id) {
+ if (destroying_) {
+ LOG(LS_WARNING) << "Tried to invoke while destroying the invoker.";
+ // Since this call transwers ownership of |closure|, we clean it up here.
+ delete closure;
+ return;
}
- thread->Post(handler, id);
+ thread->Post(this, id, new ScopedRefMessageData<AsyncClosure>(closure));
}
-void AsyncInvoker::RemoveHandler(MessageHandler* handler) {
+NotifyingAsyncClosureBase::NotifyingAsyncClosureBase(AsyncInvoker* invoker,
+ Thread* calling_thread)
+ : invoker_(invoker), calling_thread_(calling_thread) {
+ calling_thread->SignalQueueDestroyed.connect(
+ this, &NotifyingAsyncClosureBase::CancelCallback);
+ invoker->SignalInvokerDestroyed.connect(
+ this, &NotifyingAsyncClosureBase::CancelCallback);
+}
+
+void NotifyingAsyncClosureBase::TriggerCallback() {
CritScope cs(&crit_);
- handlers_.Remove(handler);
- delete handler;
+ if (!CallbackCanceled() && !callback_.empty()) {
+ invoker_->AsyncInvoke<void>(calling_thread_, callback_);
+ }
+}
+
+void NotifyingAsyncClosureBase::CancelCallback() {
+ // If the callback is triggering when this is called, block the
+ // destructor of the dying object here by waiting until the callback
+ // is done triggering.
+ CritScope cs(&crit_);
+ // calling_thread_ == NULL means do not trigger the callback.
+ calling_thread_ = NULL;
}
} // namespace talk_base
diff --git a/talk/base/asyncinvoker.h b/talk/base/asyncinvoker.h
index fabdbdc..b7dfac9 100644
--- a/talk/base/asyncinvoker.h
+++ b/talk/base/asyncinvoker.h
@@ -30,6 +30,7 @@
#include "talk/base/asyncinvoker-inl.h"
#include "talk/base/bind.h"
+#include "talk/base/sigslot.h"
#include "talk/base/scopedptrcollection.h"
#include "talk/base/thread.h"
@@ -82,18 +83,20 @@
// AsyncInvoker invoker_;
// int result_;
// };
-class AsyncInvoker {
+class AsyncInvoker : public MessageHandler {
public:
+ AsyncInvoker();
+ virtual ~AsyncInvoker();
+
// 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);
+ AsyncClosure* closure =
+ new RefCountedObject<FireAndForgetAsyncClosure<FunctorT> >(functor);
+ DoInvoke(thread, closure, id);
}
// Call |functor| asynchronously on |thread|, calling |callback| when done.
@@ -103,12 +106,10 @@
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);
+ AsyncClosure* closure =
+ new RefCountedObject<NotifyingAsyncClosure<ReturnT, FunctorT, HostT> >(
+ this, Thread::Current(), functor, callback, callback_host);
+ DoInvoke(thread, closure, id);
}
// Call |functor| asynchronously on |thread|, calling |callback| when done.
@@ -119,12 +120,10 @@
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);
+ AsyncClosure* closure =
+ new RefCountedObject<NotifyingAsyncClosure<void, FunctorT, HostT> >(
+ this, Thread::Current(), functor, callback, callback_host);
+ DoInvoke(thread, closure, id);
}
// Synchronously execute on |thread| all outstanding calls we own
@@ -134,31 +133,16 @@
// behavior is desired, call Flush() before destroying this object.
void Flush(Thread* thread, uint32 id = MQID_ANY);
+ // Signaled when this object is destructed.
+ sigslot::signal0<> SignalInvokerDestroyed;
+
private:
- void InvokeHandler(Thread* thread, MessageHandler* handler, uint32 id);
- void RemoveHandler(MessageHandler* handler);
+ virtual void OnMessage(Message* msg);
+ void DoInvoke(Thread* thread, AsyncClosure* closure, uint32 id);
- 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);
- }
+ bool destroying_;
- 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_;
+ DISALLOW_COPY_AND_ASSIGN(AsyncInvoker);
};
} // namespace talk_base
diff --git a/talk/base/messagehandler.h b/talk/base/messagehandler.h
index 8b9e5f6..6494f2b 100644
--- a/talk/base/messagehandler.h
+++ b/talk/base/messagehandler.h
@@ -28,7 +28,6 @@
#ifndef TALK_BASE_MESSAGEHANDLER_H_
#define TALK_BASE_MESSAGEHANDLER_H_
-#include "talk/base/callback.h"
#include "talk/base/constructormagic.h"
namespace talk_base {
@@ -57,14 +56,12 @@
: 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.
@@ -75,13 +72,11 @@
: 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_;
};
diff --git a/talk/base/thread_unittest.cc b/talk/base/thread_unittest.cc
index 728e321..ddf6326 100644
--- a/talk/base/thread_unittest.cc
+++ b/talk/base/thread_unittest.cc
@@ -339,7 +339,7 @@
Thread* expected_thread_;
};
-TEST_F(AsyncInvokeTest, DISABLED_FireAndForget) {
+TEST_F(AsyncInvokeTest, FireAndForget) {
AsyncInvoker invoker;
// Create and start the thread.
Thread thread;
@@ -350,7 +350,7 @@
EXPECT_TRUE_WAIT(called, kWaitTimeout);
}
-TEST_F(AsyncInvokeTest, DISABLED_WithCallback) {
+TEST_F(AsyncInvokeTest, WithCallback) {
AsyncInvoker invoker;
// Create and start the thread.
Thread thread;
@@ -363,7 +363,7 @@
EXPECT_EQ_WAIT(42, int_value_, kWaitTimeout);
}
-TEST_F(AsyncInvokeTest, DISABLED_CancelInvoker) {
+TEST_F(AsyncInvokeTest, CancelInvoker) {
// Create and start the thread.
Thread thread;
thread.Start();
@@ -379,7 +379,7 @@
EXPECT_EQ(0, int_value_);
}
-TEST_F(AsyncInvokeTest, DISABLED_CancelCallingThread) {
+TEST_F(AsyncInvokeTest, CancelCallingThread) {
AsyncInvoker invoker;
{ // Create and start the thread.
Thread thread;
@@ -396,7 +396,7 @@
EXPECT_EQ(0, int_value_);
}
-TEST_F(AsyncInvokeTest, DISABLED_KillInvokerBeforeExecute) {
+TEST_F(AsyncInvokeTest, KillInvokerBeforeExecute) {
Thread thread;
thread.Start();
{
@@ -413,7 +413,7 @@
EXPECT_EQ(0, int_value_);
}
-TEST_F(AsyncInvokeTest, DISABLED_Flush) {
+TEST_F(AsyncInvokeTest, Flush) {
AsyncInvoker invoker;
bool flag1 = false;
bool flag2 = false;
@@ -431,7 +431,7 @@
EXPECT_TRUE(flag2);
}
-TEST_F(AsyncInvokeTest, DISABLED_FlushWithIds) {
+TEST_F(AsyncInvokeTest, FlushWithIds) {
AsyncInvoker invoker;
bool flag1 = false;
bool flag2 = false;
diff --git a/talk/media/base/mediachannel.h b/talk/media/base/mediachannel.h
index 239798c..1a84704 100644
--- a/talk/media/base/mediachannel.h
+++ b/talk/media/base/mediachannel.h
@@ -749,7 +749,13 @@
jitter_buffer_preferred_ms(0),
delay_estimate_ms(0),
audio_level(0),
- expand_rate(0) {
+ expand_rate(0),
+ decoding_calls_to_silence_generator(0),
+ decoding_calls_to_neteq(0),
+ decoding_normal(0),
+ decoding_plc(0),
+ decoding_cng(0),
+ decoding_plc_cng(0) {
}
int ext_seqnum;
@@ -760,6 +766,12 @@
int audio_level;
// fraction of synthesized speech inserted through pre-emptive expansion
float expand_rate;
+ int decoding_calls_to_silence_generator;
+ int decoding_calls_to_neteq;
+ int decoding_normal;
+ int decoding_plc;
+ int decoding_cng;
+ int decoding_plc_cng;
};
struct VideoSenderInfo : public MediaSenderInfo {
diff --git a/talk/media/webrtc/webrtcvoiceengine.cc b/talk/media/webrtc/webrtcvoiceengine.cc
index f1030bd..e2415cf 100644
--- a/talk/media/webrtc/webrtcvoiceengine.cc
+++ b/talk/media/webrtc/webrtcvoiceengine.cc
@@ -3200,6 +3200,20 @@
rinfo.expand_rate =
static_cast<float>(ns.currentExpandRate) / (1 << 14);
}
+
+ webrtc::AudioDecodingCallStats ds;
+ if (engine()->voe()->neteq() &&
+ engine()->voe()->neteq()->GetDecodingCallStatistics(
+ *it, &ds) != -1) {
+ rinfo.decoding_calls_to_silence_generator =
+ ds.calls_to_silence_generator;
+ rinfo.decoding_calls_to_neteq = ds.calls_to_neteq;
+ rinfo.decoding_normal = ds.decoded_normal;
+ rinfo.decoding_plc = ds.decoded_plc;
+ rinfo.decoding_cng = ds.decoded_cng;
+ rinfo.decoding_plc_cng = ds.decoded_plc_cng;
+ }
+
if (engine()->voe()->sync()) {
int jitter_buffer_delay_ms = 0;
int playout_buffer_delay_ms = 0;