-
July 21st, 2016, 08:28 AM
#1
Gobally available Service with scoped Lifetime
Hey
I am currently working on a game and ran into a very usual problem in game development.
What I am trying to do, is providing global and scoped access to Services/Subsystems (e.g. Graphics renderer) that are not static.
Basicly 'Provider' is a template for actual providers (e.g. GraphicsProvider), whose hold pointers to services, that then can be accesst through 'Get<T>()' from all over the code.
Get will return nullptr if there is no provider holding the service, or if there is no service registered to the provider.
Please have a look into main.cpp to get an idea of how it is used.
full code:
main.cpp
provider.h
traits.h
Do you have advide or a better solution?
What do you think about this approach?
Thanks lots
-
July 21st, 2016, 10:20 AM
#2
Re: Gobally available Service with scoped Lifetime
Code:
static Provider *s_pInstance;
Looks static to me.
Don't you need the graphics renderer during the whole lifetime of the application? Then with your solution the "scoped" object is practically global anyway.
Do you really need to access these services/subsystems from all over your codebase?
You should strive to design your program in a way that minimizes dependencies.
Last edited by TubularX; July 21st, 2016 at 10:25 AM.
-
July 21st, 2016, 11:30 AM
#3
Re: Gobally available Service with scoped Lifetime
 Originally Posted by TubularX
Don't you need the graphics renderer during the whole lifetime of the application? Then with your solution the "scoped" object is practically global anyway.
This is true for Graphics, but might not be for other services.
 Originally Posted by TubularX
Do you really need to access these services/subsystems from all over your codebase?
You should strive to design your program in a way that minimizes dependencies.
I would like to seperate 'engine' and 'game', even though the engine is built to fit the game (not like unity, being a general approach). To minimize dependencies, only one of them should know the other.
If the engine knows the game, i can adjust it and improve the overall communication between game and engine. In this case only the engine needs to know about Graphics for example, because the engine will take care of routines (rendering, update, etc.) and requires data from game.
This way the 'game' is a very simple abstraction of what happens in terms of game logic and in the same time a database for the engine that presents contents to the user.
How do you think about this?
What do you think about the Provider thingy in general?
-
July 21st, 2016, 03:33 PM
#4
Re: Gobally available Service with scoped Lifetime
Well, I'm not convinced with the idea of "global and scoped access". Isn't it just global state in disguise? What's the benefits compared to using a global pointer with a scope guard? The performance of Provider is worse, because it requires extra overhead "if(provider::s_pInstance)" every time you're getting.
I don't know what your services are doing, but maybe you can use a messaging system / event queue instead. Or just pass references around (store references to the services in the classes that needs to access them).
BTW, there's a bug in your code:
Code:
if(s_pInstance == this); s_pInstance = nullptr;
-
July 24th, 2016, 11:21 AM
#5
Re: Gobally available Service with scoped Lifetime
 Originally Posted by TubularX
Well, I'm not convinced with the idea of "global and scoped access". Isn't it just global state in disguise? What's the benefits compared to using a global pointer with a scope guard? The performance of Provider is worse, because it requires extra overhead "if(provider::s_pInstance)" every time you're getting.
The primarily benefit is the abstraction and that it's more difficult to use it incorrectly. Since this is an open source project, i think using templates in that fashion might not be good, but it delivers a way to access globals in a kinda familiar way.
What properties of a scope guard would help here? I could design provider in a way, that its owning the services. What do you think about that?
 Originally Posted by TubularX
I don't know what your services are doing, but maybe you can use a messaging system / event queue instead. Or just pass references around (store references to the services in the classes that needs to access them).
Passing references deeply into the class tree causes a small object creation and memory overhead and makes maintaining a harder from my experience.
Also, if the service uses interface pattern, i can replace it on runtime.
 Originally Posted by TubularX
BTW, there's a bug in your code:
Code:
if(s_pInstance == this); s_pInstance = nullptr;
Thanks^^
I still think its a bit overkill but i kinda like the pattern.
-
July 24th, 2016, 06:05 PM
#6
Re: Gobally available Service with scoped Lifetime
it's more difficult to use it incorrectly
More difficult than what?
What properties of a scope guard would help here?
For example, here's a solution using a scope guard instead of your Provider:
Code:
Graphics* graphics = nullptr;
template <typename T>
class GlobalPointerGuard
{
T*& m_p;
public:
GlobalPointerGuard( T*& p ) : m_p(p) {}
~GlobalPointerGuard() { m_p = nullptr; }
};
int main()
{
{
Graphics scoped_graphics;
GlobalPointerGuard<Graphics> t( graphics = &scoped_graphics );
function();
}
function();
return 0;
}
void function()
{
// do something with Graphics
std::cout << graphics << std::endl;
}
This way you'll need to declare one global pointer for each service, but no extra if-statement.
Global state can become a maintenance nightmare, especially as the project grows and if you're going to run code concurrently.
Last edited by TubularX; July 24th, 2016 at 06:07 PM.
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
On-Demand Webinars (sponsored)
|