Ticket #603: mythmedia_locking.diff
File mythmedia_locking.diff, 8.0 KB (added by , 18 years ago) |
---|
-
libs/libmythui/mythmainwindow.cpp
1126 1126 iscatched = activedialog->onMediaEvent(pDev); 1127 1127 if (!iscatched) 1128 1128 { 1129 while (itr != d->mediaHandlerMap.end()) 1129 MediaMonitor *mon = MediaMonitor::GetMediaMonitor(); 1130 if (mon && mon->ValidateAndLock(pDev)) 1130 1131 { 1131 if ((itr.data().MediaType & (int)pDev->getMediaType())) 1132 { 1133 VERBOSE(VB_IMPORTANT, "Found a handler"); 1134 d->exitingtomain = true; 1135 d->exitmenumediadevicecallback = itr.data().callback; 1136 d->mediadeviceforcallback = pDev; 1137 QApplication::postEvent(this, new ExitToMainMenuEvent()); 1138 break; 1139 } 1140 itr++; 1132 while (itr != d->mediaHandlerMap.end()) 1133 { 1134 if ((itr.data().MediaType & (int)pDev->getMediaType())) 1135 { 1136 VERBOSE(VB_IMPORTANT, "Found a handler"); 1137 d->exitingtomain = true; 1138 d->exitmenumediadevicecallback = itr.data().callback; 1139 d->mediadeviceforcallback = pDev; 1140 QApplication::postEvent(this, new ExitToMainMenuEvent()); 1141 mon->Unlock(pDev); 1142 break; 1143 } 1144 itr++; 1145 } 1146 mon->Unlock(pDev); 1141 1147 } 1142 1148 } 1143 1149 } -
libs/libmyth/mythmediamonitor.h
43 43 unsigned long m_Interval; 44 44 }; 45 45 46 class MediaMonitor;47 48 46 class MediaMonitor : public QObject 49 47 { 50 48 Q_OBJECT … … 64 62 65 63 static MediaMonitor *GetMediaMonitor(void); 66 64 67 // this is not safe.. device could get deleted...68 QValueList <MythMediaDevice*> GetMedias(MediaType mediatype);65 bool ValidateAndLock(MythMediaDevice *pMedia); 66 void Unlock(MythMediaDevice *pMedia); 69 67 68 // To safely dereference the pointers returned by this function 69 // first validate the pointer with ValidateAndLock(), if true is returned 70 // it is safe to dereference the pointer. When finished call Unlock() 71 QValueList<MythMediaDevice*> GetMedias(MediaType mediatype); 72 70 73 public slots: 71 74 void mediaStatusChanged(MediaStatus oldStatus, MythMediaDevice* pMedia); 72 75 … … 87 90 static QStringList GetCDROMBlockDevices(void); 88 91 89 92 protected: 93 QMutex m_DevicesLock; 90 94 QValueList<MythMediaDevice*> m_Devices; 95 QValueList<MythMediaDevice*> m_RemovedDevices; 96 QMap<MythMediaDevice*, int> m_UseCount; 97 91 98 bool m_Active; 92 99 MonitorThread m_Thread; 93 100 bool m_AllowEject; -
libs/libmyth/mythmediamonitor.cpp
107 107 { 108 108 MythMediaDevice *selected = NULL; 109 109 110 QMutexLocker locker(&m_DevicesLock); 111 110 112 if (m_Devices.count() == 1) 111 113 { 112 114 if (m_Devices.first()->getAllowEject()) … … 194 196 195 197 MediaMonitor::MediaMonitor(QObject* par, unsigned long interval, 196 198 bool allowEject) 197 : QObject(par), m_Active(false), m_Thread( NULL, interval),199 : QObject(par), m_Active(false), m_Thread(this, interval), 198 200 m_AllowEject(allowEject), m_fifo(-1) 199 201 { 200 202 } … … 348 350 // Given a media deivce add it to our collection. 349 351 void MediaMonitor::AddDevice(MythMediaDevice* pDevice) 350 352 { 353 QMutexLocker locker(&m_DevicesLock); 354 351 355 connect(pDevice, SIGNAL(statusChanged(MediaStatus, MythMediaDevice*)), 352 356 this, SLOT(mediaStatusChanged(MediaStatus, MythMediaDevice*))); 353 357 m_Devices.push_back( pDevice ); 358 m_UseCount[pDevice] = 0; 354 359 } 355 360 356 361 // Given a fstab entry to a media device determine what type of device it is … … 575 580 */ 576 581 bool MediaMonitor::RemoveDevice(const QString &dev) 577 582 { 583 QMutexLocker locker(&m_DevicesLock); 584 578 585 QValueList<MythMediaDevice*>::iterator it; 579 586 for (it = m_Devices.begin(); it != m_Devices.end(); it++) 580 587 { 581 588 if ((*it)->getDevicePath() == dev) 582 589 { 583 m_Devices.remove(it); 590 if (m_UseCount[*it] == 0) 591 { 592 delete *it; 593 m_Devices.remove(it); 594 m_UseCount.remove(*it); 595 } 596 else 597 { 598 // Other threads are still using this device 599 // postpone actual delete until they finish. 600 disconnect(*it); 601 m_RemovedDevices.append(*it); 602 m_Devices.remove(it); 603 } 604 584 605 return true; 585 606 } 586 607 } 608 587 609 return false; 588 610 } 589 611 … … 681 703 m_Thread.wait(); 682 704 } 683 705 684 // Ask for available media 685 // this is not safe.. device could get deleted... 686 QValueList <MythMediaDevice*> MediaMonitor::GetMedias(MediaType mediatype) 706 /** \fn MediaMonitor::ValidateAndLock(MythMediaDevice *pMedia) 707 * \brief Validates the MythMediaDevice and increments its reference count 708 * 709 * Returns true if pMedia device is valid, otherwise returns false. 710 * If this function returns false the caller should gracefully recover. 711 * 712 * NOTE: This function can block. 713 * 714 * \sa Unlock(MythMediaDevice *pMedia), GetMedias(MediaType mediatype) 715 */ 716 bool MediaMonitor::ValidateAndLock(MythMediaDevice *pMedia) 687 717 { 688 Q ValueList <MythMediaDevice*> medias;718 QMutexLocker locker(&m_DevicesLock); 689 719 690 QValueList <MythMediaDevice*>::iterator it = m_Devices.begin(); 720 if (!m_Devices.contains(pMedia)) 721 return false; 722 723 m_UseCount[pMedia]++; 724 725 return true; 726 } 727 728 /** \fn MediaMonitor::Unlock(MythMediaDevice *pMedia) 729 * \brief decrements the MythMediaDevices reference count 730 * 731 * \sa ValidateAndLock(MythMediaDevice *pMedia), GetMedias(MediaType mediatype) 732 */ 733 void MediaMonitor::Unlock(MythMediaDevice *pMedia) 734 { 735 QMutexLocker locker(&m_DevicesLock); 736 737 if (!m_UseCount.contains(pMedia)) 738 return; 739 740 m_UseCount[pMedia]--; 741 742 if (m_UseCount[pMedia] == 0 && m_RemovedDevices.contains(pMedia)) 743 { 744 delete pMedia; 745 m_RemovedDevices.remove(pMedia); 746 m_UseCount.remove(pMedia); 747 } 748 } 749 750 /** \fn MediaMonitor::GetMedias(MediaType mediatype) 751 * \brief Ask for available media 752 * 753 * GetMedias returns a list of MythMediaDevice pointers which match the given mediatype. 754 * 755 * It is potentially unsafe to use the pointers returned by this function. The devices 756 * may be removed and their associated MythMediaDevice objects destroyed. It is the 757 * responsibility of the caller to ensure that the pointers are validated and 758 * and the reference count is incremented by calling MediaMonitor::ValidateAndLock() 759 * before the the returned pointer is dereferenced and MediaMonitor::Unlock() when 760 * done. 761 * 762 * \sa ValidateAndLock(MythMediaDevice *pMedia), Unlock(MythMediaDevice *pMedia) 763 */ 764 QValueList<MythMediaDevice*> MediaMonitor::GetMedias(MediaType mediatype) 765 { 766 QMutexLocker locker(&m_DevicesLock); 767 768 QValueList<MythMediaDevice*> medias; 769 770 QValueList<MythMediaDevice*>::iterator it = m_Devices.begin(); 691 771 for (;it != m_Devices.end(); it++) 692 772 { 693 773 if (((*it)->getMediaType() == mediatype) && … … 701 781 702 782 return medias; 703 783 } 784 704 785 // Signal handler. 705 786 void MediaMonitor::mediaStatusChanged(MediaStatus oldStatus, 706 787 MythMediaDevice* pMedia)