#define _POSIX_C_SOURCE 200809L #include #include #include #include /* Vaším úkolem bude napsat trojici podprogramů: * * 1. ‹counter_start›, který nastartuje asynchronní počítání bajtů * na zadaném popisovači ‹fd›, * 2. ‹counter_read›, který umožní volajícímu kdykoliv přečíst * aktuální hodnotu počítadla, * 3. ‹counter_cleanup›, který vyčká na ukončení spojení na * popisovači a vrátí celkový výsledný počet přečtených bajtů. * * Podobně jako v minulém týdnu budou podprogramy rodiny ‹counter› * propojeny ukazatelem ‹handle›, který je výsledkem podprogramu * ‹counter_start›. */ void *counter_start( int fd, int max_delay ); /* Podprogram ‹counter_read›, kdykoliv je zavolán, vrátí aktuální * hodnotu počítadla bajtů. Předchází-li spuštění ‹counter_read› * zápis ⟦n⟧ bajtů,¹ musí návratová hodnota opakovaného volání * ‹counter_read› (bez jakéhokoliv dalšího vnějšího zásahu) dříve * nebo později nabýt hodnoty ⟦k⟧ takové, že ⟦n - d ≤ k ≤ n⟧, kde * ⟦d⟧ je parametr ‹max_delay› se kterým bylo zavoláno * ‹counter_start›. */ int counter_read( void *handle ); /* Podprogram ‹counter_cleanup› obdrží ukazatel ‹handle›, který byl * vrácen podprogramem ‹counter_start›, a vrátí počet bajtů, které * byly do popisovače ‹fd› zapsané. Zároveň uvolní veškeré zdroje * spojené s ‹handle›. Není-li možné tento počet zjistit, protože * nastala nějaká systémová chyba, výsledkem bude -1. */ int counter_cleanup( void *handle ); /* ¹ Předchází ve formálním smyslu, tzn. jsou-li příslušná volání * ‹write› nebo ‹send› v relaci předcházení se spuštěním * podprogramu ‹counter_read›. */ /* ┄┄┄┄┄┄┄ %< ┄┄┄┄┄┄┄┄┄┄ následují testy ┄┄┄┄┄┄┄┄┄┄ %< ┄┄┄┄┄┄┄ */ #include /* sched_yield */ #include /* signal, SIGPIPE, SIG_IGN */ static void close_or_warn( int fd, const char *name ) { if ( close( fd ) == -1 ) warn( "closing %s", name ); } static void mk_pipe( int* fd_r, int* fd_w ) { int p[ 2 ]; if ( pipe( p ) == -1 ) err( 2, "pipe" ); *fd_r = p[ 0 ]; *fd_w = p[ 1 ]; } static void fill( int fd, ssize_t bytes ) { char buf[ 512 ]; memset( buf, 'x', 512 ); ssize_t nwrote; while ( ( nwrote = write( fd, buf, bytes > 512 ? 512 : bytes ) ) > 0 ) bytes -= nwrote; assert( nwrote != -1 ); assert( bytes == 0 ); } int main( void ) { if ( signal( SIGPIPE, SIG_IGN ) == SIG_ERR ) err( 2, "signal" ); int fd_r, fd_w; void *handle; mk_pipe( &fd_r, &fd_w ); handle = counter_start( fd_r, 10 ); fill( fd_w, 15 ); while ( counter_read( handle ) < 5 ) sched_yield(); assert( counter_read( handle ) <= 15 ); fill( fd_w, 5 ); close_or_warn( fd_w, "write end of the pipe" ); assert( counter_cleanup( handle ) == 20 ); mk_pipe( &fd_r, &fd_w ); handle = counter_start( fd_r, 1000 ); fill( fd_w, 6000 ); while ( counter_read( handle ) < 5000 ) sched_yield(); assert( counter_read( handle ) <= 6000 ); close_or_warn( fd_w, "write end of the pipe" ); assert( counter_cleanup( handle ) == 6000 ); return 0; }