This repository has been archived by the owner on Feb 3, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
OptimizableMD.h
92 lines (76 loc) · 2.46 KB
/
OptimizableMD.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
//
// Created by MMarco on 25/02/2019.
//
#ifndef MATRIX_OPIMIZABLEMD_H
#define MATRIX_OPIMIZABLEMD_H
#include <deque>
#include <future>
#include "MatrixData.h"
template<typename T, class O>
class OptimizableMD : public MatrixData<T> {
protected:
mutable std::mutex optimizeMutex; //Mutex for the method optimize()
private:
mutable std::shared_future<std::unique_ptr<O>> optimized;
//I'm saving the pointer to optimized matrix in order to skip accessing it through a future and a unique_ptr
mutable O *optimizedPointer = NULL;
public:
OptimizableMD(unsigned int rows, unsigned int columns) :
MatrixData<T>(rows, columns) {
}
OptimizableMD(const OptimizableMD<T, O> &another) :
MatrixData<T>(another.rows(), another.columns()) {
//The cached data is not passed around, since it will be too difficult to copy
if (another.optimizedPointer != NULL) {
std::cout << "Warning: cached data is lost!\n";
}
}
OptimizableMD(OptimizableMD<T, O> &&another) noexcept :
MatrixData<T>(another.rows(), another.columns()) {
//The cached data is not passed around, since it will be too difficult to move
}
virtual ~OptimizableMD() {
if (this->optimized.valid()) {
this->optimized.wait();
}
}
MATERIALIZE_IMPL
void virtualWaitOptimized() const override {
MatrixData<T>::virtualWaitOptimized();
auto future = this->optimized;
if (future.valid()) {
future.wait();
}
if (this->optimizedPointer != NULL) {
this->optimizedPointer->virtualWaitOptimized();
}
}
void virtualOptimize() const override {
this->optimize();
}
void optimize() const {
std::unique_lock<std::mutex> lock(this->optimizeMutex);
if (!this->optimizeHasBeenCalled) {
this->optimized = std::async(std::launch::async, [=] {
auto ptr = this->virtualCreateOptimizedMatrix();
ptr->virtualOptimize();
return ptr;
}).share();
this->optimizeHasBeenCalled = true;
}
}
private:
T doGet(unsigned row, unsigned col) const {
if (this->optimizedPointer == NULL) {
//I'm saving the pointer to optimized matrix in order to skip accessing it through a future and a unique_ptr
this->optimizedPointer = optimized.get().get();
}
return this->optimizedPointer->get(row, col);
}
protected:
/**
* This method optimizes the multiplication if the multiplication chain involves more than three matrix.
*/
virtual std::unique_ptr<O> virtualCreateOptimizedMatrix() const = 0;
};
#endif //MATRIX_OPIMIZABLEMD_H