00001 /************************************************************************************ 00002 00003 Filename : OVR_DeviceHandle.cpp 00004 Content : Implementation of device handle class 00005 Created : February 5, 2013 00006 Authors : Lee Cooper 00007 00008 Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. 00009 00010 Use of this software is subject to the terms of the Oculus license 00011 agreement provided at the time of installation or download, or which 00012 otherwise accompanies this software in either electronic or hard copy form. 00013 00014 *************************************************************************************/ 00015 00016 #include "OVR_DeviceHandle.h" 00017 00018 #include "OVR_DeviceImpl.h" 00019 00020 namespace OVR { 00021 00022 //------------------------------------------------------------------------------------- 00023 // ***** DeviceHandle 00024 00025 DeviceHandle::DeviceHandle(DeviceCreateDesc* impl) : pImpl(impl) 00026 { 00027 if (pImpl) 00028 pImpl->AddRef(); 00029 } 00030 00031 DeviceHandle::DeviceHandle(const DeviceHandle& src) : pImpl(src.pImpl) 00032 { 00033 if (pImpl) 00034 pImpl->AddRef(); 00035 } 00036 00037 DeviceHandle::~DeviceHandle() 00038 { 00039 if (pImpl) 00040 pImpl->Release(); 00041 } 00042 00043 void DeviceHandle::operator = (const DeviceHandle& src) 00044 { 00045 if (src.pImpl) 00046 src.pImpl->AddRef(); 00047 if (pImpl) 00048 pImpl->Release(); 00049 pImpl = src.pImpl; 00050 } 00051 00052 DeviceBase* DeviceHandle::GetDevice_AddRef() const 00053 { 00054 if (pImpl && pImpl->pDevice) 00055 { 00056 pImpl->pDevice->AddRef(); 00057 return pImpl->pDevice; 00058 } 00059 return NULL; 00060 } 00061 00062 // Returns true, if the handle contains the same device ptr 00063 // as specified in the parameter. 00064 bool DeviceHandle::IsDevice(DeviceBase* pdev) const 00065 { 00066 return (pdev && pImpl && pImpl->pDevice) ? 00067 pImpl->pDevice == pdev : false; 00068 } 00069 00070 DeviceType DeviceHandle::GetType() const 00071 { 00072 return pImpl ? pImpl->Type : Device_None; 00073 } 00074 00075 bool DeviceHandle::GetDeviceInfo(DeviceInfo* info) const 00076 { 00077 return pImpl ? pImpl->GetDeviceInfo(info) : false; 00078 } 00079 bool DeviceHandle::IsAvailable() const 00080 { 00081 // This isn't "atomically safe", but the function only returns the 00082 // recent state that may change. 00083 return pImpl ? (pImpl->Enumerated && pImpl->pLock->pManager) : false; 00084 } 00085 00086 bool DeviceHandle::IsCreated() const 00087 { 00088 return pImpl ? (pImpl->pDevice != 0) : false; 00089 } 00090 00091 DeviceBase* DeviceHandle::CreateDevice() 00092 { 00093 if (!pImpl) 00094 return 0; 00095 00096 DeviceBase* device = 0; 00097 Ptr<DeviceManagerImpl> manager= 0; 00098 00099 // Since both manager and device pointers can only be destroyed during a lock, 00100 // hold it while checking for availability. 00101 // AddRef to manager so that it doesn't get released on us. 00102 { 00103 Lock::Locker deviceLockScope(pImpl->GetLock()); 00104 00105 if (pImpl->pDevice) 00106 { 00107 pImpl->pDevice->AddRef(); 00108 return pImpl->pDevice; 00109 } 00110 manager = pImpl->GetManagerImpl(); 00111 } 00112 00113 if (manager) 00114 { 00115 if (manager->GetThreadId() != OVR::GetCurrentThreadId()) 00116 { 00117 // Queue up a CreateDevice request. This fills in '&device' with AddRefed value, 00118 // or keep it at null. 00119 manager->GetThreadQueue()->PushCallAndWaitResult( 00120 manager.GetPtr(), &DeviceManagerImpl::CreateDevice_MgrThread, 00121 &device, pImpl, (DeviceBase*)0); 00122 } 00123 else 00124 device = manager->CreateDevice_MgrThread(pImpl, (DeviceBase*)0); 00125 } 00126 return device; 00127 } 00128 00129 void DeviceHandle::Clear() 00130 { 00131 if (pImpl) 00132 { 00133 pImpl->Release(); 00134 pImpl = 0; 00135 } 00136 } 00137 00138 bool DeviceHandle::enumerateNext(const DeviceEnumerationArgs& args) 00139 { 00140 if (GetType() == Device_None) 00141 return false; 00142 00143 Ptr<DeviceManagerImpl> managerKeepAlive; 00144 Lock::Locker lockScope(pImpl->GetLock()); 00145 00146 DeviceCreateDesc* next = pImpl; 00147 // If manager was destroyed, we get removed from the list. 00148 if (!pImpl->pNext) 00149 return false; 00150 00151 managerKeepAlive = next->GetManagerImpl(); 00152 OVR_ASSERT(managerKeepAlive); 00153 00154 do { 00155 next = next->pNext; 00156 00157 if (managerKeepAlive->Devices.IsNull(next)) 00158 { 00159 pImpl->Release(); 00160 pImpl = 0; 00161 return false; 00162 } 00163 00164 } while(!args.MatchRule(next->Type, next->Enumerated)); 00165 00166 next->AddRef(); 00167 pImpl->Release(); 00168 pImpl = next; 00169 00170 return true; 00171 } 00172 00173 } // namespace OVR 00174