Webmaster  |  Imprint 
C++ Server Pages
Main  |  License  |  Documentation  |  Download 

pool.cpp

Example: pool.cpp application


#include <iostream>
#include <cxxtools/thread.h>
#include <cxxtools/pool.h>
#include <cxxtools/log.h>
#include <cxxtools/loginit.h>
#include <unistd.h>

log_define("pooldemo")

// define a dummy dbconnection-object
class Connection
{
    std::string db;
  public:
    Connection()
    {
      log_info("create connection");
    }

    Connection(const std::string& db_)
      : db(db_)
    {
      log_info("create connection to \"" << db << '"');
    }

    ~Connection()
    {
      log_info("destroy connection");
    }

    void doSomething()
    {
      sleep(1);
    }
};

// define a custom connector for passing the connection string
class Connector
{
    std::string db;

  public:
    Connector(const std::string& db_)
      : db(db_)
      { }
    Connection* operator() ()
      { return new Connection(db); }
};

// define a connection-pool-type
typedef cxxtools::Pool<Connection, Connector> ConnectionPoolType;

// define a thread, which fetches a connection from a pool
// and does something
class MyThread
{
    cxxtools::AttachedThread thread;
    ConnectionPoolType& pool;
    unsigned threadNum;
    unsigned sec;

  public:
    explicit MyThread (ConnectionPoolType& pool_, unsigned threadNum_, unsigned sec_ = 1)
      : thread( cxxtools::callable(*this, &MyThread::run) ),
        pool(pool_),
        threadNum(threadNum_),
        sec(sec_)
      { }

      void create()
      { thread.start(); }

      void join()
      { thread.join(); }

    void run()
    {
      log_info("start thread " << threadNum);

      sleep(sec);

      // We fetch a object from the pool, and call a method pool.get() does
      // not return a connection, but a proxy object, so we have to take
      // care not to assign the object to a Connection, but use that proxy
      // directy.
      //
      // This would be wrong:
      //   Connection conn = *pool.get(); // convert the proxy-object
      //   conn.doSomething(threadNum);  // the connection is back in the pool here :-(
      //
      // The reason is, that the proxy object is destroyed too early.
      // The proxy object puts the connection back to the free-list of the
      // pool, before we use the connection.
      //
      log_info("doSomething in thread " << threadNum);
      pool.get()->doSomething();
      log_info("doSomething ends in thread " << threadNum);

      log_info("thread ready " << threadNum);
    }
};

int main(int argc, char* argv[])
{
  try
  {
    log_init_info();

    ConnectionPoolType connectionPool(3, Connector("mydb"));

    MyThread th1(connectionPool, 1, 2);
    MyThread th2(connectionPool, 2);
    MyThread th3(connectionPool, 3, 3);
    MyThread th4(connectionPool, 4, 3);
    MyThread th5(connectionPool, 5, 4);

    th1.create();
    th2.create();
    th3.create();
    th4.create();
    th5.create();

    log_info("threads created");

    th1.join();

    // Thread 1 is ready and the connection is put back into the pool.
    // We release all free connections here. At least one connection
    // from thread 1 is released.
    log_info("pool drop");
    connectionPool.drop();

    th2.join();
    th4.join();
    th3.join();
    th5.join();

    log_info("threads joined");
  }
  catch (const std::exception& e)
  {
    std::cerr << e.what() << std::endl;
  }
}

Copyright © 2008 The Tntnet Development Team
Tntnet 1.6