Index: jingle/notifier/base/signal_thread_task.h |
diff --git a/jingle/notifier/base/signal_thread_task.h b/jingle/notifier/base/signal_thread_task.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..8a6ff271b79ced3be9fac0aad67b56e042bf35d0 |
--- /dev/null |
+++ b/jingle/notifier/base/signal_thread_task.h |
@@ -0,0 +1,96 @@ |
+// Copyright (c) 2009 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#ifndef JINGLE_NOTIFIER_BASE_SIGNAL_THREAD_TASK_H_ |
+#define JINGLE_NOTIFIER_BASE_SIGNAL_THREAD_TASK_H_ |
+ |
+#include "base/logging.h" |
+#include "talk/base/common.h" |
+#include "talk/base/signalthread.h" |
+#include "talk/base/sigslot.h" |
+#include "talk/base/task.h" |
+ |
+namespace notifier { |
+ |
+template<class T> |
+class SignalThreadTask : public talk_base::Task, |
+ public sigslot::has_slots<> { |
+ public: |
+ // Takes ownership of signal_thread. |
+ SignalThreadTask(talk_base::Task* task_parent, T** signal_thread) |
+ : talk_base::Task(task_parent), |
+ signal_thread_(NULL), |
+ finished_(false) { |
+ SetSignalThread(signal_thread); |
+ } |
+ |
+ virtual ~SignalThreadTask() { |
+ ClearSignalThread(); |
+ } |
+ |
+ virtual void Stop() { |
+ Task::Stop(); |
+ ClearSignalThread(); |
+ } |
+ |
+ virtual int ProcessStart() { |
+ DCHECK_EQ(GetState(), talk_base::Task::STATE_START); |
+ signal_thread_->SignalWorkDone.connect( |
+ this, |
+ &SignalThreadTask<T>::OnWorkDone); |
+ signal_thread_->Start(); |
+ return talk_base::Task::STATE_RESPONSE; |
+ } |
+ |
+ int ProcessResponse() { |
+ if (!finished_) { |
+ return talk_base::Task::STATE_BLOCKED; |
+ } |
+ SignalWorkDone(signal_thread_); |
+ ClearSignalThread(); |
+ return talk_base::Task::STATE_DONE; |
+ } |
+ |
+ sigslot::signal1<T*> SignalWorkDone; |
+ |
+ private: |
+ // Takes ownership of signal_thread. |
+ void SetSignalThread(T** signal_thread) { |
+ DCHECK(!signal_thread_); |
+ DCHECK(signal_thread); |
+ DCHECK(*signal_thread); |
+ // No one should be listening to the signal thread for work done. |
+ // They should be using this class instead. Unfortunately, we |
+ // can't verify this. |
+ |
+ signal_thread_ = *signal_thread; |
+ |
+ // Helps callers not to use signal thread after this point since this class |
+ // has taken ownership (and avoid the error of doing |
+ // signal_thread->Start()). |
+ *signal_thread = NULL; |
+ } |
+ |
+ void OnWorkDone(talk_base::SignalThread* signal_thread) { |
+ DCHECK_EQ(signal_thread, signal_thread_); |
+ finished_ = true; |
+ Wake(); |
+ } |
+ |
+ void ClearSignalThread() { |
+ if (signal_thread_) { |
+ // Don't wait on the thread destruction, or we may deadlock. |
+ signal_thread_->Destroy(false); |
+ signal_thread_ = NULL; |
+ } |
+ } |
+ |
+ T* signal_thread_; |
+ bool finished_; |
+ DISALLOW_COPY_AND_ASSIGN(SignalThreadTask); |
+}; |
+ |
+} // namespace notifier |
+ |
+#endif // JINGLE_NOTIFIER_BASE_SIGNAL_THREAD_TASK_H_ |