[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