> Do several threads share the results, or is each set of results only
> used by the thread that registered the query? If each result is only
> used by one thread it should be possible to avoid the races.
No, several threads don't share results, the result is used in one
thread exclusively.
> If the application thread that issued the query copies all the results
> while holding a mutex lock, and the database thread doesn't hold on to
> the results, then the reference-count updates should be race-free.
I made a bit different workaround for this problem. I have
DbQueryResult struct in my application which looks as follows:
struct DbQueryResult
{
.../*some helper methods*/...
private:
DbQueryPtr query;
mysqlpp::StoreQueryResult native;
};
Database thread in its run method basically does the following:
void DbService::run()
{
...
DbQueryRequestPtr request;
if(query_queue_.pop_if_present(request))
{
try
{
DbQueryPtr q = newQuery(request->str());
DbQueryResultPtr res(new DbQueryResult(q, q->store()));
request->setResult(res);
}
catch(...)
{ /*error handling*/ }
}
...
}
newQuery(...) method returns DbQueryPtr which is a shared_ptr for
DbQuery wrapper around mysqlpp::Query.
DbQuery wrapper is mainly used to hold the mysqlpp::Connection grabbed
from the pool and wrapped in a shared_ptr as well.
struct DbQuery
{
..
/*some helper methods*/
..
private:
mysqlpp::Query native_;
MySqlConnectionPtr conn_;
};
This is done intentionally - every query has its own connection
object. It's also worth mentioning that mysql::Connection wrapped into
shared_ptr with special deleter which doesn't delete the pointer but
releases connection in the pool:
struct MySqlConnectionPoolDeleter
{
MySqlConnectionPoolDeleter(DbService& svc)
: svc_(svc){}
void operator()(mysqlpp::Connection* conn)
{
svc_.pool().release(conn);
}
private:
DbService& svc_;
};
In the main thread the usage looks as follows:
DbQueryPtr query = DbService::getInstance().query();
*query << "SELECT ...";
DbService::getInstance().asyncQuery(query, someAsyncQueryHandler);
Maybe it's a bit awkward and complicated but at least it works for me.
--
Best regards, Pavel