<?php
$file = './text.txt' ;
echo filemtime( $file ) . "¥n" ;
touch( $file );
echo filemtime( $file ) . "¥n" ;
?>
なんてスクリプトを実行しても、touch前のファイル更新時刻とtouch後のファイル更新時刻は同じタイムスタンプを返します。つまり、以下のプログラム(以前紹介したことのある関数)は意図した動作はしてくれません。$file = './text.txt' ;
echo filemtime( $file ) . "¥n" ;
touch( $file );
echo filemtime( $file ) . "¥n" ;
?>
★これはまちがい★
<?php
function sleeptimer( $file , $sec , $timeout){
$start = time();
while(1){
if( file_exists( $file )){
if( time()-filemtime( $file) > $sec ){ //最低$sec秒あいだを空ける
touch( $file ); //ファイルの更新時刻を更新
return true; //成功
}else{
if( time() - $start >= $timeout ){ //giveup
return false;
}
usleep( mt_rand(200000 , 800000 ) ); //0.2〜0.8秒待ちリトライ。
}
}else{
touch( $file );
return true;
}
}
}
?>
<?php
function sleeptimer( $file , $sec , $timeout){
$start = time();
while(1){
if( file_exists( $file )){
if( time()-filemtime( $file) > $sec ){ //最低$sec秒あいだを空ける
touch( $file ); //ファイルの更新時刻を更新
return true; //成功
}else{
if( time() - $start >= $timeout ){ //giveup
return false;
}
usleep( mt_rand(200000 , 800000 ) ); //0.2〜0.8秒待ちリトライ。
}
}else{
touch( $file );
return true;
}
}
}
?>
ファイル情報に関するキャッシュをクリアしてやれば思い通りの動作をします。
☆これなら意図した動作をします☆
<?php
function sleeptimer( $file , $sec , $timeout){
$start = time();
while(1){
if( file_exists( $file )){
clearstatcache();
if( time()-filemtime( $file) > $sec ){ //最低$sec秒あいだを空ける
touch( $file ); //ファイルの更新時刻を更新
return true; //成功
}else{
if( time() - $start >= $timeout ){ //giveup
return false;
}
usleep( mt_rand(200000 , 800000 ) ); //0.2〜0.8秒待ちリトライ。
}
}else{
touch( $file );
return true;
}
}
}
?>
<?php
function sleeptimer( $file , $sec , $timeout){
$start = time();
while(1){
if( file_exists( $file )){
clearstatcache();
if( time()-filemtime( $file) > $sec ){ //最低$sec秒あいだを空ける
touch( $file ); //ファイルの更新時刻を更新
return true; //成功
}else{
if( time() - $start >= $timeout ){ //giveup
return false;
}
usleep( mt_rand(200000 , 800000 ) ); //0.2〜0.8秒待ちリトライ。
}
}else{
touch( $file );
return true;
}
}
}
?>
clearstatcache()はファイル情報に関するキャッシュをクリアする関数です。
ということで、ご迷惑をおかけしました。
匿名です
疑問に思ったのですが、なぜファイルの更新日時なのでしょうか?
usleep()を使っているのであればそれ自身が遅延なのではと
思ったのですが、そしてもし確認がしたいのであれば、
開始前と開始後にmicrotime()を使えば良い気がします。
すごく気になったので調べましたが、
PHPの公式リファレンスのmicrotime関数の使用例そのものが、
すごく良いタイマーとスリープの例が載っていました。
板主さんの例だとどんな利点がありますか?
tyzから匿名ですへの返信
複数のスレッドで、単一のタイマーを使いたい…ということです。
具体的に言うと、たとえば、
・外部のサイトに要求を送信するphpスクリプト(hoge.phpとします)があります。
・外部サイトに負荷をかけたくないので、hoge.phpが動いている自分のサイトから1秒に1回以上はリクエストを送信しないようにしたい。
このとき、hoge.phpが「常にひとつだけ」動いているのならば、おっしゃるとおりusleep()などを使って、リクエストを送信するたびに1秒間スリープさせれば大丈夫でしょう。
でも、hoge.phpがWeb上に公開されていて、AさんとBさんが「同時に」アクセスしてきた場合は…。
Aさんがアクセスして(動かして)いるhoge.phpの中では、usleep()を仕掛けておけばリクエスト間隔は1秒以上空きます。Bさんが動かしているhoge.phpの中でも同様です。
しかしサイト全体で見ると、Aさんのリクエスト送信と、Bさんのリクエスト送信との間が1秒空く…とは限らないですよね。「自分のサイト全体からの外部へのリクエストを1秒に1回以内に抑制したい」ならば、Aさんが動かしているhoge.phpとBさんが動かしているhoge.phpとの間で共通なタイマーが必要になってきます。
ということで、この記事で書いたような簡易スリープタイマーの登場、というわけです。