/**
*
* @File : Millisleep.cxx
*
* @Authors : D. Mathieu
*            M. Laporte
*
* @Date : 28/09/2000
*
* @Version : V1.0
*
* @Synopsis :
*
**/
#include <iostream>   
#include <exception>
#include <string>
#include <csignal>    // sigemptyset(), sigaction, SIGALRM
#include <ctime>      // setitimer(), ITIMER_REAL
#include <cstdlib>    // atoi()

#include <unistd.h>   // pause()

#include "nsSysteme.h"
#include "CExc.h"
#include "Time.h"     // CTimeval
#include "CTimer.h"   // CTimerReal

using namespace nsBAO;
using namespace nsSysteme;

namespace
{
    void Derout (int) {}
    void DeroutAlarm (int) { cout << "Fin du CTimerReal" << endl; }

    unsigned long MilliSleep (unsigned long NbMilliSec)
    {
        itimerval Val = { {0, 0},
                          {NbMilliSec / 1000, (NbMilliSec % 1000) * 1000} };

        itimerval OldVal;

        struct ::sigaction Action;
        struct ::sigaction OldAction;

        Action.sa_flags   = 0;
        Action.sa_handler = Derout;
        ::sigemptyset (& Action.sa_mask);

        ::setitimer (ITIMER_REAL, &Val, &OldVal);

        Sigaction (SIGALRM, &Action, &OldAction);
        ::pause();
        Sigaction (SIGALRM, &OldAction, 0);

        ::setitimer (ITIMER_REAL, &OldVal, &Val);

        return Val.it_value.tv_sec * 1000 + Val.it_value.tv_usec / 1000;

    } // MilliSleep()

} // namespace anonyme

int std::ppal (int argc, char * argv []) throw (exception)
{
    if (2 != argc) throw CExc (string ("Usage : ") + argv [0] + " <delai>");

    cout << "Essai avec SIGALRM ignoré" << endl;
    const unsigned int CstDelai = ::atoi (argv [1]);
    Signal (SIGALRM, SIG_IGN);
    Signal (SIGINT, Derout);
    cout << "Debut de MilliSleep()" << endl;
    cout << "Il restait " << MilliSleep (CstDelai) << " milli-secondes" << endl;

    cout << "Essai en concurrence avec un timer ITIMER_REAL" << endl;

    CTimerReal Timer (10);
    Timer.Start();

    Signal (SIGALRM, DeroutAlarm);
    cout << "Debut de MilliSleep()" << endl;
    cout << "Il restait " << MilliSleep (CstDelai) << " secondes" << endl;

    ::pause();

    sigset_t Mask;
    ::sigemptyset (&Mask);
    ::sigaddset   (&Mask, SIGALRM);
    Sigprocmask (SIG_BLOCK, &Mask, 0);

    cout << "Debut de MilliSleep()" << endl;
    cout << "Il restait " << MilliSleep (CstDelai) << " secondes" << endl;

    return 0;

}  //  ppal()