text: //============================================================================
  // Name        : main.cpp
  // Author      : Artak Avetyan
  // Version     :
  // Copyright   : Aregtech (c) 2021
  // Description : This project demonstrates use of logging (tracing). The 
  //               logging requires source code compilation with ENABLE_TRACES
  //               preprocessor directive to enable logging macro. It as well
  //               requires log enabling in the configuration file (by default 
  //               "./config/log.init" file). If there is no configuration file,
  //               the logging can be forced to be enabled to apply default
  //               logging settings.
  // 
  //               In this example enabling logging is forced and logging uses
  //               default settings.
  //============================================================================
  
  #include "areg/base/GEGlobal.h"
  #include "areg/base/Thread.hpp"
  #include "areg/base/IEThreadConsumer.hpp"
  #include "areg/trace/GETrace.h"
  
  #include <string_view>
  
  #ifdef WINDOWS
      #pragma comment(lib, "areg.lib")
  #endif // WINDOWS
  
  //////////////////////////////////////////////////////////////////////////
  // HelloThread class declaration
  //////////////////////////////////////////////////////////////////////////
  /**
   * \brief   A thread to run and output message
   */
  class HelloThread   : public    Thread
                      , protected IEThreadConsumer
  {
  //////////////////////////////////////////////////////////////////////////
  // Internal constants
  //////////////////////////////////////////////////////////////////////////
      /**
       * \brief   The thread name;
       */
      static constexpr std::string_view THREAD_NAME { "HelloThread" };
  
  //////////////////////////////////////////////////////////////////////////
  // Constructor / Destructor
  //////////////////////////////////////////////////////////////////////////
  public:
      HelloThread( void );
  
      virtual ~HelloThread( void ) = default;
  
  protected:
  
  /************************************************************************/
  // IEThreadConsumer interface overrides
  /************************************************************************/
  
      /**
       * \brief   This callback function is called from Thread object, when it is
       *          running and fully operable. If thread needs run in loop, the loop
       *          should be implemented here. When consumer exits this function,
       *          the thread will complete work. To restart thread running,
       *          createThread() method should be called again.
       **/
      virtual void onThreadRuns( void ) override;
  
  //////////////////////////////////////////////////////////////////////////
  // Hidden calls
  //////////////////////////////////////////////////////////////////////////
  private:
      inline HelloThread & self( void );
  };
  
  //////////////////////////////////////////////////////////////////////////
  // HelloThread implementation
  //////////////////////////////////////////////////////////////////////////
  
  
  DEF_TRACE_SCOPE(main_HelloThread_HelloThread);
  DEF_TRACE_SCOPE(main_HelloThread_onThreadRuns);
  
  HelloThread::HelloThread( void )
      : Thread            ( self(), HelloThread::THREAD_NAME.data() )
      , IEThreadConsumer  ( )
  {
      TRACE_SCOPE(main_HelloThread_HelloThread);
      TRACE_DBG("Initialized thread [ %s ]", HelloThread::THREAD_NAME.data());
  }
  
  inline HelloThread & HelloThread::self( void )
  {
      return (*this);
  }
  
  void HelloThread::onThreadRuns( void )
  {
      TRACE_SCOPE(main_HelloThread_onThreadRuns);
  
      TRACE_WARN("The thread [ %s ] runs, going to output messages ...", getName().getString());
      TRACE_INFO("!!!Hello World!!!");
      TRACE_DBG("!!!Hello Tracing!!!");
  }
  
  //////////////////////////////////////////////////////////////////////////
  // Demo
  //////////////////////////////////////////////////////////////////////////
  DEF_TRACE_SCOPE(main_main);
  /**
   * \brief   Demo to create and destroy thread.
   */
  int main()
  {
      printf("Initializing and running tracing.\n");
      // Force to start logging. See outputs log files in appropriate "logs" subfolder.
      // To change the configuration and use dynamic logging, use macro TRACER_START_LOGGING
      // and specify the logging configuration file, where you can change logging format,
      // filter logging priority and scopes.
      TRACER_CONFIGURE_AND_START(nullptr);
  
      do
      {
          // set this part of code in a block (for example, 'do-while' block).
          // otherwise, the logs will not be visible, since in the time when
          // scope is initialized, the logging is not active yet.
          TRACE_SCOPE(main_main);
  
          // declare thread object.
          TRACE_DBG("Starting Hello World thread");
          HelloThread aThread;
  
          // create and start thread, wait until it is started.
          aThread.createThread(NECommon::WAIT_INFINITE);
          TRACE_DBG("[ %s ] to create thread [ %s ]", aThread.isValid() ? "SUCCEEDED" : "FAILED", aThread.getName().getString());
  
          // stop and destroy thread, clean resources. Wait until thread ends.
          TRACE_INFO("Going to stop and destroy [ %s ] thread.", aThread.getName().getString());
          aThread.destroyThread(NECommon::WAIT_INFINITE);
  
      } while (false);
  
      // Stop logging.
      TRACER_STOP_LOGGING();
  
      printf("Completed to run tracing.\n");
  
      return 0;
  }
  