Skip to main content
gamedev.net
🔒 Locked

A Design Pattern Issue

Started by Redleaf Oct 10, 2001 at 9:48 AM 8 replies 1.1k views
Original Post
Redleaf
Redleaf
I''m currently working on an implimentation of the "Pluggable Factory Pattern" that I found in an older article entitled, "Why Pluggable Factories Rock My Multiplayer World" or something akin to that. I''d like to be able to have a template "maker" class which inherits from the abstract "maker" the author creates. However the pattern relies on each derived maker having a static instance of itself so that it will be mapped correctly upon program startup. As far as I know, in order to do this, the compiler will have to generate the required classes from the template. This could easily be done by declaring a static instance, reference, or pointer to a particular derived maker someplace else, but can be misused, and also defeats the purpose of each maker class having a static instance of itself. I was thinking that perhaps using a typedef would work, but will all compilers be guaranteed to generate specific derived maker code if only a typedef references a particular type of the templated maker, or will some compilers ignore the typedef if it is never seemingly used elsewhere in the code? Any solutions to this problem, or suggestions on better ways to accomplish my goals would be greatly appreciated. "Don''t be afraid to dream, for out of such fragile things come miracles."
Shannon Barber
Shannon Barber
quote:

will some compilers ignore the typedef if it is never seemingly used elsewhere in the code?


I'm going to go out on a limb here, and say that All compilers will ignore it (for your purpose). Some compilers might drop stuff in a obj file (or something else) but it won't ever make it to the lib/exe/dll.

You have to create an instance to get a version of the template in the compiled code.

A template might let you avoid some copy&paste'ing.
You'll still need to create a seperate class for each message.

Magmai Kai Holmlor
- Not For Rent

I think this is the best you can do with a template:
  
template<typename TClay>
class CAutoRegisterMaker: public CTheMaker
{
public:
protected:
private:
static const TClay ms_RegisterThis;
};

class CMsgChatMaker : public CAutoRegisterMaker<CMsgChatMaker>
{
virtual CMsgHeader* MakeMessage(BYTE* pByte, DWORD dwBytes) const;
};


Edited by - Magmai Kai Holmlor on October 10, 2001 9:44:36 PM
The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
Redleaf
Redleaf
Thanks for the reply.

I actually think I have a solution that works as I''d like, and so I''ll share for anyone else''s benefit.

In a source file, simply initialize the static self-instance of any particular class that you''d like from the template.

After toying around with the static member initialization thing, I came to see that at least under MSVC 6.0, a static member doesn''t seem to ever be created unless it is explicitly initialized in a source file. Is this actually the standard?

I suppose that other than particular access restrictions a static member would have, this simply behaves like a syntactically different C-style extern...

In the past I had always figured that a static member only needed explicit initialization (even if to simply state its existence without an assignment) if there was an initial value you''d want to pass to its constructor. Is it me, or what?


"Don''t be afraid to dream, for out of such fragile things come miracles."
Shannon Barber
Shannon Barber
quote:

a static member doesn''t seem to ever be created unless it is explicitly initialized in a source file. Is this actually the standard?


May as well be, you shouldn''t instance any objects in a header - always in the .cpp, only class declarations go in headers.

quote:

I suppose that other than particular access restrictions a static member would have, this simply behaves like a syntactically different C-style extern...


A static never has global scope, otherwise they act similar.

quote:

"...explicit initialization..."


What other kind is there? This ain''t Java! (you can define statics inline in Java - you can in C++ too according to the latest spec but no compilers support it, or so I''ve been told)

The compiler/linker may make a special case for static''s that are not part of a class, in which it allows you to declare and define them in the header file (they may have to be const as well, I forget). Static''s that are declared in a class need to be defined in the cpp (if nothing else it allocates storage for them).


Magmai Kai Holmlor
- Not For Rent
The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
Redleaf
Redleaf
quote:

"...explicit initialization..."



The other kind would be having the compiler do it implicitly, particularly when the static object''s constructor takes no parameters.

quote:

This ain''t Java!



I was not trying to imply that I am used to whatever syntax Java employs in dealing with static members.


"Don''t be afraid to dream, for out of such fragile things come miracles."
Shannon Barber
Shannon Barber
quote:

The other kind would be having the compiler do it implicitly, particularly when the static object''s constructor takes no parameters.


Ah, I see. I consider that explicit since you still have to tell the constructor what to do, but I can see how it''s considered implicit.

quote:

I was not trying to imply that I am used to whatever syntax Java employs in dealing with static members.


I was just kiddin'' :O


I started implementing a pluggable factory, but I didn''t like it.
Too much work is done in the base maker class, and it''s too hard change its implementation. So I decided to go the other way, and have each message maker call a Register method on an CMsgParser class (that''s part of the network client). It''s a little more work to add a message now, but not much. To add a message the old way you had to write a new maker class and instance it. My way you have to write a maker class, instance it, and call a method. You still have the problem of what to do once you make the message. It''s desirable to have MsgMaker classes available that implement common messages (like chat or position) and to allow completely new messages to be added, and both need to communicate with the game logic (not just the network client/server/peer). So you almost need to add another (virtual) method to the maker class, call it Handle? that gets called once a message has been received and assembled.

I put together a design, but it kinda got outta hand in its complexity. COM has a set of interfaces for persisting data to streams, but not quite the kind you need for networking (ISequentialStream is the closest). I decided to use IMalloc to allocate my messages; I can use the system provided allocator now, and create a circular buffer implementation later (if/when needed). I then had all these danlging BYTE*''s, which bothered me, so I made a IBlob interface & implementation which functions like a IMediaSample. There''s a pool of Blobs that allocate memory using IMalloc (to be replacement with a circular buffer later). Since the blob''s get passed all over the code, I wanted them reference counted so I knew when to return them to the pool. I also wanted a couple of simple methods to read and write to the blob (works like a file, automatically advancing the read/write pointer).
The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
Redleaf
Redleaf
Thanks for all the info. I''ll take it into account.

"Don''t be afraid to dream, for out of such fragile things come miracles."
DigitalDelusion
DigitalDelusion
The standard doesn''t say much about static variables.
Then don''t need to be initialized at all (just as any other variable) just because they are declared, and in any case you can''t predict in what order they will be initilized.

This is if you have a global factory don''t use it to init another global unless you want an headace, to save you the trip to the drugstore the solution is to "hide" them behind a singleton similar construct (i.e. a function returning a refrence to the static var), because then they will always be initilazed on use.
HardDrop - hard link shell extension."Tread softly because you tread on my dreams" - Yeats
DigitalDelusion
DigitalDelusion
The standard doesn''t say much about static variables.
Then don''t need to be initialized at all (just as any other variable) just because they are declared, and in any case you can''t predict in what order they will be initilized.

This is if you have a global factory don''t use it to init another global unless you want an headace, to save you the trip to the drugstore the solution is to "hide" them behind a singleton similar construct (i.e. a function returning a refrence to the static var), because then they will always be initilazed on use.
HardDrop - hard link shell extension."Tread softly because you tread on my dreams" - Yeats

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.