Add some basic read-write-locking to the previewDevices.

Remove comment about race conditions when setting the selected device. Turns
out this wasn't at all the case. It was a signal loop, instead.

svn path=/trunk/extragear/sysadmin/partitionmanager/; revision=1089499
This commit is contained in:
Volker Lanz 2010-02-13 11:25:56 +00:00
parent 8ee33739c6
commit d9fd184c9d
8 changed files with 37 additions and 14 deletions

View File

@ -90,4 +90,5 @@ void DeviceScanner::run()
} }
operationStack().sortDevices(); operationStack().sortDevices();
emit devicesChanged();
} }

View File

@ -38,14 +38,17 @@
#include "util/globallog.h" #include "util/globallog.h"
#include <kdebug.h> #include <kdebug.h>
#include <klocale.h> #include <klocale.h>
#include <QReadLocker>
#include <QWriteLocker>
/** Constructs a new OperationStack */ /** Constructs a new OperationStack */
OperationStack::OperationStack() : OperationStack::OperationStack() :
m_Operations(), m_Operations(),
m_PreviewDevices() m_PreviewDevices(),
m_Lock(QReadWriteLock::Recursive)
{ {
} }
@ -420,6 +423,8 @@ void OperationStack::clearOperations()
/** Clears the list of Devices. */ /** Clears the list of Devices. */
void OperationStack::clearDevices() void OperationStack::clearDevices()
{ {
QWriteLocker lockDevices(&lock());
qDeleteAll(previewDevices()); qDeleteAll(previewDevices());
previewDevices().clear(); previewDevices().clear();
} }
@ -430,6 +435,8 @@ void OperationStack::clearDevices()
*/ */
Device* OperationStack::findDeviceForPartition(const Partition* p) Device* OperationStack::findDeviceForPartition(const Partition* p)
{ {
QReadLocker lockDevices(&lock());
foreach (Device* d, previewDevices()) foreach (Device* d, previewDevices())
{ {
if (d->partitionTable() == NULL) if (d->partitionTable() == NULL)
@ -456,6 +463,8 @@ void OperationStack::addDevice(Device* d)
{ {
Q_ASSERT(d); Q_ASSERT(d);
QWriteLocker lockDevices(&lock());
previewDevices().append(d); previewDevices().append(d);
} }
@ -466,5 +475,7 @@ static bool deviceLessThan(const Device* d1, const Device* d2)
void OperationStack::sortDevices() void OperationStack::sortDevices()
{ {
QWriteLocker lockDevices(&lock());
qSort(previewDevices().begin(), previewDevices().end(), deviceLessThan); qSort(previewDevices().begin(), previewDevices().end(), deviceLessThan);
} }

View File

@ -22,6 +22,8 @@
#define OPERATIONSTACK__H #define OPERATIONSTACK__H
#include <QList> #include <QList>
#include <QReadWriteLock>
#include <qglobal.h> #include <qglobal.h>
class Device; class Device;
@ -64,6 +66,8 @@ class OperationStack
Device* findDeviceForPartition(const Partition* p); Device* findDeviceForPartition(const Partition* p);
QReadWriteLock& lock() { return m_Lock; }
protected: protected:
void clearDevices(); void clearDevices();
void addDevice(Device* d); void addDevice(Device* d);
@ -78,6 +82,7 @@ class OperationStack
private: private:
Operations m_Operations; Operations m_Operations;
mutable Devices m_PreviewDevices; mutable Devices m_PreviewDevices;
QReadWriteLock m_Lock;
}; };
#endif #endif

View File

@ -26,6 +26,7 @@
#include <kmenu.h> #include <kmenu.h>
#include <kactioncollection.h> #include <kactioncollection.h>
#include <kdebug.h>
class ListDeviceWidgetItem : public QListWidgetItem class ListDeviceWidgetItem : public QListWidgetItem
{ {

View File

@ -34,6 +34,7 @@
#include <kstandardguiitem.h> #include <kstandardguiitem.h>
#include <QCloseEvent> #include <QCloseEvent>
#include <QReadLocker>
#include <config.h> #include <config.h>
@ -176,6 +177,8 @@ void MainWindow::on_m_PartitionManagerWidget_operationsChanged()
void MainWindow::on_m_PartitionManagerWidget_devicesChanged() void MainWindow::on_m_PartitionManagerWidget_devicesChanged()
{ {
QReadLocker lockDevices(&pmWidget().operationStack().lock());
listDevices().updateDevices(pmWidget().previewDevices(), pmWidget().selectedDevice()); listDevices().updateDevices(pmWidget().previewDevices(), pmWidget().selectedDevice());
if (pmWidget().selectedDevice()) if (pmWidget().selectedDevice())

View File

@ -66,6 +66,7 @@
#include <QCursor> #include <QCursor>
#include <QPointer> #include <QPointer>
#include <QReadLocker>
#include <config.h> #include <config.h>
@ -325,15 +326,10 @@ void PartitionManagerWidget::onScanDevicesProgressChanged(const QString& device_
void PartitionManagerWidget::onScanDevicesFinished() void PartitionManagerWidget::onScanDevicesFinished()
{ {
QReadLocker lockDevices(&operationStack().lock());
if (!operationStack().previewDevices().isEmpty()) if (!operationStack().previewDevices().isEmpty())
{
setSelectedDevice(operationStack().previewDevices()[0]); setSelectedDevice(operationStack().previewDevices()[0]);
// FIXME: Normally this should be emitted in setSelectedDevice(), but if we do that
// now we get all kinds of terrible races and crashes during rescan (because DeviceScanner
// clears the devices in the operationstack while ListDevices is just iterating them).
// Once that is fixed, remove the emit here.
emit devicesChanged();
}
updatePartitions(); updatePartitions();
@ -398,6 +394,8 @@ void PartitionManagerWidget::clearSelectedPartition()
void PartitionManagerWidget::setSelectedDevice(const QString& device_node) void PartitionManagerWidget::setSelectedDevice(const QString& device_node)
{ {
QReadLocker lockDevices(&operationStack().lock());
foreach(Device* d, operationStack().previewDevices()) foreach(Device* d, operationStack().previewDevices())
if (d->deviceNode() == device_node) if (d->deviceNode() == device_node)
{ {
@ -410,9 +408,10 @@ void PartitionManagerWidget::setSelectedDevice(const QString& device_node)
void PartitionManagerWidget::setSelectedDevice(Device* d) void PartitionManagerWidget::setSelectedDevice(Device* d)
{ {
// NOTE: we cannot emit devicesChanged() here because it will end up calling
// ListDevices::updateDevices() which in turn will modify the QListWidget, which
// will then emit itemSelectionChanged() which will in the end lead us back here.
m_SelectedDevice = d; m_SelectedDevice = d;
// FIXME: We should emit devicesChanged() here, but if we do that we get terrible
// races. See onScanDevicesFinished()
clearSelectedPartition(); clearSelectedPartition();
} }

View File

@ -80,6 +80,9 @@ class LIBPARTITIONMANAGERPRIVATE_EXPORT PartitionManagerWidget : public QWidget,
const OperationStack::Devices& previewDevices() const { return operationStack().previewDevices(); } const OperationStack::Devices& previewDevices() const { return operationStack().previewDevices(); }
const OperationStack::Operations& operations() const { return operationStack().operations(); } const OperationStack::Operations& operations() const { return operationStack().operations(); }
OperationStack& operationStack() { return m_OperationStack; }
const OperationStack& operationStack() const { return m_OperationStack; }
void updatePartitions(); void updatePartitions();
Partition* clipboardPartition() { return m_ClipboardPartition; } Partition* clipboardPartition() { return m_ClipboardPartition; }
@ -111,9 +114,6 @@ class LIBPARTITIONMANAGERPRIVATE_EXPORT PartitionManagerWidget : public QWidget,
OperationRunner& operationRunner() { return m_OperationRunner; } OperationRunner& operationRunner() { return m_OperationRunner; }
const OperationRunner& operationRunner() const { return m_OperationRunner; } const OperationRunner& operationRunner() const { return m_OperationRunner; }
OperationStack& operationStack() { return m_OperationStack; }
const OperationStack& operationStack() const { return m_OperationStack; }
DeviceScanner& deviceScanner() { return m_DeviceScanner; } DeviceScanner& deviceScanner() { return m_DeviceScanner; }
const DeviceScanner& deviceScanner() const { return m_DeviceScanner; } const DeviceScanner& deviceScanner() const { return m_DeviceScanner; }

View File

@ -34,6 +34,7 @@
#include <kcmultidialog.h> #include <kcmultidialog.h>
#include <QTimer> #include <QTimer>
#include <QReadLocker>
K_PLUGIN_FACTORY( K_PLUGIN_FACTORY(
PartitionManagerKCMFactory, PartitionManagerKCMFactory,
@ -116,6 +117,8 @@ void PartitionManagerKCM::on_m_PartitionManagerWidget_operationsChanged()
void PartitionManagerKCM::on_m_PartitionManagerWidget_devicesChanged() void PartitionManagerKCM::on_m_PartitionManagerWidget_devicesChanged()
{ {
QReadLocker lockDevices(&pmWidget().operationStack().lock());
listDevices().updateDevices(pmWidget().previewDevices(), pmWidget().selectedDevice()); listDevices().updateDevices(pmWidget().previewDevices(), pmWidget().selectedDevice());
} }