OLD | NEW |
| (Empty) |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #ifndef JINGLE_NOTIFIER_BASE_SIGNAL_THREAD_TASK_H_ | |
6 #define JINGLE_NOTIFIER_BASE_SIGNAL_THREAD_TASK_H_ | |
7 | |
8 #include "base/logging.h" | |
9 #include "talk/base/common.h" | |
10 #include "talk/base/signalthread.h" | |
11 #include "talk/base/sigslot.h" | |
12 #include "talk/base/task.h" | |
13 | |
14 namespace notifier { | |
15 | |
16 template<class T> | |
17 class SignalThreadTask : public talk_base::Task, | |
18 public sigslot::has_slots<> { | |
19 public: | |
20 // Takes ownership of signal_thread. | |
21 SignalThreadTask(talk_base::Task* task_parent, T** signal_thread) | |
22 : talk_base::Task(task_parent), | |
23 signal_thread_(NULL), | |
24 finished_(false) { | |
25 SetSignalThread(signal_thread); | |
26 } | |
27 | |
28 virtual ~SignalThreadTask() { | |
29 ClearSignalThread(); | |
30 } | |
31 | |
32 virtual void Stop() { | |
33 Task::Stop(); | |
34 ClearSignalThread(); | |
35 } | |
36 | |
37 virtual int ProcessStart() { | |
38 DCHECK_EQ(GetState(), talk_base::Task::STATE_START); | |
39 signal_thread_->SignalWorkDone.connect( | |
40 this, | |
41 &SignalThreadTask<T>::OnWorkDone); | |
42 signal_thread_->Start(); | |
43 return talk_base::Task::STATE_RESPONSE; | |
44 } | |
45 | |
46 int ProcessResponse() { | |
47 if (!finished_) { | |
48 return talk_base::Task::STATE_BLOCKED; | |
49 } | |
50 SignalWorkDone(signal_thread_); | |
51 ClearSignalThread(); | |
52 return talk_base::Task::STATE_DONE; | |
53 } | |
54 | |
55 sigslot::signal1<T*> SignalWorkDone; | |
56 | |
57 private: | |
58 // Takes ownership of signal_thread. | |
59 void SetSignalThread(T** signal_thread) { | |
60 DCHECK(!signal_thread_); | |
61 DCHECK(signal_thread); | |
62 DCHECK(*signal_thread); | |
63 // No one should be listening to the signal thread for work done. | |
64 // They should be using this class instead. Unfortunately, we | |
65 // can't verify this. | |
66 | |
67 signal_thread_ = *signal_thread; | |
68 | |
69 // Helps callers not to use signal thread after this point since this class | |
70 // has taken ownership (and avoid the error of doing | |
71 // signal_thread->Start()). | |
72 *signal_thread = NULL; | |
73 } | |
74 | |
75 void OnWorkDone(talk_base::SignalThread* signal_thread) { | |
76 DCHECK_EQ(signal_thread, signal_thread_); | |
77 finished_ = true; | |
78 Wake(); | |
79 } | |
80 | |
81 void ClearSignalThread() { | |
82 if (signal_thread_) { | |
83 // Don't wait on the thread destruction, or we may deadlock. | |
84 signal_thread_->Destroy(false); | |
85 signal_thread_ = NULL; | |
86 } | |
87 } | |
88 | |
89 T* signal_thread_; | |
90 bool finished_; | |
91 DISALLOW_COPY_AND_ASSIGN(SignalThreadTask); | |
92 }; | |
93 | |
94 } // namespace notifier | |
95 | |
96 #endif // JINGLE_NOTIFIER_BASE_SIGNAL_THREAD_TASK_H_ | |
OLD | NEW |