RAUL 0.8.0

- Main Page
- Modules
- Namespaces
- Classes
- Files

- File List

DoubleBuffer.hpp

    00001 /* This file is part of Raul.
    00002  * Copyright (C) 2007-2009 David Robillard <http://drobilla.net>
    00003  *
    00004  * Raul is free software; you can redistribute it and/or modify it under the
    00005  * terms of the GNU General Public License as published by the Free Software
    00006  * Foundation; either version 2 of the License, or (at your option) any later
    00007  * version.
    00008  *
    00009  * Raul is distributed in the hope that it will be useful, but WITHOUT ANY
    00010  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    00011  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for details.
    00012  *
    00013  * You should have received a copy of the GNU General Public License along
    00014  * with this program; if not, write to the Free Software Foundation, Inc.,
    00015  * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
    00016  */
    00017
    00018 #ifndef RAUL_DOUBLE_BUFFER_HPP
    00019 #define RAUL_DOUBLE_BUFFER_HPP
    00020
    00021 #include "raul/AtomicInt.hpp"
    00022 #include "raul/AtomicPtr.hpp"
    00023
    00024 namespace Raul {
    00025
    00036 template<typename T>
    00037 class DoubleBuffer {
    00038 public:
    00039
    00040     inline DoubleBuffer(T val)
    00041         : _state(RAUL_DB_READ_WRITE)
    00042     {
    00043         _vals[0] = val;
    00044         _read_val = &_vals[0];
    00045     }
    00046
    00047     inline DoubleBuffer(const DoubleBuffer& copy)
    00048         : _state(RAUL_DB_READ_WRITE)
    00049     {
    00050         T val = copy.get();
    00051         _vals[0] = val;
    00052         _read_val = &_vals[0];
    00053     }
    00054
    00055     inline T& get() const {
    00056         return *_read_val.get();
    00057     }
    00058
    00059     inline bool set(T new_val) {
    00060         if (_state.compare_and_exchange(RAUL_DB_READ_WRITE, RAUL_DB_READ_LOCK)) {
    00061
    00062             // locked _vals[1] for write
    00063             _vals[1] = new_val;
    00064             _read_val = &_vals[1];
    00065             _state = RAUL_DB_WRITE_READ;
    00066             return true;
    00067
    00068             // concurrent calls here are fine.  good, actually - caught
    00069             // the WRITE_READ state immediately after it was set above
    00070
    00071         } else if (_state.compare_and_exchange(RAUL_DB_WRITE_READ, RAUL_DB_LOCK_READ)) {
    00072
    00073             // locked _vals[0] for write
    00074             _vals[0] = new_val;
    00075             _read_val = &_vals[0];
    00076             _state = RAUL_DB_READ_WRITE;
    00077             return true;
    00078
    00079         } else {
    00080
    00081             return false;
    00082
    00083         }
    00084     }
    00085
    00086 private:
    00087     enum States {
    00088         // vals[0] state _ vals[1] state
    00089         RAUL_DB_READ_WRITE = 0,
    00090         RAUL_DB_READ_LOCK,
    00091         RAUL_DB_WRITE_READ,
    00092         RAUL_DB_LOCK_READ
    00093     };
    00094
    00095     AtomicInt    _state;
    00096     AtomicPtr<T> _read_val;
    00097     T            _vals[2];
    00098 };
    00099
    00100
    00101 } // namespace Raul
    00102
    00103 #endif // RAUL_DOUBLE_BUFFER_HPP