#ifndef SYSLIB_THREAD_HEADER
#define SYSLIB_THREAD_HEADER

#include <stl/auto_ptr.h>
#include <xtl/exception.h>
#include <xtl/functional_fwd>

namespace syslib
{

//forward declarations
struct CurrentThreadHolder;
class  Mutex;
class  ThreadManager;

struct cancel_thread_exception: virtual public xtl::exception {};

///////////////////////////////////////////////////////////////////////////////////////////////////
///Константы
///////////////////////////////////////////////////////////////////////////////////////////////////
const int THREAD_CANCELED_EXIT_CODE = -1; //код завершения сброшенной нити

///////////////////////////////////////////////////////////////////////////////////////////////////
///Приоритет нити
///////////////////////////////////////////////////////////////////////////////////////////////////
enum ThreadPriority
{
  ThreadPriority_Low,
  ThreadPriority_Normal,
  ThreadPriority_High
};

///////////////////////////////////////////////////////////////////////////////////////////////////
///Нить
///////////////////////////////////////////////////////////////////////////////////////////////////
class Thread
{
  friend struct CurrentThreadHolder;
  friend class ThreadManager;
  public:
    typedef size_t                threadid_t;
    typedef xtl::function<int ()> Function;
    
///////////////////////////////////////////////////////////////////////////////////////////////////
///Конструкторы / деструктор / присваивание
///////////////////////////////////////////////////////////////////////////////////////////////////    
    Thread  (const Thread&);
    Thread  (const Function& thread_function);
    Thread  (const char* name, const Function& thread_function);
    ~Thread ();

    Thread& operator = (const Thread&);
    
///////////////////////////////////////////////////////////////////////////////////////////////////
///Идентификатор нити
///////////////////////////////////////////////////////////////////////////////////////////////////
    threadid_t Id () const;

///////////////////////////////////////////////////////////////////////////////////////////////////
///Имя нити
///////////////////////////////////////////////////////////////////////////////////////////////////
    const char* Name () const;

///////////////////////////////////////////////////////////////////////////////////////////////////
///Установка приоритета нити
///////////////////////////////////////////////////////////////////////////////////////////////////
    void SetPriority (ThreadPriority thread_priority);

///////////////////////////////////////////////////////////////////////////////////////////////////
///Установка маски процессоров
///////////////////////////////////////////////////////////////////////////////////////////////////
    void SetAffinity (size_t affinity);

///////////////////////////////////////////////////////////////////////////////////////////////////
///Отмена нити
///////////////////////////////////////////////////////////////////////////////////////////////////
    void Cancel ();

///////////////////////////////////////////////////////////////////////////////////////////////////
///Ожидание завершения нити
///////////////////////////////////////////////////////////////////////////////////////////////////
    int Join (); //return exit code

///////////////////////////////////////////////////////////////////////////////////////////////////
///Получение текущей нити
///////////////////////////////////////////////////////////////////////////////////////////////////
    static Thread     GetCurrent         ();
    static threadid_t GetCurrentThreadId ();
    
///////////////////////////////////////////////////////////////////////////////////////////////////
///Установка точки отмена нити
///////////////////////////////////////////////////////////////////////////////////////////////////
    static void TestCancel ();

///////////////////////////////////////////////////////////////////////////////////////////////////
///Обмен
///////////////////////////////////////////////////////////////////////////////////////////////////
    void Swap (Thread&);

  private:
    struct Impl;

    Thread (Impl*);

  private:
    Impl* impl;
};

///////////////////////////////////////////////////////////////////////////////////////////////////
///Обмен
///////////////////////////////////////////////////////////////////////////////////////////////////
void swap (Thread&, Thread&);

}

#endif
