List:MySQL++« Previous MessageNext Message »
From:Pavel Shevaev Date:July 30 2009 12:57pm
Subject:Re: Proper usage of mysql++ in a multi-threading environment
View as plain text  
> 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
Thread
Proper usage of mysql++ in a multi-threading environmentPavel Shevaev30 Jul
  • Re: Proper usage of mysql++ in a multi-threading environmentJonathan Wakely30 Jul
    • Re: Proper usage of mysql++ in a multi-threading environmentPavel Shevaev30 Jul
  • Re: Proper usage of mysql++ in a multi-threading environmentWarren Young30 Jul