[vlc-devel] [PATCH 5/5] qt: networkmediamodel: execute media_tree callback in Qt thread

Alexandre Janniaux ajanni at videolabs.io
Fri Jan 17 15:30:55 CET 2020


Delegate media_tree callback handling to the Qt thread, so that
NetworkMediaModel's internal is locked and race-free.

It needs Qt::QueuedConnection because those callbacks are either called
from the service discovery thread (normal runtime behaviour) or from the
Qt thread itself when it adds the listener (initialization). Without
Qt::QueuedConnection, the lambda won't be queued in the later case as it
is run in the same thread, and will be executed in place, which in turn
leads to a double lock.
---
 modules/gui/qt/network/networkmediamodel.cpp | 51 +++++++++++---------
 1 file changed, 29 insertions(+), 22 deletions(-)

diff --git a/modules/gui/qt/network/networkmediamodel.cpp b/modules/gui/qt/network/networkmediamodel.cpp
index 2ee79da8c1..9cb75433c7 100644
--- a/modules/gui/qt/network/networkmediamodel.cpp
+++ b/modules/gui/qt/network/networkmediamodel.cpp
@@ -267,20 +267,29 @@ bool NetworkMediaModel::initializeMediaSources()
 
 void NetworkMediaModel::onItemCleared( MediaSourcePtr mediaSource, input_item_node_t*)
 {
-    input_item_node_t *res;
-    input_item_node_t *parent;
-    if ( vlc_media_tree_Find( m_treeItem.source->tree, m_treeItem.media.get(),
-                                      &res, &parent ) == false )
-        return;
-    refreshMediaList( std::move( mediaSource ), res->pp_children, res->i_children, true );
+    QMetaObject::invokeMethod(this, [this, mediaSource = std::move(mediaSource)]() {
+        input_item_node_t *res;
+        input_item_node_t *parent;
+        vlc_media_tree_Lock( m_treeItem.source->tree );
+        bool found = vlc_media_tree_Find( m_treeItem.source->tree, m_treeItem.media.get(),
+                                          &res, &parent );
+        vlc_media_tree_Unlock( m_treeItem.source->tree );
+        if (!found)
+            return;
+
+        refreshMediaList( std::move( mediaSource ), res->pp_children, res->i_children, true );
+    }, Qt::QueuedConnection);
 }
 
 void NetworkMediaModel::onItemAdded( MediaSourcePtr mediaSource, input_item_node_t* parent,
                                   input_item_node_t *const children[],
                                   size_t count )
 {
-    if ( parent->p_item == m_treeItem.media.get() )
-        refreshMediaList( std::move( mediaSource ), children, count, false );
+    InputItemPtr p_parent { parent->p_item };
+    QMetaObject::invokeMethod(this, [this, p_parent = std::move(p_parent), mediaSource = std::move(mediaSource), children, count]() {
+        if ( p_parent.get() == m_treeItem.media.get() )
+            refreshMediaList( std::move( mediaSource ), children, count, false );
+    }, Qt::QueuedConnection);
 }
 
 void NetworkMediaModel::onItemRemoved( MediaSourcePtr,
@@ -353,20 +362,18 @@ void NetworkMediaModel::refreshMediaList( MediaSourcePtr mediaSource,
         item.tree = NetworkTreeItem( mediaSource, it );
         items.push_back( std::move( item ) );
     }
-    QMetaObject::invokeMethod(this, [this, clear, items=std::move(items)]() {
-        if ( clear == true )
-        {
-            beginResetModel();
-            m_items.erase( begin( m_items ) , end( m_items ) );
-        }
-        else
-            beginInsertRows( {}, m_items.size(), m_items.size() + items.size() - 1 );
-        std::move( begin( items ), end( items ), std::back_inserter( m_items ) );
-        if ( clear == true )
-            endResetModel();
-        else
-            endInsertRows();
-    });
+    if ( clear == true )
+    {
+        beginResetModel();
+        m_items.erase( begin( m_items ) , end( m_items ) );
+    }
+    else
+        beginInsertRows( {}, m_items.size(), m_items.size() + items.size() - 1 );
+    std::move( begin( items ), end( items ), std::back_inserter( m_items ) );
+    if ( clear == true )
+        endResetModel();
+    else
+        endInsertRows();
 }
 
 bool NetworkMediaModel::canBeIndexed(const QUrl& url , ItemType itemType )
-- 
2.25.0



More information about the vlc-devel mailing list