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
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{
58}
59
60
61PowerStatusDriverInterface::~PowerStatusDriverInterface()
62{
63}
64
65
66status_t
67PowerStatusDriverInterface::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
100status_t
101PowerStatusDriverInterface::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
118void
119PowerStatusDriverInterface::Broadcast(uint32 message)
120{
121	BAutolock autolock(fListLocker);
122	Monitor::Broadcast(message);
123}
124
125
126void
127PowerStatusDriverInterface::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
141int32
142PowerStatusDriverInterface::_ThreadWatchPowerFunction(void* data)
143{
144	PowerStatusDriverInterface* that = (PowerStatusDriverInterface*)data;
145	that->_WatchPowerStatus();
146	return 0;
147}
148
149