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
16Monitor::~Monitor()
17{
18}
19
20
21status_t
22Monitor::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
32status_t
33Monitor::StopWatching(BHandler* target)
34{
35	return fWatcherList.RemoveItem(target);
36}
37
38
39void
40Monitor::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
52PowerStatusDriverInterface::PowerStatusDriverInterface()
53	:
54	fIsWatching(0),
55	fWaitSem(-1),
56	fThread(-1),
57	fListLocker("driver list")
58{
59}
60
61
62PowerStatusDriverInterface::~PowerStatusDriverInterface()
63{
64}
65
66
67status_t
68PowerStatusDriverInterface::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
101status_t
102PowerStatusDriverInterface::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
119void
120PowerStatusDriverInterface::Broadcast(uint32 message)
121{
122	BAutolock autolock(fListLocker);
123	Monitor::Broadcast(message);
124}
125
126
127void
128PowerStatusDriverInterface::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
142int32
143PowerStatusDriverInterface::_ThreadWatchPowerFunction(void* data)
144{
145	PowerStatusDriverInterface* that = (PowerStatusDriverInterface*)data;
146	that->_WatchPowerStatus();
147	return 0;
148}
149
150