SERWER ZADAŃ
============

Załóżmy, że mamy program, który potrafi realizować jakieś skomplikowane zadanie.
Program ten przyjmuje opis zadania na wejściu po czym wykonuje zadanie (nie interesuje
nas, co robi z wynikiem zadania). Nie wiemy, jak długo będzie trwało wykonywanie
zadania; czas ten może być różny zależnie od danych wejściowych.

Na potrzeby testowania można na przykład przyjąć, że niezwykle skomplikowanym zadaniem
jest wyliczenie wyrażenia arytmetycznego i że realizujący je program to:


#!/bin/bash

#wczytuje opis zadania ze stdin
read zadanie

#"wykonuje zadanie" przez pewien czas od 1 do 10 sekund
sleep $[ $RANDOM % 10 + 1 ]

#wypisuje wynik zadania do pliku
echo "$zadanie = $[$zadanie]" >> $HOME/wyniki



Chcemy napisać program (serwer zadań), który będzie przyjmował opisy zadań do
wykonania i zlecał je programom wykonującym pracę. Program ten ma jeden parametr
wiersza poleceń: liczbę n wskazującą, ile maksymalnie procesów realizujących
zadania może być jednocześnie uruchomionych. Ścieżka do programu realizującego
pojedyncze zadanie może być umieszczona w serwerze.

Nasz serwer wczytuje opisy zadań do wykonania ze swojego standardowego wejścia (można
założyć, że opis każdego kolejnego zadania zajmuje jeden wiersz). Dla każdego zadania
serwer uruchamia osobny realizujący je proces. W żadnym momencie liczba procesów pracujących
nad zadaniami nie może przekroczyć n. W razie nadmiaru zleceń dalsze zlecenia muszą czekać
na swoją kolej.

Warunkiem koniecznym akceptacji rozwiązania jest zapewnienie dwóch własności:
(1) liczba uruchomionych jednocześnie procesów realizujących zadania nie może przekroczyć n
(2) jeżeli oczekują nowe zlecenia a liczba uruchomionych procesów jest mniejsza 
    od n, to należy niezwłocznie uruchomić nowe zlecenie. Innymi słowy nie można 
    marnować dostępnej mocy: zlecenia nie mogą czekać, jeśli są jeszcze wolne
    "sloty" w których można je uruchomić. 

Można założyć, że serwer ma działać w nieskończoność oraz że długość wiersza z opisem
zadania jest ograniczona z góry przez wybraną stałą. Można pominąć obsługę błędów przy
wywołaniach funkcji systemowych, za to należy dokładnie zamykać niepotrzebne deskryptory.

Funkcje pomocnicze, które mogą być przydatne (niekoniecznie wszystkie i niekoniecznie muszą):

gets, fgets -- wczytuje jeden wiersz ze stdin do tablicy znaków
strlen      -- oblicza długość napisu

Termin itp.
===========
16 stycznia 2008, na adres aszek@mimuw.edu.pl. Tam też pytania.

FAQ
===
Q: Jakiego typu są zlecenia przekazywane do serwera?
A: Jedno zlecenie = jeden wiersz. Nie wnikamy w jego strukturę, przekazujemy go w całości
   bezpośrednio do procesu realizującego zlecenia.