1 //----------------------------------------------------------------------------- 2 // 3 // Wait.cpp 4 // 5 // Base class for objects we want to be able to wait for. 6 // 7 // Copyright (c) 2010 Mal Lansell <mal@lansell.org> 8 // All rights reserved. 9 // 10 // SOFTWARE NOTICE AND LICENSE 11 // 12 // This file is part of OpenZWave. 13 // 14 // OpenZWave is free software: you can redistribute it and/or modify 15 // it under the terms of the GNU Lesser General Public License as published 16 // by the Free Software Foundation, either version 3 of the License, 17 // or (at your option) any later version. 18 // 19 // OpenZWave is distributed in the hope that it will be useful, 20 // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 // GNU Lesser General Public License for more details. 23 // 24 // You should have received a copy of the GNU Lesser General Public License 25 // along with OpenZWave. If not, see <http://www.gnu.org/licenses/>. 26 // 27 //----------------------------------------------------------------------------- 28 #include <stdio.h> 29 #include "Defs.h" 30 #include "platform/Wait.h" 31 #include "platform/Event.h" 32 #include "platform/Log.h" 33 34 #ifdef WIN32 35 #include "platform/windows/WaitImpl.h" // Platform-specific implementation of a Wait object 36 #elif defined WINRT 37 #include "platform/winRT/WaitImpl.h" // Platform-specific implementation of a Wait object 38 #else 39 #include "platform/unix/WaitImpl.h" // Platform-specific implementation of a Wait object 40 #endif 41 42 namespace OpenZWave 43 { 44 namespace Internal 45 { 46 namespace Platform 47 { 48 49 void WaitMultipleCallback(void* _context); 50 51 //----------------------------------------------------------------------------- 52 // <Wait::Wait> 53 // Constructor 54 //----------------------------------------------------------------------------- Wait()55 Wait::Wait() 56 { 57 m_pImpl = new WaitImpl(this); 58 } 59 60 //----------------------------------------------------------------------------- 61 // <Wait::~Wait> 62 // Destructor 63 //----------------------------------------------------------------------------- ~Wait()64 Wait::~Wait() 65 { 66 delete m_pImpl; 67 } 68 69 //----------------------------------------------------------------------------- 70 // <Wait::AddWatcher> 71 // Add a watcher to our object. 72 //----------------------------------------------------------------------------- AddWatcher(pfnWaitNotification_t _callback,void * _context)73 void Wait::AddWatcher(pfnWaitNotification_t _callback, void* _context) 74 { 75 if (!_callback) 76 { 77 assert(0); 78 return; 79 } 80 81 // Add a ref so our object cannot disappear while being watched 82 AddRef(); 83 84 // Add the watcher (platform specific code required here for thread safety) 85 m_pImpl->AddWatcher(_callback, _context); 86 } 87 88 //----------------------------------------------------------------------------- 89 // <Wait::RemoveWatcher> 90 // Remove a watcher from our object. 91 //----------------------------------------------------------------------------- RemoveWatcher(pfnWaitNotification_t _callback,void * _context)92 void Wait::RemoveWatcher(pfnWaitNotification_t _callback, void* _context) 93 { 94 if (m_pImpl->RemoveWatcher(_callback, _context)) 95 { 96 Release(); 97 } 98 } 99 100 //----------------------------------------------------------------------------- 101 // <Wait::Notify> 102 // Notify all the watchers that the object has become signalled 103 //----------------------------------------------------------------------------- Notify()104 void Wait::Notify() 105 { 106 m_pImpl->Notify(); 107 } 108 109 //----------------------------------------------------------------------------- 110 // <Wait::Multiple> 111 // Wait for one of multiple objects to become signalled. 112 //----------------------------------------------------------------------------- Multiple(Wait ** _objects,uint32 _numObjects,int32 _timeout)113 int32 Wait::Multiple(Wait** _objects, uint32 _numObjects, int32 _timeout // = -1 114 ) 115 { 116 uint32 i; 117 118 // Create an event that will be set when any of the objects in the list becomes signalled. 119 Event* waitEvent = new Event(); 120 121 // Add a watcher to each object in the list, passing in the event as the context. 122 for (i = 0; i < _numObjects; ++i) 123 { 124 // Log::Write( LogLevel_Info, "Wait::Multiple - Object %p %d", _objects[i], _objects[i]->IsSignalled()); 125 _objects[i]->AddWatcher(WaitMultipleCallback, waitEvent); 126 } 127 128 int32 res = -1; // Default to timeout result 129 string str = ""; 130 if (waitEvent->Wait(_timeout)) 131 { 132 // An object was signalled. Run through the list 133 // and see which one it was. 134 for (i = 0; i < _numObjects; ++i) 135 { 136 if (_objects[i]->IsSignalled()) 137 { 138 if (res == -1) 139 res = (int32) i; 140 char buf[15]; 141 snprintf(buf, sizeof(buf), "%d, ", i); 142 str += buf; 143 } 144 } 145 } 146 // Log::Write( LogLevel_Debug, "Wait::Multiple res=%d num=%d >%s", res, _numObjects, str.c_str() ); 147 148 // Remove the watchers 149 for (i = 0; i < _numObjects; ++i) 150 { 151 _objects[i]->RemoveWatcher(WaitMultipleCallback, waitEvent); 152 } 153 154 // We're done with the event now 155 waitEvent->Release(); 156 return res; 157 } 158 159 //----------------------------------------------------------------------------- 160 // <WaitMultipleCallback> 161 // Callback handler for the watchers added during WaitImpl::Multiple 162 //----------------------------------------------------------------------------- WaitMultipleCallback(void * _context)163 void WaitMultipleCallback(void* _context) 164 { 165 Event* waitEvent = (Event*) _context; 166 waitEvent->Set(); 167 } 168 } // namespace Platform 169 } // namespace Internal 170 } // namespace OpenZWave 171