Add a facility to the Thread class to catch blocking regressions.
This facility should be used in methods that run on known threads (e.g. signaling, worker) and do not have blocking thread syncronization operations via the Thread class such as Invoke, Sleep, etc. This is a reland of an already reviewed cl (r6679) that got reverted by mistake. TBR=xians@google.com,tommi@webrtc.org Review URL: https://webrtc-codereview.appspot.com/21889004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@6682 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
b038c72369
commit
1b84116417
@ -142,6 +142,16 @@ struct ThreadInit {
|
|||||||
Runnable* runnable;
|
Runnable* runnable;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Thread::ScopedDisallowBlockingCalls::ScopedDisallowBlockingCalls()
|
||||||
|
: thread_(Thread::Current()),
|
||||||
|
previous_state_(thread_->SetAllowBlockingCalls(false)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread::ScopedDisallowBlockingCalls::~ScopedDisallowBlockingCalls() {
|
||||||
|
ASSERT(thread_->IsCurrent());
|
||||||
|
thread_->SetAllowBlockingCalls(previous_state_);
|
||||||
|
}
|
||||||
|
|
||||||
Thread::Thread(SocketServer* ss)
|
Thread::Thread(SocketServer* ss)
|
||||||
: MessageQueue(ss),
|
: MessageQueue(ss),
|
||||||
priority_(PRIORITY_NORMAL),
|
priority_(PRIORITY_NORMAL),
|
||||||
@ -150,7 +160,8 @@ Thread::Thread(SocketServer* ss)
|
|||||||
thread_(NULL),
|
thread_(NULL),
|
||||||
thread_id_(0),
|
thread_id_(0),
|
||||||
#endif
|
#endif
|
||||||
owned_(true) {
|
owned_(true),
|
||||||
|
blocking_calls_allowed_(true) {
|
||||||
SetName("Thread", this); // default name
|
SetName("Thread", this); // default name
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,6 +171,8 @@ Thread::~Thread() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Thread::SleepMs(int milliseconds) {
|
bool Thread::SleepMs(int milliseconds) {
|
||||||
|
AssertBlockingIsAllowedOnCurrentThread();
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
::Sleep(milliseconds);
|
::Sleep(milliseconds);
|
||||||
return true;
|
return true;
|
||||||
@ -293,6 +306,8 @@ bool Thread::Start(Runnable* runnable) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Thread::Join() {
|
void Thread::Join() {
|
||||||
|
AssertBlockingIsAllowedOnCurrentThread();
|
||||||
|
|
||||||
if (running()) {
|
if (running()) {
|
||||||
ASSERT(!IsCurrent());
|
ASSERT(!IsCurrent());
|
||||||
#if defined(WIN32)
|
#if defined(WIN32)
|
||||||
@ -308,6 +323,21 @@ void Thread::Join() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Thread::SetAllowBlockingCalls(bool allow) {
|
||||||
|
ASSERT(IsCurrent());
|
||||||
|
bool previous = blocking_calls_allowed_;
|
||||||
|
blocking_calls_allowed_ = allow;
|
||||||
|
return previous;
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void Thread::AssertBlockingIsAllowedOnCurrentThread() {
|
||||||
|
#ifdef _DEBUG
|
||||||
|
Thread* current = Thread::Current();
|
||||||
|
ASSERT(!current || current->blocking_calls_allowed_);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
// As seen on MSDN.
|
// As seen on MSDN.
|
||||||
// http://msdn.microsoft.com/en-us/library/xcb2z8hs(VS.71).aspx
|
// http://msdn.microsoft.com/en-us/library/xcb2z8hs(VS.71).aspx
|
||||||
@ -374,6 +404,8 @@ void Thread::Stop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Thread::Send(MessageHandler *phandler, uint32 id, MessageData *pdata) {
|
void Thread::Send(MessageHandler *phandler, uint32 id, MessageData *pdata) {
|
||||||
|
AssertBlockingIsAllowedOnCurrentThread();
|
||||||
|
|
||||||
if (fStop_)
|
if (fStop_)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -125,6 +125,19 @@ class Thread : public MessageQueue {
|
|||||||
|
|
||||||
static Thread* Current();
|
static Thread* Current();
|
||||||
|
|
||||||
|
// Used to catch performance regressions. Use this to disallow blocking calls
|
||||||
|
// (Invoke) for a given scope. If a synchronous call is made while this is in
|
||||||
|
// effect, an assert will be triggered.
|
||||||
|
// Note that this is a single threaded class.
|
||||||
|
class ScopedDisallowBlockingCalls {
|
||||||
|
public:
|
||||||
|
ScopedDisallowBlockingCalls();
|
||||||
|
~ScopedDisallowBlockingCalls();
|
||||||
|
private:
|
||||||
|
Thread* const thread_;
|
||||||
|
const bool previous_state_;
|
||||||
|
};
|
||||||
|
|
||||||
bool IsCurrent() const {
|
bool IsCurrent() const {
|
||||||
return Current() == this;
|
return Current() == this;
|
||||||
}
|
}
|
||||||
@ -165,8 +178,11 @@ class Thread : public MessageQueue {
|
|||||||
// Uses Send() internally, which blocks the current thread until execution
|
// Uses Send() internally, which blocks the current thread until execution
|
||||||
// is complete.
|
// is complete.
|
||||||
// Ex: bool result = thread.Invoke<bool>(&MyFunctionReturningBool);
|
// Ex: bool result = thread.Invoke<bool>(&MyFunctionReturningBool);
|
||||||
|
// NOTE: This function can only be called when synchronous calls are allowed.
|
||||||
|
// See ScopedDisallowBlockingCalls for details.
|
||||||
template <class ReturnT, class FunctorT>
|
template <class ReturnT, class FunctorT>
|
||||||
ReturnT Invoke(const FunctorT& functor) {
|
ReturnT Invoke(const FunctorT& functor) {
|
||||||
|
AssertBlockingIsAllowedOnCurrentThread();
|
||||||
FunctorMessageHandler<ReturnT, FunctorT> handler(functor);
|
FunctorMessageHandler<ReturnT, FunctorT> handler(functor);
|
||||||
Send(&handler);
|
Send(&handler);
|
||||||
return handler.result();
|
return handler.result();
|
||||||
@ -229,6 +245,14 @@ class Thread : public MessageQueue {
|
|||||||
// Blocks the calling thread until this thread has terminated.
|
// Blocks the calling thread until this thread has terminated.
|
||||||
void Join();
|
void Join();
|
||||||
|
|
||||||
|
// Sets the per-thread allow-blocking-calls flag and returns the previous
|
||||||
|
// value.
|
||||||
|
bool SetAllowBlockingCalls(bool allow);
|
||||||
|
|
||||||
|
static void AssertBlockingIsAllowedOnCurrentThread();
|
||||||
|
|
||||||
|
friend class ScopedDisallowBlockingCalls;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void *PreRun(void *pv);
|
static void *PreRun(void *pv);
|
||||||
|
|
||||||
@ -255,6 +279,7 @@ class Thread : public MessageQueue {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool owned_;
|
bool owned_;
|
||||||
|
bool blocking_calls_allowed_; // By default set to |true|.
|
||||||
|
|
||||||
friend class ThreadManager;
|
friend class ThreadManager;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user