2011年06月10日

排他制御の二重呼び出しでデッドロックを起こすときどうします?

例えば、VRAMのようなシステムに一つしかないリソースを複数のタスクからアクセスするライブラリAPIを作るときに、提供するAPIの内部でセマフォやミューテックスを使って排他制御をするとします。

以下のようなコードになったとします。



void funcA( void )
{
mutex.lock();

funcB();

mutex.unlock();
}



このとき、funcB()の内部からfuncA()を呼び出すと、当然 mutex.lock() の箇所でデッドロックを起こします。



void funcB( void )
{
funcA();
}



このケースは、論外とは言いませんが、もう少し設計を考えて funcA() を呼び出さないようにすれば回避できそうです。

では funcB()内部から、funcA()を呼び出したアプリケーション側にイベント通知の為にコールバック関数を呼び出し、呼び出されたコールバック関数から funcA() が呼び出されたらどうでしょうか?
(意外と、アプリケーション側とライブラリ側の担当者が別々だったりすると、こんなことはよく起こります。)



void funcB( void )
{
app->callbackA();
}

void callbackA()
{
funcA();
}



これも、アプリケーション側の設計をもう少し考えて。。。なんていうのが通用しないことがあります。
(ある程度プログラムの作り込みが完了しているところに、アプリケーション側の担当者にプログラム変更を依頼すると、「大幅な変更になるので対応できません。」と拒否されたりします。
まぁ、この辺りは個々の担当者間の力関係で決まってきます。。。もうプログラミングとは関係ない話です。)

なんとかライブラリAPI内で解決したいところです。

私なら安直に以下のように修正します。
(まぁ、別によくある手法(?)です。)



void funcA( void )
{
static int locked_task_id;

int lock_flg = 0;
int task_id = get_task_id();

if( locked_task_id != task_id ){
mutex.lock();
locked_task_id = task_id;
lock_flg = 1;
}
funcB();

if( lock_flg == 1 ){
locked_task_id = 0;
mutex.unlock();
}
}



そもそも、ここで問題になっているのは、同一のタスクから二重に mutex.lock() を呼び出している事なので、mutex.lock()を呼び出したタスクのタスクIDを保持しておきfuncA()が呼び出されたときに、mutex.lock()を掛けたタスクと同一のタスクIDの場合、mutex.lock() を呼び出さないようにします。
当然、mutex.lock()を呼び出さなかったときは mutex.unlock() も呼び出さないようにします。

何となくうまく行きそうですがどうでしょうか?

タスクIDが取得出来ないようなOSの場合。。。。どうしましょう(;^_^A


posted by kana-soft at 02:07| Comment(2) | ソフトウェア

2011年06月04日

DirectSoundでマイクから録音するサンプルプログラムを作りました

DirectSoundを利用してマイクから録音するサンプルプログラムを作りました。

詳しくは以下のホームページにあります。

http://www.kana-soft.com/tech/sample_0011.htm

レイテンシを短くしようと試行錯誤したのですが、挫折しました。。。



posted by kana-soft at 22:18| Comment(0) | C/C++

Visual Studio 2005 SP1でリンクエラー(LNK1103)が発生

Visual Studio 2005 で、最新の DirectX SDK を使ったら、「致命的なエラー LNK1103: デバッグ情報が壊れています。」なるメッセージが表示されてリンク出来なくなってしまいました。

調べてみると、Visual Studio 2008でコンパイルしたlibファイルは、Visual Studio 2005とは互換性に問題があるらしいです。

う〜ん、困った。。。


しかし、既に修正用のプログラムがリリースされていていました。

Microsoftのホームページに詳細があります↓↓↓
http://support.microsoft.com/kb/949009/ja


修正プログラムを実行して、再度コンパイルしてみると無事コンパイルできました。

とりあえず、一安心。



posted by kana-soft at 03:23| Comment(0) | ソフトウェア