]> cloud.milkyroute.net Git - dolphin.git/commitdiff
Change the sort and merge functions to a more generic form.
authorFrank Reininghaus <frank78ac@googlemail.com>
Tue, 15 Jan 2013 17:47:00 +0000 (18:47 +0100)
committerFrank Reininghaus <frank78ac@googlemail.com>
Tue, 15 Jan 2013 17:47:51 +0000 (18:47 +0100)
This might make it easier to reuse the parallel sorting code. Moreover,
some the upperBound/lowerBound functions have been removed because
equivalents are provided by the STL.

src/kitemviews/kfileitemmodel.h
src/kitemviews/private/kfileitemmodelsortalgorithm.cpp
src/kitemviews/private/kfileitemmodelsortalgorithm.h

index ef9dc98b9a58554f99b4afa0c64b639804ea7215..75fbb7075123f5883fcfacfb19b901988023ac66 100644 (file)
@@ -476,7 +476,8 @@ private:
     // and done step after step in slotCompleted().
     QSet<KUrl> m_urlsToExpand;
 
-    friend class KFileItemModelSortAlgorithm;  // Accesses lessThan() method
+    friend class KFileItemModelLessThan;       // Accesses lessThan() method
+    friend class KFileItemModelSortAlgorithm;  // Accesses NameRole
     friend class KFileItemModelRolesUpdater;   // Accesses emitSortProgress() method
     friend class KFileItemModelTest;           // For unit testing
     friend class KFileItemListViewTest;        // For unit testing
index a09d0cd80cd4afd953a375721421d544196b3051..ea561aeea3ab3b40ca2043c9f4caaa7a4de24026 100644 (file)
 
 #include <algorithm>
 
+class KFileItemModelLessThan
+{
+public:
+    KFileItemModelLessThan(KFileItemModel* model) :
+        m_model(model)
+    {
+    }
+
+    bool operator()(const KFileItemModel::ItemData* a, const KFileItemModel::ItemData* b)
+    {
+        return m_model->lessThan(a, b);
+    }
+
+private:
+    KFileItemModel* m_model;
+};
+
 void KFileItemModelSortAlgorithm::sort(KFileItemModel* model,
                                        QList<KFileItemModel::ItemData*>::iterator begin,
                                        QList<KFileItemModel::ItemData*>::iterator end)
 {
+    KFileItemModelLessThan lessThan(model);
+
     if (model->sortRole() == model->roleForType(KFileItemModel::NameRole)) {
         // Sorting by name can be expensive, in particular if natural sorting is
         // enabled. Use all CPU cores to speed up the sorting process.
         static const int numberOfThreads = QThread::idealThreadCount();
-        parallelSort(model, begin, end, numberOfThreads);
+        parallelSort(begin, end, lessThan, numberOfThreads);
     } else {
         // Sorting by other roles is quite fast. Use only one thread to prevent
         // problems caused by non-reentrant comparison functions, see
         // https://bugs.kde.org/show_bug.cgi?id=312679
-        sequentialSort(model, begin, end);
+        sequentialSort(begin, end, lessThan);
     }
 }
 
-void KFileItemModelSortAlgorithm::sequentialSort(KFileItemModel* model,
-                                                 QList< KFileItemModel::ItemData* >::iterator begin,
-                                                 QList< KFileItemModel::ItemData* >::iterator end)
+template <typename RandomAccessIterator, typename LessThan>
+static void sequentialSort(RandomAccessIterator begin,
+                           RandomAccessIterator end,
+                           LessThan lessThan)
 {
     // The implementation is based on qStableSortHelper() from qalgorithms.h
     // Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
@@ -53,38 +73,41 @@ void KFileItemModelSortAlgorithm::sequentialSort(KFileItemModel* model,
         return;
     }
 
-    const QList<KFileItemModel::ItemData*>::iterator middle = begin + span / 2;
-    sequentialSort(model, begin, middle);
-    sequentialSort(model, middle, end);
-    merge(model, begin, middle, end);
+    const RandomAccessIterator middle = begin + span / 2;
+    sequentialSort(begin, middle, lessThan);
+    sequentialSort(middle, end, lessThan);
+    merge(begin, middle, end, lessThan);
 }
 
