1 // 2 // SuperTuxKart - a fun racing game with go-kart 3 // Copyright (C) 2010-2015 Joerg Henrichs 4 // 5 // This program is free software; you can redistribute it and/or 6 // modify it under the terms of the GNU General Public License 7 // as published by the Free Software Foundation; either version 3 8 // of the License, or (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 // 15 // You should have received a copy of the GNU General Public License 16 // along with this program; if not, write to the Free Software 17 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 19 #ifndef HEADER_SYNCHRONISED_HPP 20 #define HEADER_SYNCHRONISED_HPP 21 22 #include <mutex> 23 24 /** A variable that is automatically synchronised using pthreads mutex. 25 */ 26 template<typename TYPE> 27 class Synchronised 28 { 29 private: 30 /** The mutex to protect this variable with. */ 31 mutable std::mutex m_mutex; 32 /** The actual data to be used. */ 33 TYPE m_data; 34 public: 35 // ------------------------------------------------------------------------ 36 /** Initialise the data and the mutex with default constructors. */ Synchronised()37 Synchronised() : m_data() 38 { 39 } // Synchronised() 40 41 // ------------------------------------------------------------------------ 42 /** Initialise the data and the mutex. */ Synchronised(const TYPE & v)43 Synchronised(const TYPE &v) 44 { 45 m_data = v; 46 } // Synchronised 47 48 // ------------------------------------------------------------------------ 49 /** Destroy this mutex. 50 */ ~Synchronised()51 ~Synchronised() 52 { 53 } // ~Synchronised 54 55 // ------------------------------------------------------------------------ 56 /** Sets the value of this variable using a mutex. 57 * \param v Value to be set. 58 */ setAtomic(const TYPE & v)59 void setAtomic(const TYPE &v) 60 { 61 std::lock_guard<std::mutex> lock(m_mutex); 62 m_data = v; 63 } // set 64 65 // ------------------------------------------------------------------------ 66 /** Returns a copy of this variable. 67 */ getAtomic() const68 TYPE getAtomic() const 69 { 70 TYPE v; 71 std::unique_lock<std::mutex> ul(m_mutex); 72 v = m_data; 73 ul.unlock(); 74 return v; 75 } // get 76 // ------------------------------------------------------------------------ 77 /** Returns a reference to the original data file. NOTE: all access to 78 * the data files happen without mutex protection, so calls to lock 79 * and unlock are necessary. This method is useful in cases that several 80 * operations on the class must happen atomic. 81 */ getData()82 TYPE &getData() 83 { 84 return m_data; 85 } // getData 86 // ------------------------------------------------------------------------ getData() const87 const TYPE &getData() const 88 { 89 return m_data; 90 } // getData 91 // ------------------------------------------------------------------------ 92 /** Locks the mutex. Note that calls to get() or set() will fail, since 93 * they will try to lock the mutex as well! 94 */ lock() const95 void lock() const { m_mutex.lock(); } 96 // ------------------------------------------------------------------------ 97 /** Unlocks the mutex. 98 */ unlock() const99 void unlock() const { m_mutex.unlock(); } 100 // ------------------------------------------------------------------------ 101 /** Gives unique_lock to the mutex, which can then be used by 102 * std::condition_variable wait. */ acquireMutex() const103 std::unique_lock<std::mutex> acquireMutex() const 104 { return std::unique_lock<std::mutex>(m_mutex); } 105 private: 106 // Make sure that no actual copying is taking place 107 // ------------------------------------------------------------------------ operator =(const Synchronised<TYPE> & v)108 void operator=(const Synchronised<TYPE>& v) {} 109 }; 110 111 #endif 112