Maszyny mamy po to, aby bez znużenia wykonywały powtarzalne zadania. Czasami jednak algorytm wymaga zaprzestania pracy na jakiś czas. Na przykład, gdy nie ma nic innego do roboty, poza odliczaniem czasu pozostałego do detonacji jakiegoś ładunku wybuchowego. Okazuje się, że wstrzymanie wykonywania pracy programu nie jest takie trywialne, jednak z pomocą przychodzą narzędzia, które udostępnia nam system operacyjny. Można go poprosić, aby "uśpił" nasz program (proces) na jakiś czas. Algorytm nie człowiek- zasypia natychmiast i wznawia pracę od razu, gdy system operacyjny go wzbudzi.

Do uśpienia programu służą funkcje z rodziny sleep, które zazwyczaj są dostępne w większości języków programowania. Funkcje te przeważnie jako parametr przyjmują ilość sekund/milisekund/mikrosekund, na jaką program ma zostać zawieszony.

Należy pamiętać o tym, że czas, który podamy jako argument nie zawsze (nigdy?) będzie czasem, na jaki nasza aplikacja została uśpiona. O ile w przypadku sekund (czyli relatywnie długich czasów) ta dokładność będzie na tyle wysoka, że niedokładność można pominąć. W przypadku bardzo krótkich interwałów rzędu mikro i milisekund, czas uśpienia będzie się różnić w zależności od priorytetu naszego procesu, aktualnego obciążenia procesora, a także samego systemu operacyjnego, który ma ostatnie słowo i to on "podejmuje decyzję", kiedy dokładnie program zostanie wzbudzony. Z niedokładnością, oczywiście, można sobie poradzić wyposażając algorytm w wewnętrzne liczniki, o których poniżej.

Czy poza odliczaniem tykania bomby zegarowej usypianie się przydaje? Klasycznym przykładem niech będzie gra. Płynność animacji gry zależy od ilości klatek, które wykonają się w ciągu jednej sekundy. Przyjmijmy, że płynność uzyskujemy, gdy program przeliczy klatkę 60 razy na sekundę. Co w przypadku, gdy sprzęt jest na tyle potężny (albo gra jest bardzo), że może wykonać 1000 klatek na sekundę? Uzyskany efekt będzie taki, że gra po prostu będzie obłędnie szybko się wykonywać i nie będzie możliwe wykonanie jakiejkolwiek akcji. Do tego celu- czyli do sterowania prędkością/płynnością gry przychodzi właśnie usypianie.

Pseudorozwiązanie takiego problemu mogłoby wyglądać następująco:

int czas_przed_klatka_gry = 0;
int czas_po_klatce_gry = 0;
while (1) { // gramy w nieskoczonosc

  // pobieramy aktualny czas jako punkt odniesienia
  czas_przed_klatka_gry = pobierz_czas();
  graj_w_gre(); // wszystkie rzeczy zwiazane z gra- rysowanie sceny etc.

  // pobieramy czas, ktory jest po przebiegu calej logiki gry, roznica czasu po klatce i przed klatka da odpowiedz jak dlugo wykonywala sie gra.
  czas_po_klatce_gry = pobierz_czas();

  // roznica czasu pozwala przyrownac go do czasu, jaki poswiecamy na klatke gry. Jezeli potrzeba 60 klatek na sekunde, to jedna klatka powinna trwac maksymalnie 1/60 sekundy
  if ((czas_po_klatce_gry - czas_przed_klatka_gry) < 1/60) {
    // jezeli gra wykonala sie szybciej, tj. Roznica czasu jest mniejsza niz 1/60, nalezy "odczekac" pozostały czas dla zachowania plynnosci animacji

    usleep(czas_po_klatce_gry - czas_przed_klatka_gry);
  }
}

Powyższy przykład (mocno uproszczony) pozwala zachować płynność animacji na granicy 60Hz. Nie pozwoli wykonywać się szybciej. W przypadku, gdy logika gry zajmie więcej czasu… po prostu tych klatek będzie mniej, a tym samym płynność gry będzie mniejsza.

Należy pamiętać, że usypianie programu należy wykorzystywać z zachowaniem zdrowego rozsądku. Kategorycznie nie polecam "synchronizacji" programu na zasadzie "coś innego wykonuje się około 5 sekund to na tyle uśpię swój program". Czas w informatyce jest bardzo względny i to, że coś wykonuje się mniej więcej tyle a tyle czasu, nie oznacza, że na innym komputerze, nawet z takimi samymi parametrami, wykona się z podobną prędkością. Można w bardzo prosty sposób natrafić na "dziwne, u mnie działa".

Dobry kontent!

Piotr Poźniak

Piotr Poźniak

Programuję od ponad 15 lat. Prowadzę software house. Angażuję i zachęcam wszystkich do programowania w ramach inicjatywy Programowanie jest łatwe.

Bądź pierwszy, podziel się swoją opinią!