Page 1 of 1

Pluggable Factories & unecessary statics

Posted: 01 May 2006 22:38
by iLess
Hey Hellfire.

I looked a little at your code. I like the PacketFactory approach but i think it could be written more flexible. As it is now, for each new Packet you define, the factory code has to be changed too. I will change it a little so this is not necessary anymore. Look at this: http://www.gamedev.net/reference/articl ... cle841.asp. Its a really elegant solution.

I noticed that you put in every file:

Code: Select all

  static std::string Author;
  static std::string Name;
  static std::string Abbreviation;
  static long Count;
Whats the use of those variables? I don't see why we should have those everywhere. They will be compiled and put into the final executable where they serve no purpose. I don't think that someone will suddenly feel the urge to upen the binary file in a Hexeditor and to look around for the Authors name ;-)

Posted: 02 May 2006 01:44
by Grunt
I recall uzurpator insisting on these ages ago, though I have no idea why. If I can dig out the rationale in the threads I will do so.

EDIT: it seems this was brought up in the coding standard thread. I brought up this point; it was never addressed. uzurpator appears to have added these into the coding standard and I guess refused to remove them, so I'm not sure why we have them or why they're still there.

Posted: 02 May 2006 20:38
by Hellfire
Yeah, I started coding with Uzurpator's coding standard in mind. I don't see why we should keep those static variables. On the other hand, they don't cause much extra load on the CPU or memory, so I kept it the way it was.

The "Count" variable can be very useful, though. Imagine an assertion before each "Count--":

Code: Select all

assert(1 <= Count);
Count--;
This should bork whenever a double free() is done.
iLess wrote:I like the PacketFactory approach but i think it could be written more flexible. As it is now, for each new Packet you define, the factory code has to be changed too. I will change it a little so this is not necessary anymore. Look at this: http://www.gamedev.net/reference/articl ... cle841.asp. Its a really elegant solution.)
I just skimmed through that article. I haven't seen the details, but the idea is clear to me: the factories are registered at program startup (thanks to the static variable) and each factory can specify which packet type they can handle. It could be faster than the switch() approach too. (Although I think switch statements are logarithmic in current compilers). This approach is great! It'll take a little time to convert the current implementation, but It'll make future extensions a lot easier.

Posted: 02 May 2006 23:24
by iLess
Yes the Count can be of use, but not for classes like Server or Client. More for the ones we instantiate very often. BTW. you didn't answer to the Factory part of my msg. I sat down today and coded a little bit around.
Here is what i got: http://tempire.selfip.org/index.php/All ... le_Factory. Haven't found out yet how i can upload files to the wiki, so i put just the essential stuff there. If you want to use it you need the Boost.Preprocessor Library.

Posted: 03 May 2006 18:42
by Hellfire
iLess wrote:Yes the Count can be of use, but not for classes like Server or Client. More for the ones we instantiate very often. BTW. you didn't answer to the Factory part of my msg.
I thought I did:
Hellfire wrote:I just skimmed through that article. I haven't seen the details, but the idea is clear to me: the factories are registered at program startup (thanks to the static variable) and each factory can specify which packet type they can handle. It could be faster than the switch() approach too. (Although I think switch statements are logarithmic in current compilers). This approach is great! It'll take a little time to convert the current implementation, but It'll make future extensions a lot easier.
iLess wrote:I sat down today and coded a little bit around.
Here is what i got: http://tempire.selfip.org/index.php/All ... le_Factory. Haven't found out yet how i can upload files to the wiki, so i put just the essential stuff there. If you want to use it you need the Boost.Preprocessor Library.
What do these boost things do?

Posted: 03 May 2006 21:15
by iLess
What boost things you mean? The Preprocessor Macros?
They generate 8 versions of the same function starting with 1 argument (only the key for the map) and going up to 8 additional template and method parameters. If you run the compiler just in preprocessing mode you will basically get this (but each method will be on a single line, so i had to format it a little):

Code: Select all

T* GenerateObject(K key ) const 
{ 
  T* retval = 0; typename std::map<K,G>::const_iterator it = m_generators.find(key); 
  if (it != m_generators.end()) 
    retval = it->second(); 
  return retval; 
}


template < class A1 > 
  T* GenerateObject(K key , A1 arg1) const 
  { 
    T* retval = 0; 
    typename std::map<K,G>::const_iterator it = m_generators.find(key); 
    if (it != m_generators.end()) 
      retval = it->second( arg1); 
    return retval; 
  }


template < class A1 , class A2 > 
  T* GenerateObject(K key , A1 arg1 , A2 arg2) const 
  { 
    T* retval = 0; 
    typename std::map<K,G>::const_iterator it = m_generators.find(key); 
    if (it != m_generators.end()) 
      retval = it->second( arg1 , arg2); 
    return retval; 
  }


template < class A1 , class A2 , class A3 > 
  T* GenerateObject(K key , A1 arg1 , A2 arg2 , A3 arg3) const 
  { 
    T* retval = 0; 
    typename std::map<K,G>::const_iterator it = m_generators.find(key); 
    if (it != m_generators.end()) 
      retval = it->second( arg1 , arg2 , arg3); 
    return retval; 
  }


template < class A1 , class A2 , class A3 , class A4 > 
  T* GenerateObject(K key , A1 arg1 , A2 arg2 , A3 arg3 , A4 arg4) const  
  { 
    T* retval = 0; 
    typename std::map<K,G>::const_iterator it = m_generators.find(key); 
    if (it != m_generators.end()) 
      retval = it->second( arg1 , arg2 , arg3 , arg4); 
    return retval; }

//and so on until GENERATE_MAX_PARAMS is reached

If you really want to understand how it works look at the Boost Preprocessor library. This stuff is called Preprocessor Metaprogramming because it generates source-code using the Preprocessor. So these Macros are "Meta-Functions". It is also possible to do metaprogramming with templates. This is really powerfull stuff, but at first sight maybe a little hard to understand. I had to read a book about it to fully understand how it works. But it is REALLY worth it! (here's the page of the book: http://boost-consulting.com/mplbook/. Basically you can use the Compilers Prerprocessor or its Template-Facility to do calculations on Types. You can run the Compiler like a Touring-Machine (although a not very fast one). I actually wrote a little program once that made the compiler simulate a one-dimensional mechanical system, just using templates! As the compiler was finished with compiling, the simulation results could be read out from an array inside the executable ;-). So the only thing the App did at runtime, was just read out the result-Array. This worked on gcc3.5 but unfortunately they changed something in gcc4 and now it does not work anymore :-(. Maybe it is just because my gcc4 was altered by Apple. It would be cool if someone could check, whether it works with his compiler, or tell me the errors he gets. The source can be obtained here: http://tempire.selfip.org/index.php/COTOS

Posted: 03 May 2006 23:25
by iLess
Hellfire wrote:This approach is great! It'll take a little time to convert the current implementation, but It'll make future extensions a lot easier.
I did that already. But as I couldn't find out how to upload my source to the Wiki, i didn't post all of it there. It always says:

".zip" is not a recommended image file format.

Does anyone know where i can make it a recommended format?