タイムイベント
タイムイベント: プログラマが望む時刻に起動されるイベントのこと
送信側: エンコードタイミング、RTCP パケット送信タイミング
受信側: デコードタイミング、RTCP パケット送信タイミング
それぞれの関数の詳細は、Windows の場合は MSDN、Linux の場合は man コマンドによるオンラインマニュアルを参照のこと (例: man 3 usleep)。
Windows版:
マルチスレッド関数 | |
Sleep | ミリ秒単位にスレッドの実行を中断 |
マルチメディアタイマ | |
timeGetTime | ミリ秒単位にシステム時刻を取得 |
timeSetEvent | 特定の時刻に特定の関数を起動 |
timeKillEvent | timeSetEvent で設定されたタイマイベントの解除 |
Linux版:
マルチスレッド関数 | |
sleep | 秒単位にスレッドの実行を中断 |
usleep | マイクロ秒単位にスレッドの実行を中断 |
nanosleep | ナノ秒単位にスレッドの実行を中断 |
gettimeofday | マイクロ秒単位にシステム時刻を取得 |
各種GUIライブラリ毎のタイムイベント関数 | |
準備中 |
Windows版: マルチメディアタイマの利用
以下のプログラムは、1秒 (PERIOD = 1000ミリ秒) 毎にタイムイベントとしてコールバック関数 (callback) を呼び出し、そのたびに現在時刻と前回タイムイベントとの時間差を表示させるプログラムである。
他の作業を何もしていない場合は、1秒おきに正確にタイムイベントが発生する。しかし、他のアプリケーションを起動するなど、何らかの負荷をかけるとイベント発生間隔が揺らぐことがわかる。
一方 Sleep 関数は、CPU資源を無駄使いせずに処理を中断するのに有効な関数である。試しにシステムモニタ等を起動し、下のプログラムで Sleep をコメントアウトして実行してみると、CPU負荷が上がることがわかる。ただし、時間の精度は安定していない。
#include <stdio.h> #include <windows.h> #define PERIOD 1000 // タイムイベント間隔 #define LOOP 10 // 各種パラメータ unsigned int curr_time, prev_time, diff_time; unsigned int event_count = 0; // タイムイベントとして呼び出されるコールバック関数 static void CALLBACK callback(unsigned int timerID, unsigned int msg, unsigned int usrParam, unsigned int dw1, unsigned int dw2) { // 現在時刻と前回イベントとの時間差を表示 curr_time = timeGetTime(); diff_time = curr_time - prev_time; prev_time = curr_time; printf("現在時刻:%d ミリ秒、前回イベントとの時間差:%d ミリ秒\n", curr_time, diff_time); event_count++; } void main() { unsigned int timer; // タイムイベントの開始 timer = timeSetEvent(PERIOD, 1, (LPTIMECALLBACK) callback, (DWORD) NULL, TIME_PERIODIC); if(timer == 0) { printf("タイムイベントの生成に失敗\n"); exit(0); } // ループ while(1) { Sleep(1000); // 1秒間休み。この Sleep がないと CPU 資源の無駄使い if(event_count == LOOP) break; } // タイムイベントの終了 timeKillEvent(timer); } |
Linux版: gettimeofday の利用
各種GUIライブラリで用意されたタイムイベント関数を使う手もあるが、ここでは gettimeofday 関数を使用し、1秒ごとに時刻を取得し、イベント間の時間差を表示するプログラムを以下に示す。
#include <stdio.h> #include <sys/time.h> #include <unistd.h> #include <time.h> #define SECOND 1000000.0 #define LOOP 10 struct timeval current, prev; void function() { double t0, t1; // 時刻の取得とイベント間時間差の表示 gettimeofday(¤t, NULL); t0 = current.tv_sec * SECOND + current.tv_usec; t1 = prev.tv_sec * SECOND + prev.tv_usec; prev.tv_sec = current.tv_sec; prev.tv_usec = current.tv_usec; printf("difference: %g\n", (t0-t1) / 1000.0); } main() { int i; // 1秒間隔で関数 function() を呼び出し gettimeofday(&prev, NULL); for(i=0; i<LOOP; i++) { usleep(1000000); function(); } } |