On Jul 30, 2009, at 1:04 AM, Pavel Shevaev wrote:
> * an application thread is not allowed to make any queries to database
> since it's quite expensive(it's a game with very strict time budget
> for each frame)
Not being a game programmer myself, I could be talking out of a
suboptimal orifice, but I can't help but ask: does it make sense to
use a disk-backed, IPC-fed relational database during game play in the
first place? I can see using MySQL to store information about games
and players long-term, but I would imagine this would all be loaded up
on startup, manipulated in memory during play, and the changes not
flushed back to disk until play concludes.
The most aggressive I can imagine being on data concurrency in an
application like that would be periodic saves of in-progress game data.
If you're trying to coordinate multiple CPUs through the database, I'd
switch to some other mechanism, like a separate coordination server
which sends out play update packets over UDP/IP.
> * the application thread is allowed to register async. queries in the
> dedicated database thread
> * the dedicated database thread has a queue of requests, once the
> concrete request is executed and ready the callback is fired and other
> threads can retrieve execution results
Given the requirement to put live data in such a hard-to-reach place
-- disk-backed, and across an IPC link -- this is a sensible design.
> Since, I believe, making RefCountedPointer thread safe can be
> expensive and not quite appealing to the original authors of mysql++
You surmise correctly.
Throwing more threads -- and cores to back them up -- at a database
access problem isn't going to make it faster, so there's no point in
MySQL++ itself offering a baked-in thread safety strategy.
A program using MySQL++ may be able to use multiple cores efficiently
by throwing non-DB work at them, as in your case. In that case, you
already have to come up with your own synchronization strategy, so you
still wouldn't want MySQL++ offering an alternate strategy that could
clash with your design.
The most I could imagine MySQL++ doing is offering a peripheral
prepackaged strategy; say, a message-passing mechanism a la Erlang.
It would be like ConnectionPool, totally optional, with no interaction
with the internals of MySQL++ at all. Something you could write
yourself, with no need to dive into the MySQL++ code. (Hint.)
Embedding such a strategy deeply into MySQL++ would certainly be the
wrong thing.
> I'm currently thinking about sharing my own very simple Row
> implementation across threads which would be created by copying
> mysql++ Row data in the database thread. What do you think about it?
Yes, that's what I would do; copy the row data into a non-MySQL++ data
structure as soon as you can, and pass *that* between the threads, so
the MySQL++ data structure can be released by the thread that created
it.
Personally, I'd use STL containers of SSQLSes[*]. Query::storein()
creates a data structure with no links into the MySQL++ internals.
All MySQL++ data structures are created and destroyed within that
single method call, so you should be able to pass off the container to
the other thread as soon as it's created.
[*] Yes, SSQLS is a MySQL++ feature, but I'm not considering it a MySQL
++ data structure here because they're user-defined, only loosely
coupled to the MySQL++ internals, and the C API has no concept of them
at all. Plus, it's the copy that counts here, not so much what you
copy it *to*.