Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 2245 was 2245, checked in by scheusso, 15 years ago

most coding is done, still testing now
types should get transfered in platform independent formats now

  • Property svn:eol-style set to native
File size: 8.1 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          COUT(0) << "not updateing variable because of wrong reference number" << endl;
196          return;
197        }
198        else{
199          // apply data
200          mem += sizeof(varReference_);
201          if ( SynchronisableVariableBidirectional<T>::checkEquality( mem )==true )
202          {
203            mem += SynchronisableVariable<T>::getSize( mode );
204            return;
205          }
206          else
207          {
208            COUT(0) << "variable changed so copy over the buffer and do callback" << endl;
209            memcpy((void*)&this->varBuffer_, &this->variable_, sizeof(T));
210            if ( this->callback_ != 0 )
211              callback = true;
212          }
213        }
214      }
215      else
216      {   // we are slave for this variable
217        if (*static_cast<uint8_t*>(mem) == this->varReference_ && !forceCallback)
218        {
219          mem += getSize( mode ); //just skip the variable because nothing changed
220          return;
221        }
222        else
223        {
224          this->varReference_ = *static_cast<uint8_t*>(mem);
225          mem += sizeof(varReference_);
226          if ( SynchronisableVariable<T>::checkEquality( mem ) == false )
227          {
228            // value changed so remark for callback
229            if ( this->callback_ != 0 )
230              callback = true;
231          }
232        }
233      }
234  // now write the data
235      SynchronisableVariable<T>::setAndIncrease(mem);
236  // now do a callback if neccessary
237      if ( callback )
238        this->callback_->call();
239    }
240
241    template <class T> uint32_t SynchronisableVariableBidirectional<T>::getSize(uint8_t mode)
242    {
243      return SynchronisableVariable<T>::returnSize() + sizeof(varReference_);
244    }
245 
246
247}
248
249
250#endif
Note: See TracBrowser for help on using the repository browser.