今日は二重起動の防止処理を入れました。

※今日の日記は、かなりマニアックです。


アイコンのダブルクリックを勢い余って、トリプルクリックすると、
プログラムが二重起動してしまいますよね。


それを避けるルーチンをHSPで実現できるみたいなので、組み込んでみました。
スクリプトは、こちらを参考にさせていただきました。




HSPで二重起動を防止するには、3つの方法があるみたいです。


●方法1.
(1) プログラム起動時になんでもいいからファイルを作成する。
(2) (1)で作ったファイルがあったら、強制終了
(3) プログラム終了時に(1)のファイルを消す
⇒二番目に起動したプログラムは(2)ではじかれて終了する。

●方法2.
(1) 起動プログラムにtitleを設定
(2) HSPEXT.DLLのaplsel関数で、(1)と同じタイトルのプログラムを探す
(3) (2)が見つかったら、強制終了
⇒二番目に起動したプログラムは(3)ではじかれて終了する。

●方法3.
Kernel32.dllのミューテックス関数を使う方法

  #uselib "kernel32.dll"
  #func CreateMutexA "CreateMutexA" sptr,int,sptr
  #func CloseHandle "CloseHandle" sptr
  #func GetLastError "GetLastError"

  #define ERROR_ALREADY_EXISTS 183

CreateMutexA 0,0,"yonkoushi"
mutex_handle=stat ; Mutexのハンドルを取得

; エラーを確認
GetLastError

; すでにMutexが存在していた!(存在していてMutexが作成できなかった)
if stat=ERROR_ALREADY_EXISTS {
dialog "2重起動されています!!",1
end
}



3つ方法がありますが、私は方法3を選びました。
アトミックなレベルの処理に堅牢性がありそうだと思ったのです。


アトミックなレベルとは、例えば、
以下のスレッド1とスレッド2が同時に実行されてようないるとき、

<スレッド1>
*aaa
if( flag = 0 ){
flag += 1
処理1
flag = 0
}
else{
goto *aaa
}

<スレッド2>
*bbb
if( flag = 0 ){
flag += 1
  処理2
flag = 0
}
else{
goto *bbb
}



上のスレッド1とスレッド2が同時に実行されているとき、
処理1と処理2は、flag変数の関係で、
同時には実行されないかのように見えます。


ところが、『flag += 1』をマシン語レベルで見ると、

メモリから読み出す。
加算する
書き込む
となっているわけです。



で、二重起動のタイミングが悪いと、

1番目のプログラムが起動する
メモリから読み出す(flag == 0)
加算する
  2番目のプログラムが起動する
  メモリから読み出す(flag == 0)
書き込む(flag == 1)
  加算する
  書き込む(flag == 1)
となって二重起動を防げないわけです。
その点、ミューテックスを使えば、マシン語のレベルで
競合を回避できるということですね!


ただ1つ気になるのは、VISTAとかでもちゃんと動くのかなってことですかね?
大丈夫だとは思うのですが…。