#include "SMXDeviceSearchThreaded.h" #include "SMXDeviceSearch.h" #include "SMXDeviceConnection.h" #include #include using namespace std; using namespace SMX; SMX::SMXDeviceSearchThreaded::SMXDeviceSearchThreaded() { m_hEvent = make_shared(CreateEvent(NULL, false, false, NULL)); m_pDeviceList = make_shared(); // Start the thread. DWORD id; m_hThread = CreateThread(NULL, 0, ThreadMainStart, this, 0, &id); SMX::SetThreadName(id, "SMXDeviceSearch"); } SMX::SMXDeviceSearchThreaded::~SMXDeviceSearchThreaded() { // Shut down the thread, if it's still running. Shutdown(); } void SMX::SMXDeviceSearchThreaded::Shutdown() { if(m_hThread == INVALID_HANDLE_VALUE) return; // Tell the thread to shut down, and wait for it before returning. m_bShutdown = true; SetEvent(m_hEvent->value()); WaitForSingleObject(m_hThread, INFINITE); m_hThread = INVALID_HANDLE_VALUE; } DWORD WINAPI SMX::SMXDeviceSearchThreaded::ThreadMainStart(void *self_) { SMXDeviceSearchThreaded *self = (SMXDeviceSearchThreaded *) self_; self->ThreadMain(); return 0; } void SMX::SMXDeviceSearchThreaded::UpdateDeviceList() { m_Lock.AssertNotLockedByCurrentThread(); // Tell m_pDeviceList about closed devices, so it knows that any device on the // same path is new. m_Lock.Lock(); for(auto pDevice: m_apClosedDevices) m_pDeviceList->DeviceWasClosed(pDevice); m_apClosedDevices.clear(); m_Lock.Unlock(); // Get the current device list. wstring sError; vector> apDevices = m_pDeviceList->GetDevices(sError); if(!sError.empty()) { Log(ssprintf("Error listing USB devices: %ls", sError.c_str())); return; } // Update the device list returned by GetDevices. m_Lock.Lock(); m_apDevices = apDevices; m_Lock.Unlock(); } void SMX::SMXDeviceSearchThreaded::ThreadMain() { while(!m_bShutdown) { UpdateDeviceList(); WaitForSingleObjectEx(m_hEvent->value(), 250, true); } } void SMX::SMXDeviceSearchThreaded::DeviceWasClosed(shared_ptr pDevice) { // Add pDevice to the list of closed devices. We'll call m_pDeviceList->DeviceWasClosed // on these from the scanning thread. m_apClosedDevices.push_back(pDevice); } vector> SMX::SMXDeviceSearchThreaded::GetDevices() { // Lock to make a copy of the device list. m_Lock.Lock(); vector> apResult = m_apDevices; m_Lock.Unlock(); return apResult; }