RPGDXThe center of Indie-RPG gaming
Not logged in. [log in] [register]
 
 
Post new topic Reply to topic  
View previous topic - View next topic  
Author Message
DeveloperX
202192397


Joined: 04 May 2003
Posts: 1626
Location: Decatur, IL, USA

PostPosted: Mon Mar 02, 2009 3:01 am    Post subject: On better engine design practice. [quote]

This is more of a question to the more experienced developers that may be lingering around.

I make heavy use of the STL in my code.

I've been using the singleton pattern in my games; and as a result, I end up with code that functions fine on linux, and does not when it is built on windows.

Apparently there is a major flaw in the logic of the STL, and using singletons in the same code just causes major headaches.

Singletons, as you likely already know, are statically declared instances of a class....and if you have any STL code in them then it simply will segfault under windows.

Code:

#include <map>
class Foo
{
public:
 static Foo* GetInstance(); // returns the singleton pointer
 ~Foo();
 // foobie handler code omitted for brevity
private:
 Foo();
 Foo(const Foo& rhs);
 const Foo& operator=(const Foo& rhs);
 std :: map <const char*, Foo*> foobies_; // this causes headaches!
};
 Foo::GetInstance() { static Foo instance; return &instance; }


...yeah, so my question is this.

What should one use if not a singleton pattern?
_________________
Principal Software Architect
Rambling Indie Games, LLC

See my professional portfolio
Back to top  
Rainer Deyke
Demon Hunter


Joined: 05 Jun 2002
Posts: 672

PostPosted: Mon Mar 02, 2009 4:34 am    Post subject: Re: On better engine design practice. [quote]

I try to avoid singletons in my code. If it doesn't absolutely have to be global, I use a normal (non-singleton) object, even if the object is the only one of its class. In the rare cases where I actually want something to be global, I tend to use a regular global or static variable, without the singleton machinery.

That said, the problem with your code is probably the use of 'const char *' as a key. Use 'std::string'. (Also, if the 'Foo*' is a pointer to a dynamically allocated object, it should probably be 'boost::shared_ptr<Foo>' or another smart pointer class instead.)
Back to top  
DeveloperX
202192397


Joined: 04 May 2003
Posts: 1626
Location: Decatur, IL, USA

PostPosted: Mon Mar 02, 2009 4:50 am    Post subject: Re: On better engine design practice. [quote]

Rainer Deyke wrote:
I try to avoid singletons in my code. If it doesn't absolutely have to be global, I use a normal (non-singleton) object, even if the object is the only one of its class. In the rare cases where I actually want something to be global, I tend to use a regular global or static variable, without the singleton machinery.

That said, the problem with your code is probably the use of 'const char *' as a key. Use 'std::string'. (Also, if the 'Foo*' is a pointer to a dynamically allocated object, it should probably be 'boost::shared_ptr<Foo>' or another smart pointer class instead.)


I don't use const char* as keys....that was just the first thought that popped into my head for an example.

I'm using an std::map of std::string to std::string
_________________
Principal Software Architect
Rambling Indie Games, LLC

See my professional portfolio
Back to top  
Rainer Deyke
Demon Hunter


Joined: 05 Jun 2002
Posts: 672

PostPosted: Mon Mar 02, 2009 5:19 am    Post subject: [quote]

I see. I don't suppose you have a minimal complete example program that demonstrates the problem?

Actually it wouldn't surprise if MinGW was seriously bugged, seeing as it's a Windows port of an old, old version of gcc. Visual C++ 2005 has much better C++ language support.

Simple workaround:
Code:

Foo *the_foo;
int main()
{
  Foo the_foo_instance;
  the_foo = &the_foo_instance;
  // Program here.
  the_foo = 0; // Prevent dangling pointer.
}
Back to top  
Hajo
Demon Hunter


Joined: 30 Sep 2003
Posts: 779
Location: Between chair and keyboard.

PostPosted: Mon Mar 02, 2009 9:07 am    Post subject: Re: On better engine design practice. [quote]

DeveloperX wrote:

What should one use if not a singleton pattern?


A singleton is a relative of the factory pattern, which ensures that only exactly one instance is created.

For creation, you can still use the factory pattern, if you need the control.

Global visibility can be achieved by either a public class variable, or a the proxy pattern, where the proxy manages access to the only one instance of the class (that was a singleton before).

(Singletons should work in C++, but I have no experience with the STL - I can only say that my former project H-World used Singeltons, albeit with selfmade templates).
Back to top  
DeveloperX
202192397


Joined: 04 May 2003
Posts: 1626
Location: Decatur, IL, USA

PostPosted: Mon Mar 02, 2009 9:17 am    Post subject: [quote]

Rainer: THANK YOU! You helped me greatly!

(if it weren't for that post above, I'd still be fighting segfaults trying to build a damned windows release of my jam-entry!)
_________________
Principal Software Architect
Rambling Indie Games, LLC

See my professional portfolio
Back to top  
Tenshi
Everyone's Peachy Lil' Bitch


Joined: 31 May 2002
Posts: 386
Location: Newport News

PostPosted: Mon Mar 02, 2009 4:52 pm    Post subject: [quote]

I know you already solved the problem, but I think this is relatively similar. I am coding from Windows with "cross-platform" in mind and use MingGW to compile. But when I do static pointers I do the following:

