1 /*
2 * Copyright 2009-2015, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Clemens Zeidler, haiku@Clemens-Zeidler.de
7 */
8
9
10 #include "DriverInterface.h"
11
12 #include <Autolock.h>
13 #include <Messenger.h>
14
15
~Monitor()16 Monitor::~Monitor()
17 {
18 }
19
20
21 status_t
StartWatching(BHandler * target)22 Monitor::StartWatching(BHandler* target)
23 {
24 if (fWatcherList.HasItem(target))
25 return B_ERROR;
26
27 fWatcherList.AddItem(target);
28 return B_OK;
29 }
30
31
32 status_t
StopWatching(BHandler * target)33 Monitor::StopWatching(BHandler* target)
34 {
35 return fWatcherList.RemoveItem(target);
36 }
37
38
39 void
Broadcast(uint32 message)40 Monitor::Broadcast(uint32 message)
41 {
42 for (int i = 0; i < fWatcherList.CountItems(); i++) {
43 BMessenger messenger(fWatcherList.ItemAt(i));
44 messenger.SendMessage(message);
45 }
46 }
47
48
49 // #pragma mark -
50
51
PowerStatusDriverInterface()52 PowerStatusDriverInterface::PowerStatusDriverInterface()
53 :
54 fIsWatching(0),
55 fWaitSem(-1),
56 fThread(-1),
57 fListLocker("driver list")
58 {
59 }
60
61
~PowerStatusDriverInterface()62 PowerStatusDriverInterface::~PowerStatusDriverInterface()
63 {
64 }
65
66
67 status_t
StartWatching(BHandler * target)68 PowerStatusDriverInterface::StartWatching(BHandler* target)
69 {
70 BAutolock autolock(fListLocker);
71
72 status_t status = Monitor::StartWatching(target);
73 if (status != B_OK)
74 return status;
75
76 if (fThread > 0)
77 return B_OK;
78
79 fThread = spawn_thread(&_ThreadWatchPowerFunction, "PowerStatusThread",
80 B_LOW_PRIORITY, this);
81 if (fThread >= 0) {
82 fWaitSem = create_sem(0, "power status wait");
83
84 atomic_set(&fIsWatching, 1);
85 status = resume_thread(fThread);
86 } else
87 return fThread;
88
89 if (status != B_OK && fWatcherList.CountItems() == 0) {
90 atomic_set(&fIsWatching, 0);
91 delete_sem(fWaitSem);
92
93 fThread = -1;
94 fWaitSem = -1;
95 }
96
97 return status;
98 }
99
100
101 status_t
StopWatching(BHandler * target)102 PowerStatusDriverInterface::StopWatching(BHandler* target)
103 {
104 if (fThread < 0)
105 return B_BAD_VALUE;
106
107 fListLocker.Lock();
108
109 if (fWatcherList.CountItems() == 1) {
110 fListLocker.Unlock();
111 Disconnect();
112 } else
113 fListLocker.Unlock();
114
115 return Monitor::StopWatching(target);
116 }
117
118
119 void
Broadcast(uint32 message)120 PowerStatusDriverInterface::Broadcast(uint32 message)
121 {
122 BAutolock autolock(fListLocker);
123 Monitor::Broadcast(message);
124 }
125
126
127 void
Disconnect()128 PowerStatusDriverInterface::Disconnect()
129 {
130 if (fThread < 0)
131 return;
132
133 atomic_set(&fIsWatching, 0);
134 delete_sem(fWaitSem);
135
136 wait_for_thread(fThread, NULL);
137 fThread = -1;
138 fWaitSem = -1;
139 }
140
141
142 int32
_ThreadWatchPowerFunction(void * data)143 PowerStatusDriverInterface::_ThreadWatchPowerFunction(void* data)
144 {
145 PowerStatusDriverInterface* that = (PowerStatusDriverInterface*)data;
146 that->_WatchPowerStatus();
147 return 0;
148 }
149
150