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