##// END OF EJS Templates
Add thread protection on variable
perrinel -
r512:cc9051180991
parent child
Show More
@@ -1,65 +1,65
1 1 #ifndef SCIQLOP_VARIABLE_H
2 2 #define SCIQLOP_VARIABLE_H
3 3
4 4 #include "CoreGlobal.h"
5 5
6 6 #include <Data/SqpRange.h>
7 7
8 8 #include <QLoggingCategory>
9 9 #include <QObject>
10 10
11 11 #include <Common/MetaTypes.h>
12 12 #include <Common/spimpl.h>
13 13
14 14 Q_DECLARE_LOGGING_CATEGORY(LOG_Variable)
15 15
16 16 class IDataSeries;
17 17 class QString;
18 18
19 19 /**
20 20 * @brief The Variable class represents a variable in SciQlop.
21 21 */
22 22 class SCIQLOP_CORE_EXPORT Variable : public QObject {
23 23
24 24 Q_OBJECT
25 25
26 26 public:
27 27 explicit Variable(const QString &name, const SqpRange &dateTime,
28 28 const QVariantHash &metadata = {});
29 29
30 30 QString name() const noexcept;
31 31 SqpRange range() const noexcept;
32 32 void setRange(const SqpRange &range) noexcept;
33 33 SqpRange cacheRange() const noexcept;
34 34 void setCacheRange(const SqpRange &cacheRange) noexcept;
35 35
36 36 /// @return the data of the variable, nullptr if there is no data
37 37 IDataSeries *dataSeries() const noexcept;
38 38
39 39 QVariantHash metadata() const noexcept;
40 40
41 41 bool contains(const SqpRange &range) const noexcept;
42 42 bool intersect(const SqpRange &range) const noexcept;
43 43 bool isInside(const SqpRange &range) const noexcept;
44 44
45 45 bool cacheContains(const SqpRange &range) const noexcept;
46 46 bool cacheIntersect(const SqpRange &range) const noexcept;
47 47 bool cacheIsInside(const SqpRange &range) const noexcept;
48 48
49 QVector<SqpRange> provideNotInCacheRangeList(const SqpRange &range);
49 QVector<SqpRange> provideNotInCacheRangeList(const SqpRange &range) const noexcept;
50 50 void setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept;
51 51 void mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept;
52 52
53 53 signals:
54 54 void updated();
55 55
56 56 private:
57 57 class VariablePrivate;
58 58 spimpl::unique_impl_ptr<VariablePrivate> impl;
59 59 };
60 60
61 61 // Required for using shared_ptr in signals/slots
62 62 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_REGISTRY, std::shared_ptr<Variable>)
63 63 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_VECTOR_REGISTRY, QVector<std::shared_ptr<Variable> >)
64 64
65 65 #endif // SCIQLOP_VARIABLE_H
@@ -1,169 +1,211
1 1 #include "Variable/Variable.h"
2 2
3 3 #include <Data/IDataSeries.h>
4 4 #include <Data/SqpRange.h>
5 5
6 #include <QMutex>
6 7 #include <QReadWriteLock>
7 8 #include <QThread>
8 9
9 10 Q_LOGGING_CATEGORY(LOG_Variable, "Variable")
10 11
11 12 struct Variable::VariablePrivate {
12 13 explicit VariablePrivate(const QString &name, const SqpRange &dateTime,
13 14 const QVariantHash &metadata)
14 15 : m_Name{name}, m_Range{dateTime}, m_Metadata{metadata}, m_DataSeries{nullptr}
15 16 {
16 17 }
17 18
19 void lockRead() { m_Lock.lockForRead(); }
20 void lockWrite() { m_Lock.lockForWrite(); }
21 void unlock() { m_Lock.unlock(); }
22
18 23 QString m_Name;
19 24
20 25 SqpRange m_Range;
21 26 SqpRange m_CacheRange;
22 27 QVariantHash m_Metadata;
23 28 std::unique_ptr<IDataSeries> m_DataSeries;
29
30 QReadWriteLock m_Lock;
24 31 };
25 32
26 33 Variable::Variable(const QString &name, const SqpRange &dateTime, const QVariantHash &metadata)
27 34 : impl{spimpl::make_unique_impl<VariablePrivate>(name, dateTime, metadata)}
28 35 {
29 36 }
30 37
31 38 QString Variable::name() const noexcept
32 39 {
33 return impl->m_Name;
40 impl->lockRead();
41 auto name = impl->m_Name;
42 impl->unlock();
43 return name;
34 44 }
35 45
36 46 SqpRange Variable::range() const noexcept
37 47 {
38 return impl->m_Range;
48 impl->lockRead();
49 auto range = impl->m_Range;
50 impl->unlock();
51 return range;
39 52 }
40 53
41 54 void Variable::setRange(const SqpRange &range) noexcept
42 55 {
56 impl->lockWrite();
43 57 impl->m_Range = range;
58 impl->unlock();
44 59 }
45 60
46 61 SqpRange Variable::cacheRange() const noexcept
47 62 {
48 return impl->m_CacheRange;
63 impl->lockRead();
64 auto cacheRange = impl->m_CacheRange;
65 impl->unlock();
66 return cacheRange;
49 67 }
50 68
51 69 void Variable::setCacheRange(const SqpRange &cacheRange) noexcept
52 70 {
71 impl->lockWrite();
53 72 impl->m_CacheRange = cacheRange;
73 impl->unlock();
54 74 }
55 75
56 76 void Variable::setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
57 77 {
58 qCDebug(LOG_Variable()) << "Variable::setDataSeries" << QThread::currentThread()->objectName();
78 qCInfo(LOG_Variable()) << "Variable::setDataSeries" << QThread::currentThread()->objectName();
59 79 if (!dataSeries) {
60 80 /// @todo ALX : log
61 81 return;
62 82 }
63
83 impl->lockWrite();
64 84 impl->m_DataSeries = dataSeries->clone();
65
66 // // Inits the data series of the variable
67 // if (!impl->m_DataSeries) {
68 // impl->m_DataSeries = dataSeries->clone();
69 // }
70 // else {
71 // impl->m_DataSeries->merge(dataSeries.get());
72 // }
85 impl->unlock();
73 86 }
74 87
75 88 void Variable::mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
76 89 {
77 qCDebug(LOG_Variable()) << "Variable::setDataSeries" << QThread::currentThread()->objectName();
90 qCDebug(LOG_Variable()) << "Variable::mergeDataSeries"
91 << QThread::currentThread()->objectName();
78 92 if (!dataSeries) {
79 93 /// @todo ALX : log
80 94 return;
81 95 }
82 96
83 97 // Add or merge the data
84 98 // Inits the data series of the variable
99 impl->lockWrite();
85 100 if (!impl->m_DataSeries) {
86 101 impl->m_DataSeries = dataSeries->clone();
87 102 }
88 103 else {
89 104 impl->m_DataSeries->merge(dataSeries.get());
90 105 }
106 impl->unlock();
91 107
92 108 // sub the data
93 109 auto subData = this->dataSeries()->subData(this->cacheRange());
94 110 qCCritical(LOG_Variable()) << "TORM: Variable::mergeDataSeries sub" << subData->range();
95 111 this->setDataSeries(subData);
96 112 qCCritical(LOG_Variable()) << "TORM: Variable::mergeDataSeries set"
97 113 << this->dataSeries()->range();
98 114 }
99 115
100 116 IDataSeries *Variable::dataSeries() const noexcept
101 117 {
102 return impl->m_DataSeries.get();
118 impl->lockRead();
119 auto dataSeries = impl->m_DataSeries.get();
120 impl->unlock();
121
122 return dataSeries;
103 123 }
104 124
105 125 QVariantHash Variable::metadata() const noexcept
106 126 {
107 return impl->m_Metadata;
127 impl->lockRead();
128 auto metadata = impl->m_Metadata;
129 impl->unlock();
130 return metadata;
108 131 }
109 132
110 133 bool Variable::contains(const SqpRange &range) const noexcept
111 134 {
112 return impl->m_Range.contains(range);
135 impl->lockRead();
136 auto res = impl->m_Range.contains(range);
137 impl->unlock();
138 return res;
113 139 }
114 140
115 141 bool Variable::intersect(const SqpRange &range) const noexcept
116 142 {
117 return impl->m_Range.intersect(range);
143
144 impl->lockRead();
145 auto res = impl->m_Range.intersect(range);
146 impl->unlock();
147 return res;
118 148 }
119 149
120 150 bool Variable::isInside(const SqpRange &range) const noexcept
121 151 {
122 return range.contains(SqpRange{impl->m_Range.m_TStart, impl->m_Range.m_TEnd});
152 impl->lockRead();
153 auto res = range.contains(SqpRange{impl->m_Range.m_TStart, impl->m_Range.m_TEnd});
154 impl->unlock();
155 return res;
123 156 }
124 157
125 158 bool Variable::cacheContains(const SqpRange &range) const noexcept
126 159 {
127 return impl->m_CacheRange.contains(range);
160 impl->lockRead();
161 auto res = impl->m_CacheRange.contains(range);
162 impl->unlock();
163 return res;
128 164 }
129 165
130 166 bool Variable::cacheIntersect(const SqpRange &range) const noexcept
131 167 {
132 return impl->m_CacheRange.intersect(range);
168 impl->lockRead();
169 auto res = impl->m_CacheRange.intersect(range);
170 impl->unlock();
171 return res;
133 172 }
134 173
135 174 bool Variable::cacheIsInside(const SqpRange &range) const noexcept
136 175 {
137 return range.contains(SqpRange{impl->m_CacheRange.m_TStart, impl->m_CacheRange.m_TEnd});
176 impl->lockRead();
177 auto res = range.contains(SqpRange{impl->m_CacheRange.m_TStart, impl->m_CacheRange.m_TEnd});
178 impl->unlock();
179 return res;
138 180 }
139 181
140 182
141 QVector<SqpRange> Variable::provideNotInCacheRangeList(const SqpRange &range)
183 QVector<SqpRange> Variable::provideNotInCacheRangeList(const SqpRange &range) const noexcept
142 184 {
143 185 auto notInCache = QVector<SqpRange>{};
144 186
145 187 if (!this->cacheContains(range)) {
146 188 if (range.m_TEnd <= impl->m_CacheRange.m_TStart
147 189 || range.m_TStart >= impl->m_CacheRange.m_TEnd) {
148 190 notInCache << range;
149 191 }
150 192 else if (range.m_TStart < impl->m_CacheRange.m_TStart
151 193 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
152 194 notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart};
153 195 }
154 196 else if (range.m_TStart < impl->m_CacheRange.m_TStart
155 197 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
156 198 notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart}
157 199 << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
158 200 }
159 201 else if (range.m_TStart < impl->m_CacheRange.m_TEnd) {
160 202 notInCache << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
161 203 }
162 204 else {
163 205 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
164 206 << QThread::currentThread();
165 207 }
166 208 }
167 209
168 210 return notInCache;
169 211 }
General Comments 1
Under Review
author

Auto status change to "Under Review"

You need to be logged in to leave comments. Login now