xref: /haiku/src/apps/powerstatus/DriverInterface.cpp (revision 508f54795f39c3e7552d87c95aae9dd8ec6f505b)
1 /*
2  * Copyright 2009, 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 
16 Monitor::~Monitor()
17 {
18 }
19 
20 
21 status_t
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
33 Monitor::StopWatching(BHandler* target)
34 {
35 	return fWatcherList.RemoveItem(target);
36 }
37 
38 
39 void
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 
52 PowerStatusDriverInterface::PowerStatusDriverInterface()
53 	:
54 	fIsWatching(0),
55 	fWaitSem(-1),
56 	fThread(-1)
57 {
58 }
59 
60 
61 PowerStatusDriverInterface::~PowerStatusDriverInterface()
62 {
63 }
64 
65 
66 status_t
67 PowerStatusDriverInterface::StartWatching(BHandler* target)
68 {
69 	BAutolock autolock(fListLocker);
70 
71 	status_t status = Monitor::StartWatching(target);
72 	if (status != B_OK)
73 		return status;
74 
75 	if (fThread > 0)
76 		return B_OK;
77 
78 	fThread = spawn_thread(&_ThreadWatchPowerFunction, "PowerStatusThread",
79 		B_LOW_PRIORITY, this);
80 	if (fThread >= 0) {
81 		fWaitSem = create_sem(0, "power status wait");
82 
83 		atomic_set(&fIsWatching, 1);
84 		status = resume_thread(fThread);
85 	} else
86 		return fThread;
87 
88 	if (status != B_OK && fWatcherList.CountItems() == 0) {
89 		atomic_set(&fIsWatching, 0);
90 		delete_sem(fWaitSem);
91 
92 		fThread = -1;
93 		fWaitSem = -1;
94 	}
95 
96 	return status;
97 }
98 
99 
100 status_t
101 PowerStatusDriverInterface::StopWatching(BHandler* target)
102 {
103 	if (fThread < 0)
104 		return B_BAD_VALUE;
105 
106 	fListLocker.Lock();
107 
108 	if (fWatcherList.CountItems() == 1) {
109 		fListLocker.Unlock();
110 		Disconnect();
111 	} else
112 		fListLocker.Unlock();
113 
114 	return Monitor::StopWatching(target);
115 }
116 
117 
118 void
119 PowerStatusDriverInterface::Broadcast(uint32 message)
120 {
121 	BAutolock autolock(fListLocker);
122 	Monitor::Broadcast(message);
123 }
124 
125 
126 void
127 PowerStatusDriverInterface::Disconnect()
128 {
129 	if (fThread < 0)
130 		return;
131 
132 	atomic_set(&fIsWatching, 0);
133 	delete_sem(fWaitSem);
134 
135 	wait_for_thread(fThread, NULL);
136 	fThread = -1;
137 	fWaitSem = -1;
138 }
139 
140 
141 int32
142 PowerStatusDriverInterface::_ThreadWatchPowerFunction(void* data)
143 {
144 	PowerStatusDriverInterface* that = (PowerStatusDriverInterface*)data;
145 	that->_WatchPowerStatus();
146 	return 0;
147 }
148 
149