1 | /* -*- C++ -*- |
2 | This file declares the Collection class. |
3 | |
4 | SPDX-FileCopyrightText: 2004-2013 Mirko Boehm <mirko@kde.org> |
5 | |
6 | SPDX-License-Identifier: LGPL-2.0-or-later |
7 | */ |
8 | |
9 | #ifndef JOBCOLLECTION_H |
10 | #define JOBCOLLECTION_H |
11 | |
12 | #include "job.h" |
13 | #include "jobpointer.h" |
14 | #include "lambda.h" |
15 | |
16 | #include <functional> |
17 | |
18 | namespace ThreadWeaver |
19 | { |
20 | class Thread; |
21 | class CollectionExecuteWrapper; |
22 | |
23 | namespace Private |
24 | { |
25 | class Collection_Private; |
26 | } |
27 | |
28 | /** A Collection is a vector of Jobs that will be queued together. |
29 | * In a Collection, the order of execution of the elements is not specified. |
30 | * |
31 | * It is intended that the collection is set up first and then |
32 | * queued. After queuing, no further jobs should be added to the collection. |
33 | */ |
34 | class THREADWEAVER_EXPORT Collection : public Job |
35 | { |
36 | public: |
37 | Collection(); |
38 | Collection(ThreadWeaver::Private::Collection_Private *d); |
39 | ~Collection() override; |
40 | |
41 | /** Append a job to the collection. |
42 | * |
43 | * To use Collection, create the Job objects first, add them to the collection, and then queue it. After |
44 | * the collection has been queued, no further Jobs are supposed to be added. |
45 | * |
46 | * @note Once the job has been added, execute wrappers can no more be set on it */ |
47 | virtual void addJob(JobPointer); |
48 | |
49 | /** Stop processing, dequeue all remaining Jobs. |
50 | * |
51 | * @since 6.0 |
52 | */ |
53 | void stop(); |
54 | |
55 | /** Dequeue all remaining Jobs and request abortion of all running jobs |
56 | * @see Job::requestAbort() |
57 | * |
58 | * @since 6.0 |
59 | */ |
60 | void requestAbort() override; |
61 | |
62 | /** Return the number of elements in the collection. */ |
63 | int elementCount() const; |
64 | |
65 | /** @brief Add the job to this collection by pointer. */ |
66 | Collection &operator<<(ThreadWeaver::JobInterface *job); |
67 | |
68 | /** @brief Add the job to this collection. */ |
69 | Collection &operator<<(const ThreadWeaver::JobPointer &job); |
70 | Collection &operator<<(JobInterface &job); |
71 | |
72 | protected: |
73 | /** Overload to queue the collection. */ |
74 | void aboutToBeQueued_locked(QueueAPI *api) override; |
75 | |
76 | /** Overload to dequeue the collection. */ |
77 | void aboutToBeDequeued_locked(QueueAPI *api) override; |
78 | |
79 | /** Return a ref-erence to the job in the job list at position i. */ |
80 | JobPointer jobAt(int i); |
81 | |
82 | // FIXME remove |
83 | /** Return the number of jobs in the joblist. |
84 | * Assumes that the mutex is being held. |
85 | */ |
86 | virtual int jobListLength_locked() const; |
87 | |
88 | protected: |
89 | /** Overload the execute method. */ |
90 | void execute(const JobPointer &job, Thread *) override; |
91 | |
92 | /** Overload run(). |
93 | * We have to. */ |
94 | void run(JobPointer self, Thread *thread) override; |
95 | |
96 | protected: |
97 | friend class CollectionExecuteWrapper; // needs to access d() |
98 | friend class Collection_Private; |
99 | ThreadWeaver::Private::Collection_Private *d(); |
100 | const ThreadWeaver::Private::Collection_Private *d() const; |
101 | }; |
102 | |
103 | /** |
104 | * Make a Collection that will execute specified callable (eg. Lambda) for each item in given iterable container |
105 | * You can use it to have a parallel map function. |
106 | */ |
107 | template<typename Iterable, typename FN> |
108 | QSharedPointer<Collection> make_collection(Iterable iterable, FN callable) |
109 | { |
110 | QSharedPointer<Collection> collection(new Collection()); |
111 | for (auto it = iterable.begin(); it != iterable.end(); ++it) { |
112 | *collection << make_job([callable, item = *it, collectionJob = collection.get()]() { |
113 | callable(item, *collectionJob); |
114 | }); |
115 | } |
116 | return collection; |
117 | } |
118 | } |
119 | |
120 | #endif |
121 | |