全て クラス 名前空間 関数 変数 型定義 列挙型 列挙値 ページ
マルチスレッドアプリケーション

マルチスレッドアプリケーションでの使用方法

ここではTransactdクライアントをマルチスレッドアプリケーションでどのように使用するかを説明します。

コネクション

nsdatabase::open() は自動でサーバーとの接続も行います。その際デフォルトでは、そのホストへの接続が既にある場合それを共有します。 シングルスレッドアプリケーションであれば、接続を共有することでリソースを節約できます。
しかしながら、マルチスレッドアプリケーションの場合、接続を共有してしまうとうまく動作しません。そこで、 nsdatabase::connect() メソッドを使用して新しい接続を要求します。具体的には、connect() メソッドの第二パラメータの newConnectionにtrueを渡して呼び出します。複数の nsdatabase (継承した databaseオブジェクトも含む) で新しい接続を使用した場合、どのスレッドから使用するかに関わらず、それぞれ異なるコネクションによってサーバーとの通信が行われます。

クライアントオブジェクトのスレッドセーフモデル

nsdatabase database nstable table オブジェクトなど主要なオブジェクトは、オブジェクト単位でのスレッドセーフです。メソッド単位はスレッドセーフではありません。
オブジェクト単位でのスレッドセーフとは、「1つのdatabaseオブジェクトとそこから生成されたtableオブジェクトを含めたオブジェクトのグループは、1つのスレッドから安全に使用できる」ということです。別々のオブジェクトグループならば、同時に別のスレッドから安全に操作可能です。 以下は、10個のスレッドからデータベースに接続しアクセスするサンプルコードです。

void thread_function()
{
database* db = database::create();
db->connect(URI, true); //スキーマ名は省略できます。 "tdap://host/database"
db->open(URI);
table* tb = db->openTable(tableName, mode);
...
tb->release();
}
int main()
{
boost::thread_group threads;
for (int i = 0; i < 10; ++i)
threads.create_thread(thread_function);
threads.join_all();
}

コネクションプール

Transactdクライアントにはコネクションプールが用意されています。コネクションプールはアプリケーションに1つだけグローバルに実態化されます。 プールには、複数のdatabaseオブジェクトが保持されます。
pooledDbManeger はそのプールにアクセスするための、アクセサクラスです。このオブジェクト自体はほとんどリソースを保持しません。単にアクセスするためのクラスです。databaseオブジェクトを使用したいときに、 pooledDbManeger::use() メソッドを使ってpooledDbManegerオブジェクト内にdatabaseオブジェクトを取り出します。取り出したdatabaseオブジェクトは、そのスレッド内で安全に使用することができます。pooledDbManegerを破棄するか pooledDbManager::unUse() を呼び出すと、取り出したdatabaseオブジェクトはプールに返却されます。
貸し出し中のdatabaseオブジェクトは他からの取り出し要求で貸し出されることはありません。それによりマルチスレッドアプリケーションで安全にdatabaseオブジェクトを使用できます。
プールのデータベースがmaxConnectionに達しかつすべて貸し出し中で新たな貸し出し要求 (use()の呼び出し)が来た場合、他のスレッドによって返却されるまでuse() メソッドはwaitします。
コネクションプールは、同じホストの同じデータベースを複数保持することはもちろん、異なる複数のホストのデータベースを複数保持することも可能です。
同じホストの同じデータベースを複数保持する場合は、 pooledDbManager::reserve() メソッドを使って事前にdatabaseオブジェクトを必要なだけ準備できます。その場合、以降の use() メソッドでデータベースを指定する必要はありません。
異なる複数のホストのデータベースを保持している場合は、どの接続先のものを取り出すのかuse()のパラメータにて指定します。コネクションプールはプールの中から、指定されたホストのデータベースを持つdatabaseオブジェクトを探して貸し出します。
以下は pooledDbManager::reserve() を使用したマルチスレッドアプリケーションのサンプルコードです。

#include <pooledDatabaseManager.h>
void thread_function()
{
pooledDbManeger mgr;
mgr.use();
database* db = mgr.db();
table* tb = db->openTable(tableName, mode);
...
tb->release();
}
int main()
{
connectParams param("tdap", "192.168.0.11", "testdb", "test");
pooledDbManeger::reserve(10, param);
boost::thread_group threads;
for (int i = 0; i < 10; ++i)
threads.create_thread(thread_function);
threads.join_all();
}

Transactd SDK 2018年07月31日(火) 19時40分24秒 doxygen