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