Generic Datastore

Started by
13 comments, last by Madster 18 years, 3 months ago
Hi, haven't posted in a few months.... grr classes. Anyway, here's my question. Has anyone implemented or has ideas on how to implement a generic datastore object? The idea is to have a data-centric architecture and have several classes attaching arbitrary data to the datastore, who will serve it to anyone who wants it, will cache it if needed and will properly destroy it. Also it should only be possible to wipe the data stored by the same class. More than one Datastore should be allowed, as it would be nice, but that's not really critical. The main issues are: -Classes should be allowed to store any kind of data in the store, ordered or unordered. -Data should be cached if needed and classes should be able to turn caching on and off at will (there's probably no need to toggle it after creating the first object in the store for a given class, though) -Classes might want to see the data stored by other classes. -Any class might request the data to be delivered back to them in a certain order, maybe with special ordering types. for the first and second point I just thought of a template with handles and handle dereference objects, as seen in a Gems book. For the third I'm thinking maybe I could define a separate class with the datatype and #include it in all the interested parties For the fourth one I'm at a loss. Is this doable without calls to sort and find on each data fetch? Would I need a sort-of-iterator-for-handles thing? I don't even know if the two methods I had considered before would allow this. Plus, it's all theory so far. An use case would be something like storing the level geometry and then requesting as an octree from the physics engine and then the same geometry as a bsp by the renderer. All of this without having geometry datatypes in the Datastore class. Anyone done this before? PS: please excuse any weirdness in this post.. it's 6am :s
Working on a fully self-funded project
Advertisement
Eh I forgot...any class should be able to modify what was stored by another class... and there should be a way to *pair* data, such as attaching physics info to a game actor.

Am I aiming too high? O_o
Working on a fully self-funded project
Okay, just thinking out loud here:

collections would be inside of a static STL map after a type specified in a parameter to the template, so that when you want to access a collection of values, you'd ask by type and name.

You would use it this way:
Datastore<mydatatype> *store; // emphasis: you can create it whenever you feel like it, could be in a variable insteadstore = new Datastore<mydatatype>("nameofmystore");store.push( mydata ); // where mydata is of type mydatatypedelete store;...store = new Datastore<mydatatype>("nameofmystore");i = store.begin();for (....)

So, since the actual store is static, it doesn't get deleted unless you explicitly do so. You only need to spawn "interfases" to the store.
the store name is to avoid confusion when there are more than 1 stores with the same type.

The use for this is decoupling the loaders from the renderers from the memory managers :)
Instead of iterators ( store.begin() and such) I am considering using handlers.

any thoughts?

[Edited by - Madster on December 30, 2005 9:09:38 PM]
Working on a fully self-funded project
What are you trying to acomplish?
"Walk not the trodden path, for it has borne it's burden." -John, Flying Monk
I see what you're trying to do. Unfortunately it's damn near impossible to get right.
daerid@gmail.com
I don't really understand what you're trying to do, but whatever it is...use a singleton.

DataStore<T>& store = DataStore<T>::GetRef();
store.push_back(t);

Leave them pointers alone!

-Alex
umm I'm trying to set a scheme up so that arbitrary classes will be able to post data or get data. They don't have to know who posted the data they need, they just assume it's there and use it. This should improve modularity I think, and clean up dependencies (which have bit me several times in the past).

Say you have a simple procedural control system that modifies a vector of ints called "inputs". You decide to make a new object oriented system with bells and whistles... that does the same thing. It's configurable and has all sorts of nice things, but it's basic purpose is still posting input data.
So... it just modifies the same vector of ints called "inputs". No need to re-hook with game logic everywhere, just once for the update call in the main loop.
The same could be done with everything from pathfinding AI to textures and sounds.

So that's the purpose.
Hm it is really a singleton, isn't it?
getting the instance like that would be faster than creating and destroying stuff explicitly? or it just makes it harder to go wrong?
Working on a fully self-funded project
One idea would be to embed a database engine that uses in-memory storage, and then just use SQL statements to query and update the data.
daerid@gmail.com
I really don't recommend you do this. You are going to be writing code imperatively, and storing mutable data in a global data structure. Even if your code is not multithreaded (which in this situation would cause you pain and suffering, and ultimately death), you are still breaking down walls of abstraction and your ability to reason about the behavior of code is severely crippled. Any given computation can potentially modify this global state, and the rest of your code has no idea that this is happening. Thus, the behavior of a function invoked with the same paramters twice can result in two different values. At least with OO (not recommended, but used as an example) we can encapsulate some of this state and minimize these weird effects. You also have the issue of tracking dependencies ... you are going to end up having some data hanging around in this repository when it is no longer needed, which is basically a memory leak. So you are going to implement some reference-tracking system on top of your existing memory management solution. You really have no modularization, you have merely transformed object-to-object dependencies into object-to-mutable-global-state dependencies. It's like the worst of OO combined with the clean, elegant approach of the Windows Registry.
Interesting.

I hadn't considered SQL, and it could be argued that I am reinventing the wheel. I'll look into that, though I'm not too fond of passing strings that need to be parsed for simple accesses.

The Reindeer Effect: thanks for the reply.
For multithreading, mutexes would have to come into play. Acessing the same resource from multiple threads at the same time would mean a simple delay, and a warning would be logged, since one would want to minimize these collisions.
About this:
Quote:Any given computation can potentially modify this global state, and the rest of your code has no idea that this is happening. Thus, the behavior of a function invoked with the same paramters twice can result in two different values.

This is the purpose of the system, that any given computation could potentially modify the global state. Think of it as a game class, where the datastore is a private member. Any method could modify it, yes, that's why not *all* data goes there, only the kind we need to share.
Calling a stateful function (such as most class methods) will often result in two different values. That's not really a problem.

About data hanging around: yes, could be a problem. I plan to provide erase methods, and the method to get data will create a default object if there is none. Keep in mind this is mostly to keep resources and gamestate. The stored objects can also be reference counted, but i believe that's not what you meant. pointers to objects in the datastore are volatile, and not to be kept around.
Thread safety is accomplished, as usual, trough mutexes.

A memory leak is unfreed data that cannot possibly be freed anymore. This is not the case, as the data is still contained in a class that will free it on closure. If misused, it can produce bad memory management at most.

About this:
Quote:You really have no modularization, you have merely transformed object-to-object dependencies into object-to-mutable-global-state dependencies. It's like the worst of OO combined with the clean, elegant approach of the Windows Registry.

I believe moving dependencies from object-to-object to object-to-mutable-global-state does produce modularization, since now I can attach and detach modules at will. It was, in fact, the driving idea. Can you elaborate more on why you feel this isn't the case?
I was aiming also for registry-like functionality, without getting Win32-dependant, and also keeping things in RAM. Can you elaborate on why you feel this is the worst of OO? It is not pure OO. is that it? I feel it's pretty clean, but I'm still deciding on the final form.

Thanks again :)
Working on a fully self-funded project

This topic is closed to new replies.

Advertisement