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