questions about singletons

Started by
39 comments, last by Khatharr 10 years, 8 months ago

If there were ever two instances of this class then all of my resources would potentially be invalidated because their handles could suddenly be used to load a new resource. My whole motivation in creating the singleton was to enforce one-and-only-one instance.

As pointed out earlier in this thread (and easy enough to forget that I've done so in the past), it's not a singleton unless it provides global access.

If you're forced to use a bit of static data to enforce the "singularity" of an object, that's unfortunate, and may require you to address initialization order and threading issues.  However, that doesn't require you to also make that object globally accessible.  You can still create and use it as a normal object.

Advertisement

You always seemed like a really knowledgeable guy using tried old methods which work well for you,

semi-well. always room for improvement - sharpening the saw.


but your latest threads feel like you now want to follow the OOP+patterns crowd cause everyone uses them?

just want to make sure i'm not missing out on anything. also, i can't resist a challenge. from lurking, it appears that the C++/OO way of doing games can be less than effortless. this piqued my natural engineering curiosity. also, i suspect that what i do can be re-organized into an oo/c++ api (actually that's pretty obvious, at the end of the day, its all just code and data).

my biggest difficulty seems in determining the "correct" way to deal with "global" databases (meshes for example). straight port from C to C++ yields single instance objects with public data structures which are accessed globally. the "global access" part makes for "poorly designed" coupling between modules. but i have yet to come up with an alternative which is not less efficient. i feel if i could solve that one bit, it would give me the method i need to implement or wrap my game part libraries in a C++ api. i used to sell my libraries. but this time, i'm considering releasing them for free. i'd like to provide APIs for c, c++, java, c#, etc. by making the APIs one folks can use easily, i'll get more folks using the code, which means more feedback, and better design, which means better code. so there is a method to my madness - perhaps? <g>.

all of this is also a bit of r&d into just how generic an "engine" can be. and whether an engine or library approach is better. there are actually 3 related r&d issues driving all this: engine and library design, c++ extensions, and the latest: high level dedicated game programming languages. high level as in keywords like BeginScene and DrawIndexedPrimitive as machine opcode instructions. i ran my first test last night. 40 bytes of virtual machine code that starts directx, loads all graphics and audio content, then goes into a loop where it clears the screen, displays the name of the programming language, displays the framerate, and checks for ESC being pressed. when ESC is pressed, it shuts down directx and quits. 62.5 fps. rock solid. and that's interpreted p-code, not true machine code. so i don't have to go though the hassle of writing a full blown native code compiler.

the other can of worms is the "entity class hierarchy from hell" which apparently is another common design issue in C++. at this point, i'm still mostly in observation mode as to how others deal with these issues in C++, but so far i have yet to see some common solution rise to the surface. Since I'm still largely in data acquisition mode, so far the only things i've identified that will require more consideration are the questions of global access and entity hierarchy woes.

so, no i'm not "jumping on the bandwagon" <g>. but "a good warrior makes use of the weapons at hand". and C++ has been readily at hand for some time now. So i thought it might be a good idea to revisit the question of using c++ syntax. plus all the postings i see and all the difficulties folks seem it have, makes me think there must be a better way, some answer to this engineering challenge. maybe i'm just bored 'cause i have to do a lot of 3d modeling for CAVEMAN right now (tedious adjusting of meshes and vertices), and want something i can sink my brain into! <g>.

in fact, it occurred to me that asking that question (why do you use c++?) might get me the answers i'm looking for, as it might help highlight why (or why not) to use C++ syntax. it might be interesting to see how many use it due to outside requirements or inertia, as opposed to those who use it as a conscious decision. such a question, perhaps followed up by "what about C++ do you like?" might point to syntax advantages i can make use of.

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php


There's some links about peoples views of design patters I unintentionally found some time ago:
http://perl.plover.com/yak/design/
http://realtimecollisiondetection.net/blog/?p=81

[after following the links - and their interesting links - 4-5 hours of reading later ]

excellent links! I found the one about the "Bulb programmer" most insightful and timely, given the recent successful first test of my high level game programming language run time module yesterday. now has me thinking about a game's requirement for true macros in a programming language i have yet to design or even name! <g>.

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

Other threads related to this thread:

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php


Norman Barrows, on 29 Aug 2013 - 07:30 AM, said:
i mean am i supposed to use a setter and getter for everything?
In short, yes; your public accessable interface should be well defined; reaching into an object for various internals is violating proper usage of a class.
But this is less of an issue than using globals.

so instead of something like:

LPD3DXTEXTURE tex[maxtextures];

Zsettexture(tex[texID]);

i should have something like:

LPD3DXTEXTURE p;

texDB.gettex(&p);

Zsettexture(p);

or better yet:

texDB.settexture(texID)

although internally, set texture is a d3d device pointer method, perhaps leading to (the possibly over-engineered - over abstracted):

D3Ddevice.settex(texID) and the "database" of textures is part of the D3Ddevice object, 'cause that's the object that actually uses the data.

over-engineered, or did i just have an insight? <g>

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php


Look into dependecy injection.

seems to be about being able to select different implementation modules at runtime, instead of hard coding it.

i'm looking for an efficient way to encapsulate my "evil" globals (public static global data structures). <g>.

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

LPD3DXTEXTURE tex[maxtextures];

Zsettexture(tex[texID]);

i should have something like:

LPD3DXTEXTURE p;

texDB.gettex(&p);

Zsettexture(p);

or better yet:

texDB.settexture(texID)

although internally, set texture is a d3d device pointer method, perhaps leading to (the possibly over-engineered - over abstracted):

D3Ddevice.settex(texID) and the "database" of textures is part of the D3Ddevice object, 'cause that's the object that actually uses the data.

over-engineered, or did i just have an insight? <g>

Certainly if you desire to have an object that holds textures; it might be:

texDB->addTexture(id, pTexture);

then later

tex=texDB->getTexture(id);

these two methods form an interface, with that interface I as another developer can replace your implementation with another that functions different internally; without upsetting any other code.

As for:

D3Ddevice.settex(texID)

i would assume that is a static method off of a class;

instead you should have an instance of a D3DDevice

D3DDevice* device=new D3DDevice(/*params require for instantiation*/);

device->setTexture(tex);

Raymond Jacobs, Owner - Ethereal Darkness Interactive
www.EDIGames.com - EDIGamesCompany - @EDIGames

Unless I missed something, what's the harm in having a singleton privately manage itself with read-only properties that can be used by the classes that need it?

it seems to me that encapsulating a global data structure in a class with a get and set API gets you access control, allowing you to change the underling implementation without breaking anything, at the cost of the overhead of going though the get and set API, instead of referencing the global directly.

it also appears that much of this stuff about C++/OO syntax, design patterns, etc. is about "too many chefs spoiling the soup" - something which may not be germane to a "Studio of One".

in my recent re-review of c++ syntax constructs, templates, and such, i kept noticing recurring themes of "reuse" (especially over multiple projects), "multiple developers", and "hand holding" (for lack of a better term). IE mostly organizational and ease of use extensions to the basic capabilities of C. but not much else. and sometimes these extensions come with a performance cost. of course these days, PCs are fast enough that slight performance overheads in things other than tight loops are acceptable. witness the framerate i'm getting with interpreted p-code on a rtm.

i have to admit its been a long time since i thought the OO way. But its starting to come back to me now. D3Ddevice.settex(texID) is an example of that.

BTW, taken to its logical conclusion would D3Ddevice be considered a "god object"? the mesh, texture, model, animation, animation players, and materials "databases" in the game (and probably others too) would all be part of the D3Ddevice.

or is a god object just a "one class fits all" design?

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php


As for:

D3Ddevice.settex(texID)

i would assume that is a static method off of a class;

instead you should have an instance of a D3DDevice

D3DDevice* device=new D3DDevice(/*params require for instantiation*/);

device->setTexture(tex);

actually it would probably be a class that included a LPDIRECT3DDEVICE instance as a private data variable.

The D3Ddevice class would be a wrapper for an instance of a d3d device COM object, that also included the texture database (and all the other graphic primitives data).

since the LPDIRECT3DDEVICE is actually just a component of the D3Ddevice object, lets rename the D3Ddevice to "GU" (for Graphics Unit) for clarity.

so you'd have calls like:

GU.loadallassets()

GU.beginscene()

GU.clear_renderables()

GU.add_renderable(drawinfo)

GU.render_rendrables()

GU.showscene()

inside the GU module, you'd have calls like:
d3d_device_ptr->settexture(tex.get(texID));
where the tex object (textures database) is a member of the GU object, along with the mesh, material, ani, model, and aniplayer objects (databases), and probably some others too .

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

This topic is closed to new replies.

Advertisement