RAUL  0.8.0
DoubleBuffer.hpp
1 /* This file is part of Raul.
2  * Copyright (C) 2007-2009 David Robillard <http://drobilla.net>
3  *
4  * Raul is free software; you can redistribute it and/or modify it under the
5  * terms of the GNU General Public License as published by the Free Software
6  * Foundation; either version 2 of the License, or (at your option) any later
7  * version.
8  *
9  * Raul is distributed in the hope that it will be useful, but WITHOUT ANY
10  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16  */
17 
18 #ifndef RAUL_DOUBLE_BUFFER_HPP
19 #define RAUL_DOUBLE_BUFFER_HPP
20 
21 #include "raul/AtomicInt.hpp"
22 #include "raul/AtomicPtr.hpp"
23 
24 namespace Raul {
25 
36 template<typename T>
37 class DoubleBuffer {
38 public:
39 
40  inline DoubleBuffer(T val)
41  : _state(RAUL_DB_READ_WRITE)
42  {
43  _vals[0] = val;
44  _read_val = &_vals[0];
45  }
46 
47  inline DoubleBuffer(const DoubleBuffer& copy)
48  : _state(RAUL_DB_READ_WRITE)
49  {
50  T val = copy.get();
51  _vals[0] = val;
52  _read_val = &_vals[0];
53  }
54 
55  inline T& get() const {
56  return *_read_val.get();
57  }
58 
59  inline bool set(T new_val) {
60  if (_state.compare_and_exchange(RAUL_DB_READ_WRITE, RAUL_DB_READ_LOCK)) {
61 
62  // locked _vals[1] for write
63  _vals[1] = new_val;
64  _read_val = &_vals[1];
65  _state = RAUL_DB_WRITE_READ;
66  return true;
67 
68  // concurrent calls here are fine. good, actually - caught
69  // the WRITE_READ state immediately after it was set above
70 
71  } else if (_state.compare_and_exchange(RAUL_DB_WRITE_READ, RAUL_DB_LOCK_READ)) {
72 
73  // locked _vals[0] for write
74  _vals[0] = new_val;
75  _read_val = &_vals[0];
76  _state = RAUL_DB_READ_WRITE;
77  return true;
78 
79  } else {
80 
81  return false;
82 
83  }
84  }
85 
86 private:
87  enum States {
88  // vals[0] state _ vals[1] state
89  RAUL_DB_READ_WRITE = 0,
90  RAUL_DB_READ_LOCK,
91  RAUL_DB_WRITE_READ,
92  RAUL_DB_LOCK_READ
93  };
94 
95  AtomicInt _state;
96  AtomicPtr<T> _read_val;
97  T _vals[2];
98 };
99 
100 
101 } // namespace Raul
102 
103 #endif // RAUL_DOUBLE_BUFFER_HPP
Atomic pointer.
Definition: AtomicPtr.hpp:30
Definition: Array.hpp:26
Double buffer.
Definition: DoubleBuffer.hpp:37
bool compare_and_exchange(int old, int val)
Set value to val iff current value is old.
Definition: AtomicInt.hpp:64
Atomic integer.
Definition: AtomicInt.hpp:29