Code:

    Map           *MAPENGINE;
int main() // Technically not main, but yeah
{
    MAPENGINE     = new Map( *TILES );
    // Program
    delete MAPENGINE;
    exit( 0 );
}


Also I do use maps similar to you, and I see you say you don't use const char * as the key... which I agree with because those things can be spooky:
Code:

    map[string, Script *> *GLOBALSCRIPTLIST = NULL;
    map[string, Event *>  *GLOBALEVENTLIST   = NULL;

_________________
- Jaeda
Back to top  
Mattias Gustavsson
Mage


Joined: 10 Nov 2007
Posts: 457
Location: Royal Leamington Spa, UK

PostPosted: Tue Mar 03, 2009 2:01 pm    Post subject: [quote]

About using strings for keys...

I'm a bit careful about using strings of any sort (especially std::string) as keys, ever since the time I was hired to optimize a game&engine which turned out to be using hundreds of megabytes for strings (lots of duplicates) and where string comparisons,copying and allocation was right at the top of the profiling results :P

So personally I use something I call a StringId, which basically is just a pointer to a string in a global table (a hashtable for faster lookup). That way, string comparisons is just a pointer compare and duplicating a StringId is just duplicating a pointer. Creating a new StringId instance is slower (involves looking up the string in the hash table, or insert it if it doesn't exist already), but that's ok as I tend to do that mostly during initialization.

Details:
http://www.colossusentertainment.com/pixiedocs/_string_id_8h-source.html
http://www.colossusentertainment.com/pixiedocs/_string_id_8cpp-source.html
_________________
www.mattiasgustavsson.com - My blog
www.rivtind.com - My Fantasy world and isometric RPG engine
www.pixieuniversity.com - Software 2D Game Engine
Back to top  
Hajo
Demon Hunter


Joined: 30 Sep 2003
Posts: 779
Location: Between chair and keyboard.

PostPosted: Tue Mar 03, 2009 3:49 pm    Post subject: [quote]

The people who designed Java knew that, too, and made all string literals internalized, and gave the String class the intern() function that does just this trick ;)

http://java.sun.com/j2se/1.4.2/docs/api/java/lang/String.html#intern()

Might be even more evidence how right Matthias is there.

Edit: The quotes belong to the url, but the forum software does not like them inside the url tags, and neither very much outside :(
Back to top  
DeveloperX
202192397


Joined: 04 May 2003
Posts: 1626
Location: Decatur, IL, USA

PostPosted: Tue Mar 03, 2009 4:02 pm    Post subject: [quote]

Hajo wrote:

Edit: The quotes belong to the url, but the forum software does not like them inside the url tags, and neither very much outside :(


You need to use HTML entity encoding

http://java.sun.com/j2se/1.4.2/docs/api/java/lang/String.html#intern%28%29


About the StringId:

I looked through your code Mattias, and honestly, I don't fully understand the whole hashmap thing that you have going in Pixie. :S

I'm not going to worry too much about memory usage since its cheap these days and its highly unlikely that I will have enough strings in memory to be any issue. I'm also not worried about optimizations at this point. I'm making really basic games here and the systems that are being marketed today are more than 50 times powerful enough to handle anything I'll be throwing at it.

In response to Tenshi:

I see where you are going with that.
Its similar to what I'm doing now, except I don't create my instance on the heap.
_________________
Principal Software Architect
Rambling Indie Games, LLC

See my professional portfolio
Back to top  
Mattias Gustavsson
Mage


Joined: 10 Nov 2007
Posts: 457
Location: Royal Leamington Spa, UK

PostPosted: Tue Mar 03, 2009 4:34 pm    Post subject: [quote]

Well, my StringId class is a bit more complicated than needed, as it also functions as a HashTableKey.

But my point was more conceptual: it's better to use shared strings, for both performance and memory. The way I see it, is that it doesn't hurt to worry about the small things, because you never know when they'll come back and bite you. Like a game requiring 4 times as much memory as a normal PC has, and therefore using the swapfile like crazy :D
_________________
www.mattiasgustavsson.com - My blog
www.rivtind.com - My Fantasy world and isometric RPG engine
www.pixieuniversity.com - Software 2D Game Engine
Back to top  
RedSlash
Mage


Joined: 12 May 2005
Posts: 331

PostPosted: Tue Mar 03, 2009 5:15 pm    Post subject: [quote]

I know that GCC's STL uses copy-on-write optimizations on string, so in theory as long as you're taking advantage of this optimization (using consts properly, etc..), you should be reducing the effects of duplicate copies and comparisons. But I don't really know if it makes the difference, since I usually use const char *, and it seems to be consistant in behaviour.
Back to top  
Tenshi
Everyone's Peachy Lil' Bitch


Joined: 31 May 2002
Posts: 386
Location: Newport News

PostPosted: Wed Mar 04, 2009 12:05 am    Post subject: [quote]

I know in my case theoretically it shouldn't be using much memory at all because there will be few strings in memory in the first place and the majority of the time the strings aren't even actually directly referenced (iterators used). The only time the strings are even checked is if a script I write needs to directly address one, and I went with Strings because it's much easier than trying to keep track of integers when writing a billion scripts anyway.
_________________
- Jaeda
Back to top  
Post new topic Reply to topic Page 1 of 1 All times are GMT
 



Display posts from previous:   
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum