msはマイクロソフトではなく1000分の1秒。
ここらへんの続き。
今こんな感じ。
#include <X11/Xlib.h> #include <stdio.h> #include <stdlib.h> // nanosleep用。 #include <time.h> // gettimeofday用。 #include <sys/time.h> #define WIDTH 400 // ウィンドウの幅。 #define HEIGHT 200 // ウィンドウの高さ。 #define R 10 // 円の半径。 #define V 5 // 1回の移動の距離。 #define INTERVAL 20 // 移動の間隔。(ms) #define MAX 250 // 最大間隔。(ms) #define MIN 10 // MINms単位で間隔を変える。MAX > 間隔 > MINという訳ではない。ややこし。 #define N 10 // 繰り返し回数。 main(){ Display *d; int screen; Window root, window; unsigned long black, white; XGCValues xgcv; GC gc; char s[5]; Window circle[2]; // 0が右、1が左。 int cx[2], cy[2]; struct timespec interval, rand_int; struct timeval start_time, end_time; int i = N; // i回繰り返す。 interval.tv_sec = 0; interval.tv_nsec = INTERVAL * 1000 * 1000; if( (d = XOpenDisplay( NULL )) == NULL ){ fprintf( stderr, "can't open display.\n" ); exit(1); } screen = DefaultScreen(d); root = DefaultRootWindow(d); white = WhitePixel(d, screen); black = BlackPixel(d, screen); window = XCreateSimpleWindow(d, root, 0, 0, WIDTH, HEIGHT, 1, black, white); gc = XCreateGC(d, window, 0, NULL); cx[0] = WIDTH - 2*R; cy[0] = HEIGHT/2 - R; cx[1] = WIDTH/2 - 2*R; cy[1] = HEIGHT/2 - R; circle[0] = XCreateSimpleWindow(d, window, cx[0], cy[0], 2*R, 2*R, 0, black, white); circle[1] = XCreateSimpleWindow(d, window, cx[1], cy[1], 2*R, 2*R, 0, black, white); XMapWindow(d, window); XMapWindow(d, circle[0]); XMapWindow(d, circle[1]); XFlush(d); fgets(s, 5, stdin); XFillArc(d, circle[0], gc, 0, 0, 2*R, 2*R, 0, 360*64); XFillArc(d, circle[1], gc, 0, 0, 2*R, 2*R, 0, 360*64); XFlush(d); do{ if( i-- <= 0 ){ break; } srand( time(NULL) ); rand_int.tv_nsec = (int)( MAX/MIN * ( rand()/(double)RAND_MAX ) ) * MIN * 1000*1000; rand_int.tv_sec = 0; cx[0] = WIDTH - 2*R; cx[1] = WIDTH/2 - 2*R; XMoveWindow(d, circle[1], cx[1], cy[1]); XFlush(d); while( cx[0] > WIDTH/2 ){ nanosleep( &interval, NULL ); cx[0] -= V; XMoveWindow(d, circle[0], cx[0], cy[0]); XFlush(d); }
gettimeofday( &start_time, NULL ); nanosleep( &rand_int, NULL ); cx[1] -= V; XMoveWindow(d, circle[1], cx[1], cy[1]); XFlush(d); gettimeofday( &end_time, NULL );
while( cx[1] > 0 ){ nanosleep( &interval, NULL ); cx[1] -= V; XMoveWindow(d, circle[1], cx[1], cy[1]); XFlush(d); }
printf( "sleep( %d.%03d %03d %03ds )\n", rand_int.tv_sec, rand_int.tv_nsec/(1000*1000), (rand_int.tv_nsec/1000)%1000, rand_int.tv_nsec%1000 ); if( end_time.tv_usec - start_time.tv_usec >= 0 ){ printf( "sleep %d.%03d %03ds\n", end_time.tv_sec - start_time.tv_sec, (end_time.tv_usec - start_time.tv_usec )/1000, (end_time.tv_usec - start_time.tv_usec )%1000 ); }else{ printf( "sleep %d.%03d %03ds\n", end_time.tv_sec - start_time.tv_sec -1, (end_time.tv_usec - start_time.tv_usec +1000*1000 )/1000, (end_time.tv_usec - start_time.tv_usec +1000*1000 )%1000 ); }
fgets(s, 5, stdin); }while( s[0]=='1' || s[0]=='2' || s[0]=='3' ); }
nanosleepで間隔をあけるようにした*1。その前後でgettimeofdayで時間を手に入れて、差を出してみた。その出力。
$ ./hi-3.a-2 sleep( 0.020 000 000s ) sleep 0.029 993s 1 sleep( 0.040 000 000s ) sleep 0.049 995s 1 sleep( 0.180 000 000s ) sleep 0.189 968s 2 sleep( 0.160 000 000s ) sleep 0.169 967s 2 sleep( 0.060 000 000s ) sleep 0.069 968s 1 sleep( 0.200 000 000s ) sleep 0.209 951s 3 sleep( 0.220 000 000s ) sleep 0.229 962s 3 sleep( 0.110 000 000s ) sleep 0.119 977s 2 sleep( 0.170 000 000s ) sleep 0.179 963s 2 sleep( 0.060 000 000s ) sleep 0.069 975s 1
sleep( …s )がnanosleepで指定した値。sleep …s がgettimeofdayの差で出した実際の値。*2
10ms程、長くかかってる。10msがsleepできる単位、ってことですな。なんかOS論でやったような。
そんなことより、これってグラフ書く時どっちの値使えばいいんですかい。実際の値の方がいいような気がするけど、パーセント出すときに10ms単位に四捨五入するんだったら、指定した値を使うか、+10msして使うかした方がよさそうな気がするんですが。
+10msがいい感じかな。