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