// E07-Interrupt.cpp -- demonstrates thread interruption using Task::interrupt method

#include <Platform.h>
using namespace Platform;


// MyThread implements Thread::IRunnable interface
//----------------------------------------------------------------------------------------------------
class MyThread:
    public Thread::IRunnable
{
public:
    enum Action
    {
        Action_BailOut,
        Action_WatchSomeMovie,
        Action_ListenToMusic,
        Action_JustRelax,
        Action_Nothing,
    };

    // run is invoked once a task is created in the parent thread
    Void run()
    {
        // define the command this thread should perform
        //  the initial value is to do nothing
        Int command = Action_Nothing;

        // enter a loop which will be exited once this thread receives
        //  Action_BailOut command from the parent thread
        while(True)
        {
            try
            {
                // suspend (block) this thread until the parent thread sends an interrupt signal
                //  note that if the parent thread never sends an interrupt nor a cancel signals
                //  this thread will stay in suspended state indefinitely
                Thread::sleep();
            }
            catch(Thread::InterruptSignal signal)
            {
                // retrieve the interrupt code and treat it as a command sent from the parent thread
                command = signal.code();
            }

            // perform the specified action
            switch(command)
            {
                default:
                    Runtime::StdOut::fprintln(appText("Thread [%Lx] received an unknown command %d!"), Thread::id(), command);
                    break;

                case Action_WatchSomeMovie:
                    Runtime::StdOut::fprintln(appText("Thread [%Lx] is watching a movie"), Thread::id());
                    break;

                case Action_ListenToMusic:
                    Runtime::StdOut::fprintln(appText("Thread [%Lx] is listening to music"), Thread::id());
                    break;

                case Action_JustRelax:
                    Runtime::StdOut::fprintln(appText("Thread [%Lx] is relaxing"), Thread::id());
                    break;

                case Action_BailOut:
                    Runtime::StdOut::fprintln(appText("Thread [%Lx] is bailing out"), Thread::id());
                    return;
            }
        }
        // once this method returns this thread will end, and the joined (main) thread will continue
    }
};


// program entry point
//====================================================================================================
AppMain(args)
{
    Runtime::StdOut::fprintln(appText("Thread [%Lx] is the main thread"), Thread::id());

    // print the current time
    Runtime::StdOut::println(DateTime::now().format(appText("The time is %h:%m:%s.%u")));

    // create a worker thread
    MyThread thread;
    // start the worker thread
    Thread::Task task(&thread);

    // suspend main thread for 2 seconds
    Thread::sleep(2000);
    // tell the worker thread to go watch a movie
    task.interrupt(MyThread::Action_WatchSomeMovie);

    // suspend main thread for 0.5 seconds
    Thread::sleep(500);
    // tell the worker thread to go listen to some music
    task.interrupt(MyThread::Action_ListenToMusic);

    // suspend main thread for 1.5 seconds
    Thread::sleep(1500);
    // tell the worker thread to go on and relax
    task.interrupt(MyThread::Action_JustRelax);

    // suspend main thread for 0.5 seconds
    Thread::sleep(500);
    // tell the worker thread to bail out
    task.interrupt(MyThread::Action_BailOut);

    // suspend this thread until the worker task finishes
    task.join();

    // print the new time
    Runtime::StdOut::println(DateTime::now().format(appText("And now the time is %h:%m:%s.%u")));

    return 0;
}


/* EOF */