Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/network64/src/network/synchronisable/SynchronisableVariable.h @ 2255

Last change on this file since 2255 was 2246, checked in by scheusso, 16 years ago

forgot a file and removed some debug output

  • Property svn:eol-style set to native
File size: 7.9 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Oliver Scheuss, (C) 2008
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29
30#ifndef _NETWORK_SYNCHRONISABLEVARIABLE__
31#define _NETWORK_SYNCHRONISABLEVARIABLE__
32
33#include "core/Core.h"
34#include "core/CoreIncludes.h"
35#include <string>
36#include <cassert>
37#include "network/NetworkPrereqs.h"
38
39namespace orxonox{
40 
41  namespace variableDirection{
42    enum syncdirection{
43      toclient=0x1,
44      toserver=0x2
45    };
46    enum bidirectional{
47      serverMaster=0x1,
48      clientMaster=0x2
49    };
50  }
51 
52  class _NetworkExport SynchronisableVariableBase
53  {
54    public:
55      virtual void getData(uint8_t*& mem, uint8_t mode)=0;
56      virtual void putData(uint8_t*& mem, uint8_t mode, bool forceCallback = false)=0;
57      virtual uint32_t getSize(uint8_t mode)=0;
58      virtual void* getReference()=0;
59      virtual uint8_t getMode()=0;
60      virtual ~SynchronisableVariableBase() {}
61    protected:
62      static uint8_t state_;
63  };
64
65  template <class T>
66  class _NetworkExport SynchronisableVariable: public SynchronisableVariableBase
67  {
68    public:
69      SynchronisableVariable(T& variable, uint8_t syncDirection=variableDirection::toclient, NetworkCallbackBase *cb=0);
70      virtual ~SynchronisableVariable();
71
72      virtual inline uint8_t getMode(){ return mode_; }
73      virtual void getData(uint8_t*& mem, uint8_t mode);
74      virtual void putData(uint8_t*& mem, uint8_t mode, bool forceCallback = false);
75      virtual inline uint32_t getSize(uint8_t mode);
76      virtual void* getReference(){ return (void *)&this->variable_; }
77    protected:
78      inline bool checkEquality(uint8_t* mem);
79      inline void setAndIncrease(uint8_t*& mem);
80      inline void getAndIncrease(uint8_t*& mem);
81      inline uint32_t returnSize();
82     
83      T& variable_;
84      uint8_t mode_;
85      NetworkCallbackBase *callback_;
86  };
87 
88  template <class T>
89  class _NetworkExport SynchronisableVariableBidirectional: public SynchronisableVariable<T>
90  {
91    public:
92      SynchronisableVariableBidirectional(T& variable, uint8_t master=variableDirection::serverMaster, NetworkCallbackBase *cb=0);
93      virtual ~SynchronisableVariableBidirectional();
94     
95      virtual inline uint8_t getMode(){ return 0x3; } //this basically is a hack ^^
96      virtual void getData(uint8_t*& mem, uint8_t mode);
97      virtual void putData(uint8_t*& mem, uint8_t mode, bool forceCallback = false);
98      virtual inline uint32_t getSize(uint8_t mode);
99    private:
100      T varBuffer_;
101      uint8_t varReference_;
102  };
103
104  // ================= Unidirectional Part ===============
105
106  template <class T> SynchronisableVariable<T>::SynchronisableVariable(T& variable, uint8_t syncDirection, NetworkCallbackBase *cb):
107      variable_( variable ), mode_( syncDirection ), callback_( cb )
108  {
109    if ( state_ == 0x0 )
110    {
111      state_ = Core::isMaster() ? 0x1 : 0x2;  // set the appropriate mode here
112    }
113  }
114 
115  template <class T> SynchronisableVariable<T>::~SynchronisableVariable()
116  {
117    if (this->callback_ != 0)
118      delete this->callback_;
119  }
120
121  template <class T> void SynchronisableVariable<T>::getData(uint8_t*& mem, uint8_t mode)
122  {
123    if ( state_ == this->mode_ )
124      getAndIncrease( mem );
125//   mem += SynchronisableVariable<T>::getSize();
126  }
127
128  template <class T> void SynchronisableVariable<T>::putData(uint8_t*& mem, uint8_t mode, bool forceCallback)
129  {
130    assert ( mode == 0x1 || mode == 0x2 );
131    bool callback = false;
132    if ( mode == this->mode_ ) //don't do anything
133      return;
134  // check whether we need to consider a callback
135    if ( this->callback_ != 0 )
136    {
137      if( forceCallback || !checkEquality( mem ) )
138        callback = true;
139    }
140  // write the data
141    setAndIncrease( mem );
142//   mem += SynchronisableVariable<T>::getSize();
143  // now do a callback if neccessary
144    if ( callback )
145      this->callback_->call();
146  }
147
148  template <class T> uint32_t SynchronisableVariable<T>::getSize(uint8_t mode)
149  {
150    if ( mode == this->mode_ )
151      return returnSize();
152    else
153      return 0;
154  }
155
156
157// ================= Bidirectional Part ================
158
159    template <class T> SynchronisableVariableBidirectional<T>::SynchronisableVariableBidirectional(T& variable, uint8_t master, NetworkCallbackBase *cb):
160    SynchronisableVariable<T>( variable, master, cb ), varBuffer_( variable ), varReference_( 0 )
161    {
162    }
163
164    template <class T> SynchronisableVariableBidirectional<T>::~SynchronisableVariableBidirectional()
165    {
166    }
167
168    template <class T> void SynchronisableVariableBidirectional<T>::getData(uint8_t*& mem, uint8_t mode)
169    {
170      if ( this->mode_ == mode )
171      {   // we are master for this variable and have to check whether to change the varReference
172        if( this->varBuffer_ != this->variable_ )
173        {
174          this->varReference_++;
175          memcpy((void*)&this->varBuffer_, &this->variable_, sizeof(this->variable_));
176        }
177      }
178  // write the reference number to the stream
179      *static_cast<uint8_t*>(mem) = varReference_;
180      mem += sizeof(this->varReference_);
181  // now write the content
182      SynchronisableVariable<T>::getAndIncrease( mem );
183//   mem += SynchronisableVariable<T>::getSize();
184    }
185
186    template <class T> void SynchronisableVariableBidirectional<T>::putData(uint8_t*& mem, uint8_t mode, bool forceCallback)
187    {
188      bool callback = false;
189      if ( this->mode_ == mode )
190      {   //        MASTER
191        // check that the client (source of the data) has a recent version of this variable
192        if ( *static_cast<uint8_t*>(mem) != this->varReference_ )
193        { // wrong reference number, so discard the data
194          mem += getSize( mode ); // SynchronisableVariableBidirectional::getSize returns size of variable + reference
195          return;
196        }
197        else{
198          // apply data
199          mem += sizeof(varReference_);
200          if ( SynchronisableVariableBidirectional<T>::checkEquality( mem )==true )
201          {
202            mem += SynchronisableVariable<T>::getSize( mode );
203            return;
204          }
205          else
206          {
207            memcpy((void*)&this->varBuffer_, &this->variable_, sizeof(T));
208            if ( this->callback_ != 0 )
209              callback = true;
210          }
211        }
212      }
213      else
214      {   // we are slave for this variable
215        if (*static_cast<uint8_t*>(mem) == this->varReference_ && !forceCallback)
216        {
217          mem += getSize( mode ); //just skip the variable because nothing changed
218          return;
219        }
220        else
221        {
222          this->varReference_ = *static_cast<uint8_t*>(mem);
223          mem += sizeof(varReference_);
224          if ( SynchronisableVariable<T>::checkEquality( mem ) == false )
225          {
226            // value changed so remark for callback
227            if ( this->callback_ != 0 )
228              callback = true;
229          }
230        }
231      }
232  // now write the data
233      SynchronisableVariable<T>::setAndIncrease(mem);
234  // now do a callback if neccessary
235      if ( callback )
236        this->callback_->call();
237    }
238
239    template <class T> uint32_t SynchronisableVariableBidirectional<T>::getSize(uint8_t mode)
240    {
241      return SynchronisableVariable<T>::returnSize() + sizeof(varReference_);
242    }
243 
244
245}
246
247
248#endif
Note: See TracBrowser for help on using the repository browser.