xref: /haiku/src/apps/powerstatus/DriverInterface.cpp (revision 90169e6310ba20c6c41ee81347d27724c3cf7080)
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