CodaDevicePtr SymbianDeviceManager::getCodaDevice(const QString &port) { ensureInitialized(); QMutexLocker lock(&d->m_devicesLock); const int idx = findByPortName(port); if (idx == -1) { qWarning("Attempt to acquire device '%s' that does not exist.", qPrintable(port)); if (debug) qDebug() << *this; return CodaDevicePtr(); } SymbianDevice& device = d->m_devices[idx]; CodaDevicePtr& devicePtr = device.m_data->codaDevice; if (devicePtr.isNull() || !devicePtr->device()->isOpen()) { // Check we instanciate in the correct thread - we can't afford to create the CodaDevice (and more specifically, open the VirtualSerialDevice) in a thread that isn't guaranteed to be long-lived. // Therefore, if we're not in SymbianDeviceManager's thread, rejig things so it's opened in the main thread if (QThread::currentThread() != thread()) { // SymbianDeviceManager is owned by the main thread d->m_codaPortWaitMutex.lock(); QWaitCondition waiter; QCoreApplication::postEvent(this, new QConstructCodaPortEvent((QEvent::Type)d->m_constructCodaPortEventType, port, &devicePtr, &waiter)); waiter.wait(&d->m_codaPortWaitMutex); // When the wait returns (due to the wakeAll in SymbianDeviceManager::customEvent), the CodaDevice will be fully set up d->m_codaPortWaitMutex.unlock(); } else { // We're in the main thread, just set it up directly constructCodaPort(devicePtr, port); } // We still carry on in the case we failed to open so the client can access the IODevice's errorString() } if (devicePtr->device()->isOpen()) device.m_data->deviceAcquired++; return devicePtr; }
void SymbianDeviceManager::customEvent(QEvent *event) { if (event->type() == d->m_constructTcfPortEventType) { QConstructTcfPortEvent* constructEvent = static_cast<QConstructTcfPortEvent*>(event); constructCodaPort(*constructEvent->m_device, constructEvent->m_portName); constructEvent->m_waiter->wakeAll(); // Should only ever be one thing waiting on this } }