Line data Source code
1 : #include "OperationManager.h"
2 :
3 : #include "../utilities/Utilities.h"
4 : #include "../utilities/ErrorHandling.h"
5 : #include "../utilities/FangLogging.h"
6 :
7 2 : OperationManager::OperationManager(QObject *parent) :
8 : FangObject(parent),
9 2 : queue(),
10 2 : pending(),
11 4 : operationTimer()
12 : {
13 2 : operationTimer.setSingleShot(true);
14 2 : connect(&operationTimer, &QTimer::timeout, this, &OperationManager::runNextOperations);
15 2 : }
16 :
17 4 : OperationManager::~OperationManager()
18 : {
19 4 : }
20 :
21 0 : void OperationManager::enqueue(AsyncOperation *operation)
22 : {
23 0 : switch (operation->getPriority()) {
24 0 : case AsyncOperation::BACKGROUND:
25 : // Queue for the future.
26 0 : queue.enqueue(operation);
27 0 : executeOperations();
28 :
29 0 : break;
30 :
31 0 : case AsyncOperation::IMMEDIATE:
32 : // Let's do it!
33 0 : runNow(operation);
34 :
35 0 : break;
36 :
37 0 : default:
38 0 : FANG_UNREACHABLE("Invalid operation priority");
39 : // Treat as background operation to avoid crashes
40 : queue.enqueue(operation);
41 : executeOperations();
42 : break;
43 : }
44 0 : }
45 :
46 1 : void OperationManager::run(SyncOperation *operation)
47 : {
48 1 : operation->execute();
49 1 : }
50 :
51 0 : void OperationManager::onOperationFinished(AsyncOperation* operation)
52 : {
53 0 : pending.remove(operation);
54 0 : operation->deleteLater(); // Trigger safe deletion.
55 0 : }
56 :
57 0 : void OperationManager::executeOperations()
58 : {
59 : // Run the next operation at 300ms+ in the future.
60 0 : operationTimer.start(300);
61 0 : }
62 :
63 0 : void OperationManager::runNow(AsyncOperation *operation)
64 : {
65 : // Double check that we're in the right thread.
66 0 : FANG_CHECK(Utilities::isInMainThread(), "OperationManager::runNow called from non-main thread");
67 :
68 0 : pending.insert(operation);
69 0 : QObject::connect(operation, &AsyncOperation::finished, this, &OperationManager::onOperationFinished);
70 0 : operation->execute();
71 0 : }
72 :
73 0 : void OperationManager::runNextOperations()
74 : {
75 0 : if (queue.isEmpty()) {
76 0 : return; // Nothing to do.
77 : }
78 :
79 : // Don't do too much at once. Schedule another call in the future if we're still busy.
80 0 : if (pending.size() >= 2) {
81 0 : executeOperations();
82 :
83 0 : return;
84 : }
85 :
86 : // Pop the next 2 ops off the queue and run 'em.
87 0 : int i = 0;
88 0 : while(!queue.isEmpty()) {
89 0 : if (i >= 2) {
90 0 : break;
91 : }
92 :
93 0 : i++;
94 0 : AsyncOperation* operation = queue.dequeue();
95 0 : if (operation == nullptr) {
96 0 : qCDebug(logOperation) << "Op null";
97 0 : continue;
98 0 : }
99 :
100 : // And awaaaaay we go!
101 0 : runNow(operation);
102 : }
103 :
104 : // Schedule the next call.
105 0 : executeOperations();
106 : }
|