ThreadWeaver

collection.cpp
1 /* -*- C++ -*-
2  This file implements the Collection class.
3 
4  SPDX-FileCopyrightText: 2004-2013 Mirko Boehm <[email protected]>
5 
6  SPDX-License-Identifier: LGPL-2.0-or-later
7 */
8 
9 #include "collection.h"
10 
11 #include "collection_p.h"
12 #include "debuggingaids.h"
13 #include "queueapi.h"
14 #include "queueing.h"
15 
16 #include <QList>
17 #include <QObject>
18 #include <QPointer>
19 
20 #include "dependencypolicy.h"
21 #include "executewrapper_p.h"
22 #include "thread.h"
23 
24 namespace ThreadWeaver
25 {
26 class CollectionExecuteWrapper : public ExecuteWrapper
27 {
28 public:
29  CollectionExecuteWrapper()
30  : collection(nullptr)
31  {
32  }
33 
34  void setCollection(Collection *collection_)
35  {
36  collection = collection_;
37  }
38 
39  void begin(const JobPointer &job, Thread *thread) override
40  {
41  TWDEBUG(4, "CollectionExecuteWrapper::begin: collection %p\n", collection);
42  ExecuteWrapper::begin(job, thread);
43  Q_ASSERT(collection);
44  collection->d()->elementStarted(collection, job, thread);
45  ExecuteWrapper::begin(job, thread);
46  }
47 
48  void end(const JobPointer &job, Thread *thread) override
49  {
50  TWDEBUG(4, "CollectionExecuteWrapper::end: collection %p\n", collection);
51  Q_ASSERT(collection);
52  ExecuteWrapper::end(job, thread);
53  collection->d()->elementFinished(collection, job, thread);
54  }
55 
56  void cleanup(const JobPointer &job, Thread *) override
57  {
58  // Once job is unwrapped from us, this object is dangling. Job::executor points to the next higher up execute wrapper.
59  // It is thus safe to "delete this". By no means add any later steps after delete!
60  delete unwrap(job);
61  }
62 
63 private:
64  ThreadWeaver::Collection *collection;
65 };
66 
67 Collection::Collection()
68  : Job(new Private::Collection_Private)
69 {
70 }
71 
72 Collection::Collection(Private::Collection_Private *d__)
73  : Job(d__)
74 {
75 }
76 
77 Collection::~Collection()
78 {
79  MUTEX_ASSERT_UNLOCKED(mutex());
80  // dequeue all remaining jobs:
81  QMutexLocker l(mutex());
82  Q_UNUSED(l);
83  if (d()->api != nullptr) { // still queued
84  d()->dequeueElements(this, false);
85  }
86 }
87 
88 void Collection::addJob(JobPointer job)
89 {
90  QMutexLocker l(mutex());
91  Q_UNUSED(l);
92  REQUIRE(d()->api == nullptr || d()->selfIsExecuting == true); // not queued yet or still running
93  REQUIRE(job != nullptr);
94 
95  CollectionExecuteWrapper *wrapper = new CollectionExecuteWrapper();
96  wrapper->setCollection(this);
97  wrapper->wrap(job->setExecutor(wrapper));
98  d()->elements.append(job);
99 }
100 
102 {
103  Q_UNUSED(job);
104  QMutexLocker l(mutex());
105  Q_UNUSED(l);
106  d()->stop_locked(this);
107 }
108 
109 void Collection::aboutToBeQueued_locked(QueueAPI *api)
110 {
111  Q_ASSERT(!mutex()->tryLock());
112  Q_ASSERT(d()->api == nullptr); // never queue twice
113  d()->api = api;
114  d()->selfExecuteWrapper.wrap(setExecutor(&d()->selfExecuteWrapper));
115  CollectionExecuteWrapper *wrapper = new CollectionExecuteWrapper();
116  wrapper->setCollection(this);
117  wrapper->wrap(setExecutor(wrapper));
118  Job::aboutToBeQueued_locked(api);
119 }
120 
121 void Collection::aboutToBeDequeued_locked(QueueAPI *api)
122 {
123  Q_ASSERT(!mutex()->tryLock());
124  Q_ASSERT(api && d()->api == api);
125  d()->dequeueElements(this, true);
126  d()->api = nullptr;
127  Job::aboutToBeDequeued_locked(api);
128 }
129 
130 void Collection::execute(const JobPointer &job, Thread *thread)
131 {
132  {
133  QMutexLocker l(mutex());
134  Q_UNUSED(l);
135  Q_ASSERT(d()->self.isNull());
136  Q_ASSERT(d()->api != nullptr);
137  d()->self = job;
138  d()->selfIsExecuting = true; // reset in elementFinished
139  }
140  Job::execute(job, thread);
141 }
142 
143 void Collection::run(JobPointer, Thread *)
144 {
145  // empty
146 }
147 
148 Private::Collection_Private *Collection::d()
149 {
150  return reinterpret_cast<Private::Collection_Private *>(Job::d());
151 }
152 
153 const Private::Collection_Private *Collection::d() const
154 {
155  return reinterpret_cast<const Private::Collection_Private *>(Job::d());
156 }
157 
158 JobPointer Collection::jobAt(int i)
159 {
160  Q_ASSERT(!mutex()->tryLock());
161  Q_ASSERT(i >= 0 && i < d()->elements.size());
162  return d()->elements.at(i);
163 }
164 
165 int Collection::elementCount() const
166 {
167  QMutexLocker l(mutex());
168  Q_UNUSED(l);
169  return jobListLength_locked();
170 }
171 
172 #if THREADWEAVER_BUILD_DEPRECATED_SINCE(5, 0)
173 int Collection::jobListLength() const
174 {
175  QMutexLocker l(mutex());
176  Q_UNUSED(l);
177  return jobListLength_locked();
178 }
179 #endif
180 
181 int Collection::jobListLength_locked() const
182 {
183  return d()->elements.size();
184 }
185 
186 Collection &Collection::operator<<(JobInterface *job)
187 {
188  addJob(make_job(job));
189  return *this;
190 }
191 
192 Collection &Collection::operator<<(const JobPointer &job)
193 {
194  addJob(job);
195  return *this;
196 }
197 
198 Collection &Collection::operator<<(JobInterface &job)
199 {
200  addJob(make_job_raw(&job));
201  return *this;
202 }
203 
204 }
void stop(Ekos::AlignState mode)
const QList< QKeySequence > & begin()
Thread represents a worker thread in a Queue's inventory.
Definition: thread.h:27
A Collection is a vector of Jobs that will be queued together.
Definition: collection.h:31
const QList< QKeySequence > & end()
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Tue Feb 7 2023 04:09:38 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.