Changeset 1907 for code/trunk/src/network/Synchronisable.cc
- Timestamp:
- Oct 12, 2008, 7:40:47 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
code/trunk/src/network/Synchronisable.cc
r1856 r1907 51 51 namespace network 52 52 { 53 53 54 55 std::map<unsigned int, Synchronisable *> Synchronisable::objectMap_; 56 std::queue<unsigned int> Synchronisable::deletedObjects_; 54 57 55 58 int Synchronisable::state_=0x1; // detemines wheter we are server (default) or client … … 57 60 /** 58 61 * Constructor: 59 * calls registarAllVariables, that has to be implemented by the inheriting classID62 * Initializes all Variables and sets the right objectID 60 63 */ 61 64 Synchronisable::Synchronisable(){ 62 65 RegisterRootObject(Synchronisable); 63 static int idCounter=0; 64 datasize=0; 66 static uint32_t idCounter=0; 65 67 objectFrequency_=1; 66 objectMode_=0x1; // by default do not send data to server e68 objectMode_=0x1; // by default do not send data to server 67 69 objectID=idCounter++; 68 70 syncList = new std::list<synchronisableVariable *>; 69 //registerAllVariables(); 70 } 71 71 } 72 73 /** 74 * Destructor: 75 * Delete all callback objects and remove objectID from the objectMap_ 76 */ 72 77 Synchronisable::~Synchronisable(){ 73 78 // delete callback function objects 74 if(!orxonox::Identifier::isCreatingHierarchy()) 79 if(!orxonox::Identifier::isCreatingHierarchy()){ 75 80 for(std::list<synchronisableVariable *>::iterator it = syncList->begin(); it!=syncList->end(); it++) 76 81 delete (*it)->callback; 77 } 78 82 deletedObjects_.push(objectID); 83 // COUT(3) << "destruct synchronisable +++" << objectID << " | " << classID << std::endl; 84 // COUT(3) << " bump ---" << objectID << " | " << &objectMap_ << std::endl; 85 // assert(objectMap_[objectID]->objectID==objectID); 86 // objectMap_.erase(objectID); 87 } 88 } 89 90 /** 91 * This function gets called after all neccessary data has been passed to the object 92 * Overload this function and recall the create function of the parent class 93 * @return true/false 94 */ 79 95 bool Synchronisable::create(){ 80 96 this->classID = this->getIdentifier()->getNetworkID(); 81 COUT(4) << "creating synchronisable: setting classid from " << this->getIdentifier()->getName() << " to: " << classID << std::endl; 97 // COUT(4) << "creating synchronisable: setting classid from " << this->getIdentifier()->getName() << " to: " << classID << std::endl; 98 99 // COUT(3) << "construct synchronisable +++" << objectID << " | " << classID << std::endl; 100 // objectMap_[objectID]=this; 101 // assert(objectMap_[objectID]==this); 102 // assert(objectMap_[objectID]->objectID==objectID); 82 103 return true; 83 104 } 84 105 85 106 107 /** 108 * This function sets the internal mode for synchronisation 109 * @param b true if this object is located on a client or on a server 110 */ 86 111 void Synchronisable::setClient(bool b){ 87 112 if(b) // client … … 91 116 } 92 117 93 bool Synchronisable::fabricate(unsigned char*& mem, int mode) 118 /** 119 * This function fabricated a new synchrnisable (and children of it), sets calls updateData and create 120 * After calling this function the mem pointer will be increased by the size of the needed data 121 * @param mem pointer to where the appropriate data is located 122 * @param mode defines the mode, how the data should be loaded 123 * @return pointer to the newly created synchronisable 124 */ 125 Synchronisable *Synchronisable::fabricate(uint8_t*& mem, int mode) 94 126 { 95 unsigned int size, objectID, classID; 96 size = *(unsigned int *)mem; 97 objectID = *(unsigned int*)(mem+sizeof(unsigned int)); 98 classID = *(unsigned int*)(mem+2*sizeof(unsigned int)); 99 100 if(size==3*sizeof(unsigned int)){ //not our turn, dont do anything 101 mem+=3*sizeof(unsigned int); 102 return true; 103 } 104 105 orxonox::Identifier* id = ClassByID(classID); 106 if(!id){ 107 COUT(3) << "We could not identify a new object; classid: " << classID << " uint: " << (unsigned int)classID << " objectID: " << objectID << " size: " << size << std::endl; 108 assert(0); 109 return false; // most probably the gamestate is corrupted 110 } 127 synchronisableHeader *header = (synchronisableHeader *)mem; 128 129 COUT(3) << "fabricating object with id: " << header->objectID << std::endl; 130 131 orxonox::Identifier* id = ClassByID(header->classID); 132 assert(id); 111 133 orxonox::BaseObject *bo = id->fabricate(); 112 134 Synchronisable *no = dynamic_cast<Synchronisable *>(bo); 113 135 assert(no); 114 no->objectID= objectID;115 no->classID= classID;136 no->objectID=header->objectID; 137 no->classID=header->classID; 116 138 COUT(3) << "fabricate objectID: " << no->objectID << " classID: " << no->classID << std::endl; 117 139 // update data and create object/entity... 118 if( !no->updateData(mem, mode) ){ 119 COUT(1) << "We couldn't update the object: " << objectID << std::endl; 140 bool b = no->updateData(mem, mode); 141 assert(b); 142 b = no->create(); 143 assert(b); 144 return no; 145 } 146 147 148 /** 149 * Finds and deletes the Synchronisable with the appropriate objectID 150 * @param objectID objectID of the Synchronisable 151 * @return true/false 152 */ 153 bool Synchronisable::deleteObject(unsigned int objectID){ 154 // assert(getSynchronisable(objectID)); 155 if(!getSynchronisable(objectID)) 120 156 return false; 121 } 122 if( !no->create() ) 123 { 124 COUT(1) << "We couldn't manifest (create() ) the object: " << objectID << std::endl; 157 assert(getSynchronisable(objectID)->objectID==objectID); 158 // delete objectMap_[objectID]; 159 Synchronisable *s = getSynchronisable(objectID); 160 if(s) 161 delete s; 162 else 125 163 return false; 126 }127 164 return true; 128 165 } 129 166 167 /** 168 * This function looks up the objectID in the objectMap_ and returns a pointer to the right Synchronisable 169 * @param objectID objectID of the Synchronisable 170 * @return pointer to the Synchronisable with the objectID 171 */ 172 Synchronisable* Synchronisable::getSynchronisable(unsigned int objectID){ 173 orxonox::ObjectList<Synchronisable>::iterator it; 174 for(it = orxonox::ObjectList<Synchronisable>::begin(); it; ++it){ 175 if( it->getObjectID()==objectID ) 176 return *it; 177 } 178 return NULL; 179 180 // std::map<unsigned int, Synchronisable *>::iterator i = objectMap_.find(objectID); 181 // if(i==objectMap_.end()) 182 // return NULL; 183 // assert(i->second->objectID==objectID); 184 // return (*i).second; 185 } 186 187 130 188 /** 131 189 * This function is used to register a variable to be synchronized … … 133 191 * @param var pointer to the variable 134 192 * @param size size of the datatype the variable consists of 193 * @param t the type of the variable (network::DATA or network::STRING 194 * @param mode same as in getData 195 * @param cb callback object that should get called, if the value of the variable changes 135 196 */ 136 197 void Synchronisable::registerVar(void *var, int size, variableType t, int mode, NetworkCallbackBase *cb){ … … 143 204 temp->callback = cb; 144 205 COUT(5) << "Syncronisable::registering var with size: " << temp->size << " and type: " << temp->type << std::endl; 145 // increase datasize146 datasize+=sizeof(int)+size;147 206 //std::cout << "push temp to syncList (at the bottom) " << datasize << std::endl; 148 207 COUT(5) << "Syncronisable::objectID: " << objectID << " this: " << this << " name: " << this->getIdentifier()->getName() << " networkID: " << this->getIdentifier()->getNetworkID() << std::endl; 149 208 syncList->push_back(temp); 150 } 151 152 /** 153 * This function takes all SynchronisableVariables out of the Synchronisable and saves it into a syncData struct 154 * Difference to the above function: 209 #ifndef NDEBUG 210 std::list<synchronisableVariable *>::iterator it = syncList->begin(); 211 while(it!=syncList->end()){ 212 assert(*it!=var); 213 it++; 214 } 215 #endif 216 } 217 218 /** 219 * This function takes all SynchronisableVariables out of the Synchronisable and saves them together with the size, objectID and classID to the given memory 155 220 * takes a pointer to already allocated memory (must have at least getSize bytes length) 156 221 * structure of the bitstream: 157 * (var1_size,var1,var2_size,var2,...) 158 * varx_size: size = sizeof(int) 159 * varx: size = varx_size 160 * @return data containing all variables and their sizes 161 */ 162 bool Synchronisable::getData(unsigned char*& mem, unsigned int id, int mode){ 222 * |totalsize,objectID,classID,var1,var2,string1_length,string1,var3,...| 223 * length of varx: size saved int syncvarlist 224 * @param mem pointer to allocated memory with enough size 225 * @param id gamestateid of the gamestate to be saved (important for priorities) 226 * @param mode defines the direction in which the data will be send/received 227 * 0x1: server->client 228 * 0x2: client->server (not recommended) 229 * 0x3: bidirectional 230 * @return true: if !isMyTick or if everything was successfully saved 231 */ 232 bool Synchronisable::getData(uint8_t*& mem, unsigned int id, int mode){ 233 //if this tick is we dont synchronise, then abort now 234 if(!isMyTick(id)) 235 return true; 163 236 //std::cout << "inside getData" << std::endl; 164 237 unsigned int tempsize = 0; … … 167 240 if(classID==0) 168 241 COUT(3) << "classid 0 " << this->getIdentifier()->getName() << std::endl; 169 this->classID=this->getIdentifier()->getNetworkID(); // TODO: correct this 242 assert(this->classID==this->getIdentifier()->getNetworkID()); 243 // this->classID=this->getIdentifier()->getNetworkID(); // TODO: correct this 170 244 std::list<synchronisableVariable *>::iterator i; 171 245 unsigned int size; 172 size=getSize 2(id, mode);246 size=getSize(id, mode); 173 247 174 248 // start copy header 175 memcpy(mem, &size, sizeof(unsigned int));176 mem+=sizeof(unsigned int);177 memcpy(mem, &(this->objectID), sizeof(unsigned int));178 mem+=sizeof(unsigned int);179 memcpy(mem, &(this->classID), sizeof(unsigned int));180 mem+=sizeof(unsigned int);181 tempsize+=12;249 synchronisableHeader *header = (synchronisableHeader *)mem; 250 header->size = size; 251 header->objectID = this->objectID; 252 header->classID = this->classID; 253 header->dataAvailable = true; 254 tempsize+=sizeof(synchronisableHeader); 255 mem+=sizeof(synchronisableHeader); 182 256 // end copy header 183 257 184 //if this tick is we dont synchronise, then abort now185 if(!isMyTick(id))186 return true;187 258 188 259 COUT(5) << "Synchronisable getting data from objectID: " << objectID << " classID: " << classID << " length: " << size << std::endl; 189 260 // copy to location 190 261 for(i=syncList->begin(); i!=syncList->end(); ++i){ 191 //(std::memcpy(retVal.data+n, (const void*)(&(i->size)), sizeof(int));192 262 if( ((*i)->mode & mode) == 0 ){ 193 263 COUT(5) << "not getting data: " << std::endl; … … 217 287 218 288 /** 219 * This function takes a syncData struct and takes it to update the variables 220 * @param vars data of the variables 289 * This function takes a bytestream and loads the data into the registered variables 290 * @param mem pointer to the bytestream 291 * @param mode same as in getData 221 292 * @return true/false 222 293 */ 223 bool Synchronisable::updateData(unsigned char*& mem, int mode){ 224 unsigned char *data = mem; 294 bool Synchronisable::updateData(uint8_t*& mem, int mode){ 225 295 if(mode==0x0) 226 296 mode=state_; … … 231 301 } 232 302 303 uint8_t *data=mem; 233 304 // start extract header 234 unsigned int objectID, classID, size; 235 size = *(int *)mem; 236 mem+=sizeof(size); 237 objectID = *(int *)mem; 238 mem+=sizeof(objectID); 239 classID = *(int *)mem; 240 mem+=sizeof(classID); 305 synchronisableHeader *syncHeader = (synchronisableHeader *)mem; 306 assert(syncHeader->objectID==this->objectID); 307 if(syncHeader->dataAvailable==false){ 308 mem+=syncHeader->size; 309 return true; 310 } 311 312 mem+=sizeof(synchronisableHeader); 241 313 // stop extract header 242 assert(this->objectID==objectID); 243 assert(this->classID==classID); 244 if(size==3*sizeof(unsigned int)) //if true, only the header is available 245 return true; 246 //assert(0); 247 248 COUT(5) << "Synchronisable: objectID " << objectID << ", classID " << classID << " size: " << size << " synchronising data" << std::endl; 249 for(i=syncList->begin(); i!=syncList->end() && mem <= data+size; i++){ 314 assert(this->objectID==syncHeader->objectID); 315 // assert(this->classID==syncHeader->classID); //TODO: fix this!!! maybe a problem with the identifier ? 316 317 COUT(5) << "Synchronisable: objectID " << syncHeader->objectID << ", classID " << syncHeader->classID << " size: " << syncHeader->size << " synchronising data" << std::endl; 318 for(i=syncList->begin(); i!=syncList->end() && mem <= data+syncHeader->size; i++){ 250 319 if( ((*i)->mode ^ mode) == 0 ){ 251 320 COUT(5) << "synchronisable: not updating variable " << std::endl; … … 263 332 break; 264 333 case STRING: 265 (*i)->size = *( int *)mem;334 (*i)->size = *(uint32_t *)mem; 266 335 COUT(5) << "string size: " << (*i)->size << std::endl; 267 336 mem+=sizeof(int); … … 283 352 /** 284 353 * This function returns the total amount of bytes needed by getData to save the whole content of the variables 354 * @param id id of the gamestate 355 * @param mode same as getData 285 356 * @return amount of bytes 286 357 */ 287 int Synchronisable::getSize(unsigned int id, int mode){358 uint32_t Synchronisable::getSize(unsigned int id, int mode){ 288 359 if(!isMyTick(id)) 289 360 return 0; 290 int tsize= 0;361 int tsize=sizeof(synchronisableHeader); 291 362 if(mode==0x0) 292 363 mode=state_; … … 311 382 312 383 /** 313 * This function returns the total amount of bytes needed by getData to save the whole content of the variables 314 * @return amount of bytes 315 */ 316 int Synchronisable::getSize2(unsigned int id, int mode){ 317 return sizeof(synchronisableHeader) + getSize( id, mode ); 318 } 319 320 /** 321 * 322 * @param id 323 * @return 384 * This function determines, wheter the object should be saved to the bytestream (according to its syncmode/direction) 385 * @param id gamestate id 386 * @return true/false 324 387 */ 325 388 bool Synchronisable::isMyTick(unsigned int id){ 326 // return true; 389 return ( (objectMode_&state_)!=0 ); 390 } 391 392 bool Synchronisable::doSelection(unsigned int id){ 327 393 return ( id==0 || id%objectFrequency_==objectID%objectFrequency_ ) && ((objectMode_&state_)!=0); 328 394 } 329 395 330 bool Synchronisable::isMyData(unsigned char* mem) 396 /** 397 * This function looks at the header located in the bytestream and checks wheter objectID and classID match with the Synchronisables ones 398 * @param mem pointer to the bytestream 399 */ 400 bool Synchronisable::isMyData(uint8_t* mem) 331 401 { 332 unsigned int objectID, classID, size;333 size = *(int *)mem;334 mem+=sizeof(size);335 objectID = *(int *)mem;336 mem+=sizeof(objectID); 337 classID = *(int *)mem;338 mem+=sizeof(classID);339 340 assert(classID == this->classID);341 return (objectID == this->objectID);342 }343 402 synchronisableHeader *header = (synchronisableHeader *)mem; 403 assert(header->objectID==this->objectID); 404 return header->dataAvailable; 405 } 406 407 /** 408 * This function sets the synchronisation mode of the object 409 * If set to 0x1 variables will only be synchronised to the client 410 * If set to 0x2 variables will only be synchronised to the server 411 * If set to 0x3 variables will be synchronised bidirectionally (only if set so in registerVar) 412 * @param mode same as in registerVar 413 */ 344 414 void Synchronisable::setObjectMode(int mode){ 345 415 assert(mode==0x1 || mode==0x2 || mode==0x3);
Note: See TracChangeset
for help on using the changeset viewer.