Scope
ScopeNumber.h
1 #pragma once
2 
3 #include "ScopeValue.h"
4 
5 namespace scope {
6 
9 template <class T>
10 class ScopeNumber
11  : public ScopeValue<T>
12  , virtual public ScopeValueBase {
13 
14 protected:
17 
20 
22  inline T CoerceValue(const T& v) const override {
23  return( ( v < lowerLimit ) ? lowerLimit : ( v > upperLimit ? upperLimit : v ) );
24  }
25 
26 public:
31  ScopeNumber(const T& _v = 0, const T& _ll = 0, const T& _ul = 0, const std::wstring& _name = L"None")
32  : ScopeValueBase(_name) {
33  SetWithLimits(_v, _ll, _ul);
34  }
35 
38  : ScopeValueBase(orig.Name()) {
39  SetWithLimits(orig.Value(), orig.ll(), orig.ul());
40  }
41 
44  // avoid self assignment (leads to deadlock)
45  if ( this != &v )
46  SetWithLimits(v.Value(), v.ll(), v.ul());
47  // assign name and rw state (after we have set the value)
49  return *this;
50  }
51 
53  ScopeNumber& operator=(const T& v) {
54  Set(v);
55  return *this;
56  }
57 
61  ScopeNumber& operator+=(const ScopeNumber<T>& v) {
62  Set(Value()+v.Value());
63  return *this;
64  }
65 
66  ScopeNumber& operator+=(const T& _val) {
67  Set(Value()+_val);
68  return *this;
69  }
70 
71  ScopeNumber& operator-=(const ScopeNumber<T>& v) {
72  Set(Value()-v.Value());
73  return *this;
74  }
75 
76  ScopeNumber& operator-=(const T& _val) {
77  Set(Value()-_val);
78  return *this;
79  }
80 
81  ScopeNumber& operator*=(const ScopeNumber<T>& v) {
82  Set(Value()*v.Value());
83  return *this;
84  }
85 
86  ScopeNumber& operator*=(const T& _val) {
87  Set(Value()*_val);
88  return *this;
89  }
90 
91  ScopeNumber& operator/=(const ScopeNumber<T>& v) {
92  Set(Value()/v.Value());
93  return *this;
94  }
95 
96  ScopeNumber& operator/=(const T& _val) {
97  Set(Value()/_val);
98  return *this;
99  }
100 
101  ScopeNumber operator+(const ScopeNumber<T>& v) const { return ScopeNumber(*this) += v; }
102  ScopeNumber operator-(const ScopeNumber<T>& v) const { return ScopeNumber(*this) -= v; }
103  ScopeNumber operator*(const ScopeNumber<T>& v) const { return ScopeNumber(*this) *= v; }
104  ScopeNumber operator/(const ScopeNumber<T>& v) const { return ScopeNumber(*this) /= v; }
105 
106  ScopeNumber operator+(const T& _val) const { return ScopeNumber(*this) += _val; }
107  ScopeNumber operator-(const T& _val) const { return ScopeNumber(*this) -= _val; }
108  ScopeNumber operator*(const T& _val) const { return ScopeNumber(*this) *= _val; }
109  ScopeNumber operator/(const T& _val) const { return ScopeNumber(*this) /= _val; }
115  bool operator<(const ScopeNumber<T>& r) const {
116  return ( Value() < r.Value() );
117  }
118 
119  bool operator<(const T& r) const {
120  return ( Value() < r );
121  }
122 
123  bool operator>(const ScopeNumber<T>& r) const {
124  return ( Value() > r.Value() );
125  }
126 
127  bool operator>(const T& r) const {
128  return ( Value() > r );
129  }
130 
131  bool operator==(const ScopeNumber<T>& r) const {
132  return ( Value() == r.Value() );
133  }
134 
135  /*bool operator==(T r) { // Bug? does not compile (see here: http://www.windows-api.com/microsoft/C/35711014/enum-operator-overload-ambiguity.aspx)
136  return ( Value() == r );
137  }*/
138 
139  bool operator!=(const ScopeNumber<T>& r) const {
140  return !(operator==(r));
141  }
142 
143  /* bool operator!=(const T& r) {
144  return !(operator==(r));
145  }*/
149  T ll() const {
150  std::lock_guard<std::mutex> lock(mutex);
151  return lowerLimit;
152  }
153 
155  T ul() const {
156  std::lock_guard<std::mutex> lock(mutex);
157  return upperLimit;
158  }
159 
161  T SetWithLimits(const T& v, const T& ll, const T& ul) {
162  SetLimits(ll, ul);
163  return Set(v);
164  }
165 
174  T SetLimits(const T& _ll, const T& _ul, const bool& _callguisignal = true, const bool& _callothersignal = true, const bool& _callatnochange = false) {
175  T tmp(value);
176  bool changed = false;
177  if ( readwrite ) {
178  std::lock_guard<std::mutex> lock(mutex);
179  lowerLimit = ( ( _ll < _ul ) ? _ll : _ul );
180  upperLimit = ( ( _ll < _ul ) ? _ul : _ll );
182  changed = (tmp != value);
183  // keep the (now possibly changed) value for later outside the protected area
184  tmp = value;
185  }
186  // Following code had to be copied from ScopeValue
187  // call signals after unlocking the mutex to avoid possible deadlock!
188  // Since signals2 is thread-safe we do not have to protect call to signal methods with a mutex.
189  // avoid calling when variable was not changed unless desired.
190  if ( changed || _callatnochange) {
191  if ( _callguisignal )
192  changesiggui();
193  if ( _callothersignal )
194  changesigother();
195  }
196  return tmp;
197  }
198 };
199 
200 }
std::wstring Name() const
signalchange_t changesigother
signal that is called for other stuff on value changes
virtual T Set(const T &_v, const bool &_callguisignal=true, const bool &_callothersignal=true, const bool &_callatnochange=false)
Sets the value and calls both change signals if the value actually changed.
Definition: ScopeValue.h:67
T lowerLimit
lower limit (including) to which the value is coerced
Definition: ScopeNumber.h:16
ScopeValueBase & operator=(const ScopeValueBase &_svb)
Safe assignment.
T Value() const
Definition: ScopeValue.h:46
std::mutex mutex
a mutex for protection.
T SetLimits(const T &_ll, const T &_ul, const bool &_callguisignal=true, const bool &_callothersignal=true, const bool &_callatnochange=false)
Sets the limits and coerces the value accordingly change signal is called if value has to be coerced...
Definition: ScopeNumber.h:174
T SetWithLimits(const T &v, const T &ll, const T &ul)
Sets new value and new limits at the same time.
Definition: ScopeNumber.h:161
T upperLimit
upper limit (including) to which the value is coerced
Definition: ScopeNumber.h:19
bool readwrite
read-write state, true if read&write, false if onyl read (not an atomic, since access to the data var...
ScopeNumber(const ScopeNumber< T > &orig)
Safe copy constructor.
Definition: ScopeNumber.h:37
ScopeNumber(const T &_v=0, const T &_ll=0, const T &_ul=0, const std::wstring &_name=L"None")
Definition: ScopeNumber.h:31
ScopeNumber & operator=(const ScopeNumber< T > &v)
Safe assignment.
Definition: ScopeNumber.h:43
T value
the value proper
Definition: ScopeValue.h:16
signalchange_t changesiggui
signal that is called for GUI on value changes
A templated class for a thread-safe numeric value, with signals that are called on value changes...
Definition: XYControl.h:7
Base class for a thread-safe value, with signals that are called on value changes.
Definition: ScopeValueBase.h:7
ScopeNumber & operator=(const T &v)
Safe assignment, does keep name and limits.
Definition: ScopeNumber.h:53
T CoerceValue(const T &v) const override
Does the actual coercion in between the lowerLimit and upperLimit.
Definition: ScopeNumber.h:22