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