/*	Praca domowa ZPR
Katarzyna Rusinowska
Grupa studencka:	N1-IBERE2
Temat pracy:	boost::asio (obsługa timerów)
*/

/*
Operacje wejścia/wyjścia często mają wyznaczony czas w przeciągu, którego muszą zostać wykonane. 
Czas ten może być określony jako czas absolutny, bądź obliczony w stosunku do czasu bieżącego.
W celu sprecyzowania owego czasu z pomocą przychodzi nam biblioteka Asio wraz z klasą deadline_timer,
która pozwala nam na zaimplementowanie timerów synchronicznych i asynchronicznych.
*/

/*
Ważniejsze funkcje dostępne w klasie deadline_timer :
-basic_deadline_timer::async_wait
async_wait(handler) służy do inicjacji asynchronicznego czekania na timer, każde wywołanie async_wait 
spowoduje wywołanie dokładnie raz handlera, w przypadku kiedy: 
a)minie czas 
b)działanie zegara zostanie anulowane(zostanie wywołany kod błędu: boost::asio::error::operation_aborted)  
Wywoływany handler musi mieć następująca formę:
void handler(const boost::system::error_code& error / Result of operation/);

-basic_deadline_timer::expires_from_now
ustawienie czasu upłynięcia terminu w stosunku do czasu bieżącego np. expires_from_now(boost::posix_time::seconds(5))

-basic_deadline_timer::expires_at0
ustawienie terminu ostatecznego wygaśnięcia jako czasu absolutnego 

-basic_deadline_timer::cancel
anuluje każdą asynchroniczną operację, na którą czeka timer

-basic_deadline_timer::wait 
wykonuje "blokujące" czekanie na timer
*/

/*
Zaimplementowane konstruktory umożliwiają:
-tworzenie timera bez ustawiania czasu wygaśnięcia, np. boost::asio::deadline_timer t(io), wymaga wywołania po niej funkcji expires_at() 
albo expires_from_now()aby skonfigurować czas wygaśnięcia

-tworzenie timera z absolutnym czasem wygaśnięcia, 

-tworzenie timera z aktualnym czasem wygaśnięcia, 
np. boost::asio::deadline_timer t(io,boost::posix_time::time_from_string("2009-05-01 23:59:59.000"))
*/

/*
Ogólny algorytm wykorzystania timerów przy operacjach asynchronicznych(tu asynchroniczne czytanie z socketa):
 1)io_service ios;
  deadline_timer t(ios);
  tcp::socket socket(ios);
 2)socket.async_read()
 3)timer_.expires_from_now(boost::posix_time::seconds(5));
   timer_.async_wait(handler);
W przypadku przerwania odczytu z soceta na dłużej niż 5 sekund zostanie wywołany handler.
*/

//PRZYKŁAD OBSŁUGI TIMERÓW Z WYKORZYSTANIEM BIBLIOTEKI boost::asio
#include <iostream>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/bind.hpp>


//Operacja synchronicznego czekania z wykorzystaniem czasu aktualnego, blokuje dalsze wykonywane zadania
void timer_synch()
{

	boost::asio::io_service io;//niezbędna usługa potrzebna każdemu obiektowi boost::asio do przeprowadzenia operacji I/O 
							   //ułatwia wykonywanie operacji na asynchronicznych funkcjach

	boost::asio::deadline_timer t(io);

	t.expires_from_now(boost::posix_time::seconds(10));//ustawienie czasu upłynięcia terminu w stosunku do czasu bieżącego
													   //lub boost::asio::deadline_timer t(io,boost::posix_time::seconds(5)); 
	std::cout<<"Testowanie timera synchronicznego rozpoczete\n";
	t.wait();//gwarantuje brak powrotu dopóki zegar nie wygaśnie
	std::cout<<"Testowanie timera synchronicznego zakonczone\n";

}

//Funkcja wywoływana w przypadku wygaśnięcia czasu oczekiwania timera asynchronicznego
void handler(const boost::system::error_code& e)
{
	std::cout << "Handler timer asynchronicznego: Czas minal\n";
}

//Operacja asynchronicznego czekania z wykorzystaniem czasu aktualnego
void timer_asynch()
{

	boost::asio::io_service io;//niezbędna usługa potrzebna każdemu obiektowi boost::asio do przeprowadzenia operacji I/O 
							   //ułatwia wykonywanie operacji na asynchronicznych funkcjach

	boost::asio::deadline_timer t(io, boost::posix_time::seconds(10));
	
	std::cout<<"Testowanie timera asynchronicznego rozpoczete\n";
	t.async_wait(handler);//inicjacja asynchronicznego czekania na timer
	std::cout<<"Wtrakcie czekania ...\n";
	io.run();//biblioteka asio gwarantuje nam, że callback  handlera będzie tylko wywołany z wątku , który obecnie wywołuje io_service::run()
	std::cout<<"Testowanie timera asynchronicznego zakonczone\n";
}


int main()
{
	try{
		timer_synch();
		timer_asynch();
	}
	catch (std::exception& e)
	{
		std::cout << "Wyjatek: " << e.what() << "\n";
		getchar();
	}
	return 0;
}