File indexing completed on 2024-04-28 04:01:22
0001 /* -*- C++ -*- 0002 This file implements the Collection class. 0003 0004 SPDX-FileCopyrightText: 2004-2013 Mirko Boehm <mirko@kde.org> 0005 0006 SPDX-License-Identifier: LGPL-2.0-or-later 0007 */ 0008 0009 #include "collection.h" 0010 0011 #include "collection_p.h" 0012 #include "debuggingaids.h" 0013 #include "queueapi.h" 0014 #include "queueing.h" 0015 0016 #include <QList> 0017 #include <QObject> 0018 #include <QPointer> 0019 0020 #include "dependencypolicy.h" 0021 #include "executewrapper_p.h" 0022 #include "thread.h" 0023 0024 namespace ThreadWeaver 0025 { 0026 class CollectionExecuteWrapper : public ExecuteWrapper 0027 { 0028 public: 0029 CollectionExecuteWrapper() 0030 : collection(nullptr) 0031 { 0032 } 0033 0034 void setCollection(Collection *collection_) 0035 { 0036 collection = collection_; 0037 } 0038 0039 void begin(const JobPointer &job, Thread *thread) override 0040 { 0041 TWDEBUG(4, "CollectionExecuteWrapper::begin: collection %p\n", collection); 0042 ExecuteWrapper::begin(job, thread); 0043 Q_ASSERT(collection); 0044 collection->d()->elementStarted(collection, job, thread); 0045 ExecuteWrapper::begin(job, thread); 0046 } 0047 0048 void end(const JobPointer &job, Thread *thread) override 0049 { 0050 TWDEBUG(4, "CollectionExecuteWrapper::end: collection %p\n", collection); 0051 Q_ASSERT(collection); 0052 ExecuteWrapper::end(job, thread); 0053 collection->d()->elementFinished(collection, job, thread); 0054 } 0055 0056 bool ownedByJob() const override 0057 { 0058 return true; 0059 } 0060 0061 private: 0062 ThreadWeaver::Collection *collection; 0063 }; 0064 0065 Collection::Collection() 0066 : Job(new Private::Collection_Private) 0067 { 0068 } 0069 0070 Collection::Collection(Private::Collection_Private *d__) 0071 : Job(d__) 0072 { 0073 } 0074 0075 Collection::~Collection() 0076 { 0077 MUTEX_ASSERT_UNLOCKED(mutex()); 0078 // dequeue all remaining jobs: 0079 QMutexLocker l(mutex()); 0080 Q_UNUSED(l); 0081 if (d()->api != nullptr) { // still queued 0082 d()->dequeueElements(this, false); 0083 } 0084 } 0085 0086 void Collection::addJob(JobPointer job) 0087 { 0088 QMutexLocker l(mutex()); 0089 Q_UNUSED(l); 0090 REQUIRE(d()->api == nullptr || d()->selfIsExecuting == true); // not queued yet or still running 0091 REQUIRE(job != nullptr); 0092 0093 CollectionExecuteWrapper *wrapper = new CollectionExecuteWrapper(); 0094 wrapper->setCollection(this); 0095 wrapper->wrap(job->setExecutor(wrapper)); 0096 d()->elements.append(job); 0097 } 0098 0099 void Collection::stop() 0100 { 0101 d()->stop(this); 0102 } 0103 0104 void Collection::requestAbort() 0105 { 0106 Job::requestAbort(); 0107 d()->requestAbort(this); 0108 } 0109 0110 void Collection::aboutToBeQueued_locked(QueueAPI *api) 0111 { 0112 Q_ASSERT(!mutex()->tryLock()); 0113 Q_ASSERT(d()->api == nullptr); // never queue twice 0114 d()->api = api; 0115 d()->selfExecuteWrapper.wrap(setExecutor(&d()->selfExecuteWrapper)); 0116 CollectionExecuteWrapper *wrapper = new CollectionExecuteWrapper(); 0117 wrapper->setCollection(this); 0118 wrapper->wrap(setExecutor(wrapper)); 0119 Job::aboutToBeQueued_locked(api); 0120 } 0121 0122 void Collection::aboutToBeDequeued_locked(QueueAPI *api) 0123 { 0124 Q_ASSERT(!mutex()->tryLock()); 0125 Q_ASSERT(api && d()->api == api); 0126 d()->dequeueElements(this, true); 0127 d()->api = nullptr; 0128 0129 Q_ASSERT(dynamic_cast<CollectionExecuteWrapper *>(executor())); 0130 auto wrapper = static_cast<CollectionExecuteWrapper *>(executor()); 0131 wrapper->unwrap(this); 0132 delete wrapper; 0133 0134 Q_ASSERT(executor() == &d()->selfExecuteWrapper); 0135 d()->selfExecuteWrapper.unwrap(this); 0136 0137 Job::aboutToBeDequeued_locked(api); 0138 } 0139 0140 void Collection::execute(const JobPointer &job, Thread *thread) 0141 { 0142 { 0143 QMutexLocker l(mutex()); 0144 Q_UNUSED(l); 0145 Q_ASSERT(d()->self.isNull()); 0146 Q_ASSERT(d()->api != nullptr); 0147 d()->self = job; 0148 d()->selfIsExecuting = true; // reset in elementFinished 0149 } 0150 Job::execute(job, thread); 0151 } 0152 0153 void Collection::run(JobPointer, Thread *) 0154 { 0155 // empty 0156 } 0157 0158 Private::Collection_Private *Collection::d() 0159 { 0160 return reinterpret_cast<Private::Collection_Private *>(Job::d()); 0161 } 0162 0163 const Private::Collection_Private *Collection::d() const 0164 { 0165 return reinterpret_cast<const Private::Collection_Private *>(Job::d()); 0166 } 0167 0168 JobPointer Collection::jobAt(int i) 0169 { 0170 Q_ASSERT(!mutex()->tryLock()); 0171 Q_ASSERT(i >= 0 && i < d()->elements.size()); 0172 return d()->elements.at(i); 0173 } 0174 0175 int Collection::elementCount() const 0176 { 0177 QMutexLocker l(mutex()); 0178 Q_UNUSED(l); 0179 return jobListLength_locked(); 0180 } 0181 0182 int Collection::jobListLength_locked() const 0183 { 0184 return d()->elements.size(); 0185 } 0186 0187 Collection &Collection::operator<<(JobInterface *job) 0188 { 0189 addJob(make_job(job)); 0190 return *this; 0191 } 0192 0193 Collection &Collection::operator<<(const JobPointer &job) 0194 { 0195 addJob(job); 0196 return *this; 0197 } 0198 0199 Collection &Collection::operator<<(JobInterface &job) 0200 { 0201 addJob(make_job_raw(&job)); 0202 return *this; 0203 } 0204 0205 }