DSPatch  v.5.01
Signal.h
1 /************************************************************************
2 DSPatch - The C++ Flow-Based Programming Framework
3 Copyright (c) 2012-2018 Marcus Tomlinson
4 
5 This file is part of DSPatch.
6 
7 GNU Lesser General Public License Usage
8 This file may be used under the terms of the GNU Lesser General Public
9 License version 3.0 as published by the Free Software Foundation and
10 appearing in the file LICENSE included in the packaging of this file.
11 Please review the following information to ensure the GNU Lesser
12 General Public License version 3.0 requirements will be met:
13 http://www.gnu.org/copyleft/lgpl.html.
14 
15 Other Usage
16 Alternatively, this file may be used in accordance with the terms and
17 conditions contained in a signed written agreement between you and
18 Marcus Tomlinson.
19 
20 DSPatch is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
23 ************************************************************************/
24 
25 #pragma once
26 
27 #include <dspatch/Common.h>
28 
29 namespace DSPatch
30 {
31 
33 
44 class DLLEXPORT Signal final
45 {
46 public:
47  NONCOPYABLE( Signal );
48  DEFINE_PTRS( Signal );
49 
50  Signal();
51  ~Signal();
52 
53  bool HasValue() const;
54 
55  template <class ValueType>
56  ValueType* GetValue();
57 
58  template <class ValueType>
59  void SetValue( ValueType const& newValue );
60 
61  bool CopySignal( Signal::SPtr const& fromSignal );
62  bool MoveSignal( Signal::SPtr const& fromSignal );
63 
64  void ClearValue();
65 
66  std::type_info const& GetType() const;
67 
68 private:
69  struct _ValueHolder
70  {
71  NONCOPYABLE( _ValueHolder );
72 
73  _ValueHolder() = default;
74  virtual ~_ValueHolder() = default;
75 
76  virtual std::type_info const& GetType() const = 0;
77  virtual _ValueHolder* GetCopy() const = 0;
78  virtual void SetValue( _ValueHolder* valueHolder ) = 0;
79  };
80 
81  template <class ValueType>
82  struct _Value final : _ValueHolder
83  {
84  NONCOPYABLE( _Value );
85 
86  _Value( ValueType const& value )
87  : value( value )
88  , type( typeid( ValueType ) )
89  {
90  }
91 
92  virtual std::type_info const& GetType() const override
93  {
94  return type;
95  }
96 
97  virtual _ValueHolder* GetCopy() const override
98  {
99  return new _Value( value );
100  }
101 
102  virtual void SetValue( _ValueHolder* valueHolder ) override
103  {
104  value = ( (_Value<ValueType>*)valueHolder )->value;
105  }
106 
107  ValueType value;
108  std::type_info const& type;
109  };
110 
111  _ValueHolder* _valueHolder = nullptr;
112  bool _hasValue = false;
113 };
114 
115 template <class ValueType>
116 ValueType* Signal::GetValue()
117 {
118  // You might be thinking: Why the raw pointer return here?
119 
120  // This is mainly for performance, and partly for readability. Performance, because returning a
121  // shared_ptr here means having to store the value as a shared_ptr in Signal::_Value too. This
122  // adds yet another level of indirection to the value, as well as some reference counting
123  // overhead. These Get() and Set() methods are VERY frequently called, so doing as little as
124  // possible with the data here is best, which actually aids in the readably of the code too.
125 
126  if ( _hasValue && GetType() == typeid( ValueType ) )
127  {
128  return &( (_Value<ValueType>*)_valueHolder )->value;
129  }
130  else
131  {
132  return nullptr;
133  }
134 }
135 
136 template <class ValueType>
137 void Signal::SetValue( ValueType const& newValue )
138 {
139  if ( GetType() == typeid( ValueType ) )
140  {
141  ( (_Value<ValueType>*)_valueHolder )->value = newValue;
142  }
143  else
144  {
145  delete _valueHolder;
146  _valueHolder = new _Value<ValueType>( newValue );
147  }
148  _hasValue = true;
149 }
150 
151 } // namespace DSPatch
Value container used to carry data between components.
Definition: Signal.h:44