-void KFileItemModelSortAlgorithm::parallelSort(KFileItemModel* model,
-                                               QList< KFileItemModel::ItemData* >::iterator begin,
-                                               QList< KFileItemModel::ItemData* >::iterator end,
-                                               const int numberOfThreads)
+template <typename RandomAccessIterator, typename LessThan>
+static void parallelSort(RandomAccessIterator begin,
+                         RandomAccessIterator end,
+                         LessThan lessThan,
+                         int numberOfThreads,
+                         int parallelSortingThreshold)
 {
     const int span = end - begin;
 
-    if (numberOfThreads > 1 && span > 100) {
+    if (numberOfThreads > 1 && span > parallelSortingThreshold) {
         const int newNumberOfThreads = numberOfThreads / 2;
-        const QList<KFileItemModel::ItemData*>::iterator middle = begin + span / 2;
+        const RandomAccessIterator middle = begin + span / 2;
 
-        QFuture<void> future = QtConcurrent::run(parallelSort, model, begin, middle, newNumberOfThreads);
-        parallelSort(model, middle, end, newNumberOfThreads);
+        QFuture<void> future = QtConcurrent::run(parallelSort<RandomAccessIterator, LessThan>, begin, middle, lessThan, newNumberOfThreads, parallelSortingThreshold);
+        parallelSort(middle, end, lessThan, newNumberOfThreads, parallelSortingThreshold);
 
         future.waitForFinished();
 
-        merge(model, begin, middle, end);
+        merge(begin, middle, end, lessThan);
     } else {
-        sequentialSort(model, begin, end);
+        sequentialSort(begin, end, lessThan);
     }
 }
 
-void KFileItemModelSortAlgorithm::merge(KFileItemModel* model,
-                                        QList<KFileItemModel::ItemData*>::iterator begin,
-                                        QList<KFileItemModel::ItemData*>::iterator pivot,
-                                        QList<KFileItemModel::ItemData*>::iterator end)
+template <typename RandomAccessIterator, typename LessThan>
+static void merge(RandomAccessIterator begin,
+                  RandomAccessIterator pivot,
+                  RandomAccessIterator end,
+                  LessThan lessThan)
 {
     // The implementation is based on qMerge() from qalgorithms.h
     // Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
@@ -97,82 +120,29 @@ void KFileItemModelSortAlgorithm::merge(KFileItemModel* model,
     }
 
     if (len1 + len2 == 2) {
-        if (model->lessThan(*(begin + 1), *(begin))) {
+        if (lessThan(*(begin + 1), *(begin))) {
             qSwap(*begin, *(begin + 1));
         }
         return;
     }
 
-    QList<KFileItemModel::ItemData*>::iterator firstCut;
-    QList<KFileItemModel::ItemData*>::iterator secondCut;
+    RandomAccessIterator firstCut;
+    RandomAccessIterator secondCut;
     int len2Half;
     if (len1 > len2) {
         const int len1Half = len1 / 2;
         firstCut = begin + len1Half;
-        secondCut = lowerBound(model, pivot, end, *firstCut);
+        secondCut = std::lower_bound(pivot, end, *firstCut, lessThan);
         len2Half = secondCut - pivot;
     } else {
         len2Half = len2 / 2;
         secondCut = pivot + len2Half;
-        firstCut = upperBound(model, begin, pivot, *secondCut);
+        firstCut = std::upper_bound(begin, pivot, *secondCut, lessThan);
     }
 
     std::rotate(firstCut, pivot, secondCut);
 
-    const QList<KFileItemModel::ItemData*>::iterator newPivot = firstCut + len2Half;
-    merge(model, begin, firstCut, newPivot);
-    merge(model, newPivot, secondCut, end);
-}
-
-
-QList<KFileItemModel::ItemData*>::iterator
-KFileItemModelSortAlgorithm::lowerBound(KFileItemModel* model,
-                                        QList<KFileItemModel::ItemData*>::iterator begin,
-                                        QList<KFileItemModel::ItemData*>::iterator end,
-                                        const KFileItemModel::ItemData* value)
-{
-    // The implementation is based on qLowerBound() from qalgorithms.h
-    // Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-
-    QList<KFileItemModel::ItemData*>::iterator middle;
-    int n = int(end - begin);
-    int half;
-
-    while (n > 0) {
-        half = n >> 1;
-        middle = begin + half;
-        if (model->lessThan(*middle, value)) {
-            begin = middle + 1;
-            n -= half + 1;
-        } else {
-            n = half;
-        }
-    }
-    return begin;
-}
-
-QList<KFileItemModel::ItemData*>::iterator
-KFileItemModelSortAlgorithm::upperBound(KFileItemModel* model,
-                                        QList<KFileItemModel::ItemData*>::iterator begin,
-                                        QList<KFileItemModel::ItemData*>::iterator end,
-                                        const KFileItemModel::ItemData* value)
-{
-    // The implementation is based on qUpperBound() from qalgorithms.h
-    // Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-
-    QList<KFileItemModel::ItemData*>::iterator middle;
-    int n = end - begin;
-    int half;
-
-    while (n > 0) {
-        half = n >> 1;
-        middle = begin + half;
-        if (model->lessThan(value, *middle)) {
-            n = half;
-        } else {
-            begin = middle + 1;
-            n -= half + 1;
-        }
-    }
-    return begin;
+    RandomAccessIterator newPivot = firstCut + len2Half;
+    merge(begin, firstCut, newPivot, lessThan);
+    merge(newPivot, secondCut, end, lessThan);
 }
index b86d490aae9cb08d4cd122c2e8aca8e77d88fd43..6e6db7d5e1a65d4dffc236847b778d88ef5c5575 100644 (file)
@@ -42,34 +42,25 @@ public:
     static void sort(KFileItemModel* model,
                      QList<KFileItemModel::ItemData*>::iterator begin,
                      QList<KFileItemModel::ItemData*>::iterator end);
+};
 
-private:
-    static void sequentialSort(KFileItemModel* model,
-                               QList<KFileItemModel::ItemData*>::iterator begin,
-                               QList<KFileItemModel::ItemData*>::iterator end);
-
-    static void parallelSort(KFileItemModel* model,
-                             QList<KFileItemModel::ItemData*>::iterator begin,
-                             QList<KFileItemModel::ItemData*>::iterator end,
-                             const int numberOfThreads);
-
-    static void merge(KFileItemModel* model,
-                      QList<KFileItemModel::ItemData*>::iterator begin,
-                      QList<KFileItemModel::ItemData*>::iterator pivot,
-                      QList<KFileItemModel::ItemData*>::iterator end);
+template <typename RandomAccessIterator, typename LessThan>
+static void sequentialSort(RandomAccessIterator begin,
+                           RandomAccessIterator end,
+                           LessThan lessThan);
 
-    static QList<KFileItemModel::ItemData*>::iterator
-                lowerBound(KFileItemModel* model,
-                           QList<KFileItemModel::ItemData*>::iterator begin,
-                           QList<KFileItemModel::ItemData*>::iterator end,
-                           const KFileItemModel::ItemData* value);
+template <typename RandomAccessIterator, typename LessThan>
+static void parallelSort(RandomAccessIterator begin,
+                         RandomAccessIterator end,
+                         LessThan lessThan,
+                         int numberOfThreads,
+                         int parallelSortingThreshold = 100);
 
-    static QList<KFileItemModel::ItemData*>::iterator
-                upperBound(KFileItemModel* model,
-                           QList<KFileItemModel::ItemData*>::iterator begin,
-                           QList<KFileItemModel::ItemData*>::iterator end,
-                           const KFileItemModel::ItemData* value);
-};
+template <typename RandomAccessIterator, typename LessThan>
+static void merge(RandomAccessIterator begin,
+                  RandomAccessIterator pivot,
+                  RandomAccessIterator end,
+                  LessThan lessThan);
 
 #endif