класс-поток
От: k732  
Дата: 05.08.06 12:04
Оценка:
подскажите пожалуйста как создать класс, который на вход принимает функцию или метод класса и запускает, останавливает поток. Тоесть некая обертка над потоком.

Если не сложно, то желательно с boost::thread
Re: класс-поток
От: g_i  
Дата: 05.08.06 12:44
Оценка:
Здравствуйте, k732, Вы писали:

Что-нибудь навроде


class WaitableObject
{
public:
  virtual void Wait(unsigned period) = 0;

protected:
  WaitableObject(){}
  virtual ~WaitableObject(){}

private:
  WaitableObject(const WaitableObject&);
  WaitableObject& operator =(const WaitableObject&);
};

typedef void* ThreadFuncArgType;
typedef void (*ThreadFuncType)(void*);

class Thread: public WaitableObject
{
public:
  virtual ~Thread();

  virtual Thread* Execute() = 0;
  virtual Thread* Execute(ThreadFuncType fn, ThreadFuncArgType arg) = 0;

  static Thread* CreateThread();
  static Thread* CreateThread(ThreadFuncType fn, ThreadFuncArgType arg);
  template <class T, void (T::*fn)()>
    static Thread* CreateThread(T* obj);

protected:
  Thread();

private:
  Thread(const Thread&);
  Thread& operator =(const Thread&);
};

//////////////////////////////////////////////////////////////////////////
// helpers

template <class T, void (T::*fn)()>
  void ThreadFuncImpl(void* arg)
{
  T* instance = reinterpret_cast<T*>(arg);
  (instance->*fn)();
}

#define CREATETHREAD(klass, method, object)\
Thread::CreateThread(ThreadFuncImpl<klass, klass::method>, object)

#define CREATETHREAD_EXECUTE(klass, object, method)\
CREATETHREAD(klass, method, object)->Execute()

#define CREATETHREAD_EXECUTE_WAIT(klass, object, method)\
CREATETHREAD_EXECUTE(klass, method, object)->Wait()


Имплементация очевидная.

Используется тоже понятно как:


void fn()
{
  class A
  {
  public:
    void Do(){}
  };

  CREATETHREAD_EXECUTE_WAIT(A, Do, new A); 
}
Re[2]: класс-поток
От: g_i  
Дата: 05.08.06 13:28
Оценка:
Здравствуйте, g_i, Вы писали:

g_i>Здравствуйте, k732, Вы писали:


g_i>Что-нибудь навроде


Только шаблонный метод не нужен.. так, для путаницы.
Re[2]: класс-поток
От: k732  
Дата: 05.08.06 15:59
Оценка:
Здравствуйте, g_i, Вы писали:

g_i>Здравствуйте, k732, Вы писали:


g_i>Что-нибудь навроде



тоесть на сколько я понял
1.Thread хочет на вход функцию
void (*func)(void *)
2.Нужно наследоваться от Thread и перекрывать Execute

но тогда у одного класса может быть только один поток

а хотелось бы, чтоб этому классу можно мыло натровить любую функцию
как
void (*func)(void *)
так и
void Class::func (void *)

более того — хотелось бы чтоб это было внутри класса

например

void func1 (void *){...}
Thread thread1 (func1);
thread1.start();
...
thread.stop();


и для класса

class Some {
private:
    void func2 (void *);    
    void func3 (void *);
    Thread thread2;
    Thread thread3;


public :
    Some : thread2(&func2, this), thread3 (&func3, this)
    {
        thread2.start();
        thread3.start();
    }
    ~Some
    {
        thread2.stop();
        thread3.stop();
    }
}


тоесть еще хотелось бы чтоб Thread работал и с функциями и с методами классов (очевидно для этого ему нужен будет класс, который инкапсулирует в себе эти возможности — в идеале бы
чтоб класс был шаблонный и можно было бы задавать разные аргументы и выходные параметры
Re[3]: класс-поток
От: _Dreamer Россия  
Дата: 07.08.06 02:30
Оценка:
Здравствуйте, k732, Вы писали:

K>тоесть на сколько я понял

K>1.Thread хочет на вход функцию
K>void (*func)(void *)
K>2.Нужно наследоваться от Thread и перекрывать Execute

K>но тогда у одного класса может быть только один поток


K>а хотелось бы, чтоб этому классу можно мыло натровить любую функцию

K>как
K>void (*func)(void *)
K>так и
K>void Class::func (void *)

K>тоесть еще хотелось бы чтоб Thread работал и с функциями и с методами классов (очевидно для этого ему нужен будет класс, который инкапсулирует в себе эти возможности — в идеале бы

K>чтоб класс был шаблонный и можно было бы задавать разные аргументы и выходные параметры

судя по описанию, Вам нужно взять boost::function и наслаждаться жизнью
дока на boost::function
Re[4]: класс-поток
От: k732  
Дата: 07.08.06 05:14
Оценка:
Здравствуйте, _Dreamer, Вы писали:

K>>тоесть еще хотелось бы чтоб Thread работал и с функциями и с методами классов (очевидно для этого ему нужен будет класс, который инкапсулирует в себе эти возможности — в идеале бы

K>>чтоб класс был шаблонный и можно было бы задавать разные аргументы и выходные параметры

_D>судя по описанию, Вам нужно взять boost::function и наслаждаться жизнью

_D>дока на boost::function

ну его boost::function можно использовать например внутри класса-функции, который идет на вход классу-потоку

или Вы имели ввиду что-то другое ?

может boost::function + boost::thread + boost::bind?
Re[3]: класс-поток
От: g_i  
Дата: 07.08.06 06:23
Оценка:
Ну ты еще раз внимательно посмотри. Там все так и есть. Только это абстрактный класс.
Наследоваться не нужно — вернее, нужно класс имплементации написать (скажем, в ThreadImpl::Execute должна зваться _beginthreadex) )). Или убери virtual из объявлеиня функций, и сделай его классом реализации. Добавь шаблонный конструктор или шаблонный Execute, если не хочешь ThreadFuncImpl пользоваться.
Re[5]: класс-поток
От: Аноним  
Дата: 07.08.06 07:28
Оценка:
Здравствуйте, k732, Вы писали:

K>>>тоесть еще хотелось бы чтоб Thread работал и с функциями и с методами классов (очевидно для этого ему нужен будет класс, который инкапсулирует в себе эти возможности — в идеале бы

K>>>чтоб класс был шаблонный и можно было бы задавать разные аргументы и выходные параметры

_D>>судя по описанию, Вам нужно взять boost::function и наслаждаться жизнью

_D>>дока на boost::function

K>ну его boost::function можно использовать например внутри класса-функции, который идет на вход классу-потоку


K>или Вы имели ввиду что-то другое ?


Наверно в объект boost::function (функтор) надо запихнуть искомый вызов функции/класса при создании (при этом функтор должен создаваься динамически), после чего функтор передается в класс потока, который его уже асинхронно обрабатывает (т.е. исполняет в нужное время и внужном месте)
Re[5]: класс-поток
От: _Dreamer Россия  
Дата: 07.08.06 07:34
Оценка:
Здравствуйте, k732, Вы писали:

K>ну его boost::function можно использовать например внутри класса-функции, который идет на вход классу-потоку

K>или Вы имели ввиду что-то другое ?

ну да, я об этом.

K>может boost::function + boost::thread + boost::bind?

если Вам охота именно такую связку — можно придумать вот такое —
void my_print( void )
{
    printf( "hello\n" );
    Sleep( 5 * 1000 );
    printf( "world\n" );
}

struct some 
{
    void foo()
    {
        Sleep( 500 );
        printf( "from foo()\n" );
        Sleep( 3 * 1000 );
        printf( "end foo()\n" );
    }
};

struct thread_runner
{
    thread_runner( some * sm ) :
        th1( boost::bind( &some::foo, sm ) ),
        th2( &my_print )
    {
    }

    ~thread_runner()
    {
        th1.join();
        th2.join();
    }

    boost::thread th1;
    boost::thread th2;
};

int main( int argc, const char **argv )
{
    some s;
    {
        thread_runner runner( &s );
    }
    printf( "main\n" );
    
return 0;
}


thread_runner был придуман, чтобы избежать передачи this в boost::bind, как у Вас было —
class Some {
public :
    Some : thread2(&func2, this), thread3 (&func3, this) {...}
}

если мне склероз не изменяет, это UB.

если нужно иметь несколько потоков, то для этого вроде boost::thread_group придуман.
а вот остановку потока я бы сделал руками, внутри самой функции потока.
тоесть работать пока не было события, или отработать и ждать события, тут от задачи зависит.
Re[3]: класс-поток
От: zaufi Земля  
Дата: 07.08.06 07:56
Оценка:
Здравствуйте, k732, Вы писали:

K>тоесть еще хотелось бы чтоб Thread работал и с функциями и с методами классов (очевидно для этого ему нужен будет класс, который инкапсулирует в себе эти возможности — в идеале бы

K>чтоб класс был шаблонный и можно было бы задавать разные аргументы и выходные параметры

с этим то проблем как раз нет... желаемое тобой уже было реализовано (подозреваю даже не раз ...
тебе прежде всего стоит задуматься над реализацией cancellation pointов и вызовом дестукторов в насильственно убиваемых thread'ах
не сделав этого (в своей библе) ты имеешь 100%ный шанс (в коде сложнее чем multithreaded-hello-world) ОГРЕСТИ ПО ПОЛНОЙ ПРОГРАММЕ!
отладчик буит единственной прогой в которой ты буишь сидеть неделями и концов буит не найти...
Re[4]: класс-поток
От: k732  
Дата: 07.08.06 08:06
Оценка:
Здравствуйте, g_i, Вы писали:

g_i>Ну ты еще раз внимательно посмотри. Там все так и есть. Только это абстрактный класс.

g_i>Наследоваться не нужно — вернее, нужно класс имплементации написать (скажем, в ThreadImpl::Execute должна зваться _beginthreadex) )). Или убери virtual из объявлеиня функций, и сделай его классом реализации. Добавь шаблонный конструктор или шаблонный Execute, если не хочешь ThreadFuncImpl пользоваться.

тоесть функтор примерно так

class CallImpl {
private :
    CallImpl (const CallImpl&);
    CallImpl& operator = (const CallImpl&);

public :
    CallImpl () {;}
    virtual ~CallImpl () = 0 {;}
    virtual unsigned call (void* arg) const = 0;

};

class Caller : public CallImpl {
private :
    boost::function <unsigned (void *)> m_func;

    Caller (const Caller&);
    Caller& operator = (const Caller&);

public :
    explicit Caller (unsigned (*func)(void *)) : m_func (func) {;}

    template <class T>
    Caller (T& obj, unsigned (T::*func)(void *))
        : m_func (boost::bind (func, &obj, _1)) {;}

    virtual ~Caller () {;}
    virtual unsigned call (void* arg) const
    {
        return m_func (arg);
    }

};


я правильно понял ? только прототип функции поменять нельзя ?
а теперь я так понял его на вход потоку

class Thread {
private :
    boost::shared_ptr <CallerImpl> m_caller;

public :
    Thread (const boost::shared_ptr<Caller>& caller)
    ~Thread();
}


но как Thread-у ждать завершение потоковой функции. Можно INFINITE, но кто-то должет например взводить и сбразывать флаг по-которому
нужно выходить из функции.
Re[5]: класс-поток
От: zaufi Земля  
Дата: 07.08.06 08:09
Оценка:
Здравствуйте, k732, Вы писали:

K>но как Thread-у ждать завершение потоковой функции. Можно INFINITE, но кто-то должет например взводить и сбразывать флаг по-которому

K>нужно выходить из функции.

а это правильный вопрос!
подумай еще вот над чем: что буит если твой thread застранет в lock'e (на неопределенное (долгое) время) -- как ты его завершишь в таком случе?
Re[4]: класс-поток
От: k732  
Дата: 07.08.06 08:10
Оценка:
Здравствуйте, zaufi, Вы писали:

Z>Здравствуйте, k732, Вы писали:


K>>тоесть еще хотелось бы чтоб Thread работал и с функциями и с методами классов (очевидно для этого ему нужен будет класс, который инкапсулирует в себе эти возможности — в идеале бы

K>>чтоб класс был шаблонный и можно было бы задавать разные аргументы и выходные параметры

Z>с этим то проблем как раз нет... желаемое тобой уже было реализовано (подозреваю даже не раз ...

Z>тебе прежде всего стоит задуматься над реализацией cancellation pointов и вызовом дестукторов в насильственно убиваемых thread'ах
Z>не сделав этого (в своей библе) ты имеешь 100%ный шанс (в коде сложнее чем multithreaded-hello-world) ОГРЕСТИ ПО ПОЛНОЙ ПРОГРАММЕ!
Z>отладчик буит единственной прогой в которой ты буишь сидеть неделями и концов буит не найти...

а можно подробнее — где могут быть грабли
Re[6]: класс-поток
От: zaufi Земля  
Дата: 07.08.06 08:10
Оценка:
Здравствуйте, zaufi, Вы писали:

Z>Здравствуйте, k732, Вы писали:


K>>но как Thread-у ждать завершение потоковой функции. Можно INFINITE, но кто-то должет например взводить и сбразывать флаг по-которому

K>>нужно выходить из функции.

Z>а это правильный вопрос!

Z>подумай еще вот над чем: что буит если твой thread застранет в lock'e (на неопределенное (долгое) время) -- как ты его завершишь в таком случе?

ну и разумеется если ты его таки сможешь убить... вызовутся ли деструкторы для объектов там созданных ?
Re[5]: класс-поток
От: zaufi Земля  
Дата: 07.08.06 08:13
Оценка:
Здравствуйте, k732, Вы писали:

K>Здравствуйте, zaufi, Вы писали:


Z>>Здравствуйте, k732, Вы писали:


K>>>тоесть еще хотелось бы чтоб Thread работал и с функциями и с методами классов (очевидно для этого ему нужен будет класс, который инкапсулирует в себе эти возможности — в идеале бы

K>>>чтоб класс был шаблонный и можно было бы задавать разные аргументы и выходные параметры

Z>>с этим то проблем как раз нет... желаемое тобой уже было реализовано (подозреваю даже не раз ...

Z>>тебе прежде всего стоит задуматься над реализацией cancellation pointов и вызовом дестукторов в насильственно убиваемых thread'ах
Z>>не сделав этого (в своей библе) ты имеешь 100%ный шанс (в коде сложнее чем multithreaded-hello-world) ОГРЕСТИ ПО ПОЛНОЙ ПРОГРАММЕ!
Z>>отладчик буит единственной прогой в которой ты буишь сидеть неделями и концов буит не найти...

K>а можно подробнее — где могут быть грабли


ПОВСЮДУ! и в самых неожиданных местах
--
основная твоя проблема на данный момент: нада научиться безопастно убивать thread -- т.е. так чтоб при его убийстве у тя не было ликов (памяти, дескрипторов, и еще черт знает чего) -- вобщем не освобожденных ресурсов... чтобы при убийстве не оставалось залоченых mutexов (или иных объектов синхроницации)... и т.д. и т.п. (сам додумай
Re[7]: класс-поток
От: k732  
Дата: 07.08.06 08:13
Оценка:
Здравствуйте, zaufi, Вы писали:

Z>>а это правильный вопрос!

Z>>подумай еще вот над чем: что буит если твой thread застранет в lock'e (на неопределенное (долгое) время) -- как ты его завершишь в таком случе?

Z>ну и разумеется если ты его таки сможешь убить... вызовутся ли деструкторы для объектов там созданных ?


что-то Вы меня прям пугаете ... Ведь наверняка есть обкатанные методики
Re[8]: класс-поток
От: zaufi Земля  
Дата: 07.08.06 08:16
Оценка:
Здравствуйте, k732, Вы писали:

K>Здравствуйте, zaufi, Вы писали:


Z>>>а это правильный вопрос!

Z>>>подумай еще вот над чем: что буит если твой thread застранет в lock'e (на неопределенное (долгое) время) -- как ты его завершишь в таком случе?

Z>>ну и разумеется если ты его таки сможешь убить... вызовутся ли деструкторы для объектов там созданных ?


K>что-то Вы меня прям пугаете ... Ведь наверняка есть обкатанные методики


ты в стандарте денить видел описание того как вызываются деструкторы в thread'ах??
можешь не листать -- там этого НЕТ
как правило (исключения таки есть реализация threadов (системнозависимая надо заметить) НИЧЕГО не знает о твоих объектах С++!
Re[9]: класс-поток
От: k732  
Дата: 07.08.06 08:36
Оценка:
Здравствуйте, zaufi, Вы писали:

Z>ты в стандарте денить видел описание того как вызываются деструкторы в thread'ах??

Z>можешь не листать -- там этого НЕТ
Z>как правило (исключения таки есть реализация threadов (системнозависимая надо заметить) НИЧЕГО не знает о твоих объектах С++!

так как тогда правильно сделать
Re[6]: класс-поток
От: k732  
Дата: 07.08.06 09:00
Оценка:
Здравствуйте, zaufi, Вы писали:

Z>Здравствуйте, k732, Вы писали:


K>>Здравствуйте, zaufi, Вы писали:


Z>>>Здравствуйте, k732, Вы писали:


K>>>>тоесть еще хотелось бы чтоб Thread работал и с функциями и с методами классов (очевидно для этого ему нужен будет класс, который инкапсулирует в себе эти возможности — в идеале бы

K>>>>чтоб класс был шаблонный и можно было бы задавать разные аргументы и выходные параметры

Z>>>с этим то проблем как раз нет... желаемое тобой уже было реализовано (подозреваю даже не раз ...

Z>>>тебе прежде всего стоит задуматься над реализацией cancellation pointов и вызовом дестукторов в насильственно убиваемых thread'ах
Z>>>не сделав этого (в своей библе) ты имеешь 100%ный шанс (в коде сложнее чем multithreaded-hello-world) ОГРЕСТИ ПО ПОЛНОЙ ПРОГРАММЕ!
Z>>>отладчик буит единственной прогой в которой ты буишь сидеть неделями и концов буит не найти...

K>>а можно подробнее — где могут быть грабли


Z>ПОВСЮДУ! и в самых неожиданных местах

Z>--
Z>основная твоя проблема на данный момент: нада научиться безопастно убивать thread -- т.е. так чтоб при его убийстве у тя не было ликов (памяти, дескрипторов, и еще черт знает чего) -- вобщем не освобожденных ресурсов... чтобы при убийстве не оставалось залоченых mutexов (или иных объектов синхроницации)... и т.д. и т.п. (сам додумай


чесно говоря что-то я повелся на дискуссию

мне кажется что объект-поток должен отвечать только за корректный запуск и остановку потока. А "чтоб при его убийстве у тя не было ликов (памяти, дескрипторов, и еще черт знает чего)" это не его проблеммы, а проблеммы разработчика самой потоковой функции. Ведь системной _beginthreadex это тоже по барабану
Re[7]: класс-поток
От: zaufi Земля  
Дата: 07.08.06 09:22
Оценка:
Здравствуйте, k732, Вы писали:

K>мне кажется что объект-поток должен отвечать только за корректный запуск и остановку потока. А "чтоб при его убийстве у тя не было ликов (памяти, дескрипторов, и еще черт знает чего)" это не его проблеммы, а проблеммы разработчика самой потоковой функции. Ведь системной _beginthreadex это тоже по барабану


корректный с чьей точки зрения? -- системы наплевавшей на кучу объектов нуждающихся в нетривиальном удалении?

такой подход тоже имеет право на существование -- вот поэтому мне и не нравятся бустерные threadы (и многие другие библы по сути являющиеся wapperами (разной степени корявости) над системными Сишными функциями)

разумееца программер должен следить за кучей всего в своей проге (вместа того чтоб сконцентрироватся над задачей ) -- но это не наш way

в эру когда на нас надвигаются multicorные камни проги просто обязаны уметь пользовать все доступные CPU при этом если написание таких прог останется на текущем уровне то это буит ПРОГРАММЕРСКИЙ АД -- ну согласись кодя на С++ ты должен помнить и следить еще за такими тривиальными вещами как вызов деструкторов, отслеживать последовательность создания/удаления оберток над mutex/condition/thread в дадамемберах своего класса (помня о том кто и как это использует) -- все это требует упрощения!

я для себя лична выбрал way когда эти проблемы максимально переносятся с плеч прогаммера на плечи компилятора + threads implementation -- и на протяжении 3х лет успешно этим решением пользуюсь
Re[8]: класс-поток
От: k732  
Дата: 07.08.06 09:35
Оценка:
Здравствуйте, zaufi, Вы писали:

Z>Здравствуйте, k732, Вы писали:


K>>мне кажется что объект-поток должен отвечать только за корректный запуск и остановку потока. А "чтоб при его убийстве у тя не было ликов (памяти, дескрипторов, и еще черт знает чего)" это не его проблеммы, а проблеммы разработчика самой потоковой функции. Ведь системной _beginthreadex это тоже по барабану


Z>корректный с чьей точки зрения? -- системы наплевавшей на кучу объектов нуждающихся в нетривиальном удалении?


поймите же, что это лишь вспомогательный объект, который ничего не должен знать что происходит у него внутри потоковой функции. От лишь должен быть безопасен и нейстрален.

Z>такой подход тоже имеет право на существование -- вот поэтому мне и не нравятся бустерные threadы (и многие другие библы по сути являющиеся wapperами (разной степени корявости) над системными Сишными функциями)


ну я думаю вы согласитесь с тем, что даже обкатанный STL имеет множетсво органичений и рекомендаций. Обобщенный ког я считаю нельзя написать впринципе

Z>разумееца программер должен следить за кучей всего в своей проге (вместа того чтоб сконцентрироватся над задачей ) -- но это не наш way


Z>в эру когда на нас надвигаются multicorные камни проги просто обязаны уметь пользовать все доступные CPU при этом если написание таких прог останется на текущем уровне то это буит ПРОГРАММЕРСКИЙ АД -- ну согласись кодя на С++ ты должен помнить и следить еще за такими тривиальными вещами как вызов деструкторов, отслеживать последовательность создания/удаления оберток над mutex/condition/thread в дадамемберах своего класса (помня о том кто и как это использует) -- все это требует упрощения!


Z>я для себя лична выбрал way когда эти проблемы максимально переносятся с плеч прогаммера на плечи компилятора + threads implementation -- и на протяжении 3х лет успешно этим решением пользуюсь



ну я считаю, что вызов деструкторов в исключительной ситуации — это проблеммы самого C++ и компилятора. А в остальных случаях — разработчика (не считая платформ .NET и Java — где за это отвечает сборщик мусора)

Поэтому мне кажется — это не совсем суть темы


Что касается самого класса
1. Я правильно реализовал Impl — или может boost::function универсальнее передать прям в Thread
2. Кто отвечает за выход из потоковой функции (когда Thread просит его остановиться)- код разработчика, или сам Thread
Re[9]: класс-поток
От: zaufi Земля  
Дата: 07.08.06 10:06
Оценка:
Здравствуйте, k732, Вы писали:

K>>>мне кажется что объект-поток должен отвечать только за корректный запуск и остановку потока. А "чтоб при его убийстве у тя не было ликов (памяти, дескрипторов, и еще черт знает чего)" это не его проблеммы, а проблеммы разработчика самой потоковой функции. Ведь системной _beginthreadex это тоже по барабану


Z>>корректный с чьей точки зрения? -- системы наплевавшей на кучу объектов нуждающихся в нетривиальном удалении?


K>поймите же, что это лишь вспомогательный объект, который ничего не должен знать что происходит у него внутри потоковой функции. От лишь должен быть безопасен и нейстрален.


чего уж тут не понятного -- враппер он и есь враппер
дык о какой безопастности threadного враппера мы говорим? -- он нарушает все что только можно нарушить в C++ -- начиная от безопастности типов и заканчивая exceptions safety


Z>>такой подход тоже имеет право на существование -- вот поэтому мне и не нравятся бустерные threadы (и многие другие библы по сути являющиеся wapperами (разной степени корявости) над системными Сишными функциями)


K>ну я думаю вы согласитесь с тем, что даже обкатанный STL имеет множетсво органичений и рекомендаций. Обобщенный ког я считаю нельзя написать впринципе


безусловно органичения на типы в STL есть -- но эти ограничения всеже позволяют писать довольно genericовые алгоритмы -- и думаю нет смысла спорить что STLный код можно считать высокореюзабельным (это следствие genericoвости

в случае с threadами все тоже самое -- можно постоянно изобретать велосипеды сращивая несращиваемое (я про threads + C++) делая каждый раз новое customное решение или попытаться заgeneralizить этот код и реюзать -- второе разумеется сложнее

Z>>разумееца программер должен следить за кучей всего в своей проге (вместа того чтоб сконцентрироватся над задачей ) -- но это не наш way



K>ну я считаю, что вызов деструкторов в исключительной ситуации — это проблеммы самого C++ и компилятора. А в остальных случаях — разработчика (не считая платформ .NET и Java — где за это отвечает сборщик мусора)


мы про исключительные ситуации еще и не говорили!
кроме исключительных ситуаций когда компилятор обязан вызвать деструктор есть еще и такие простые вещи как выход переменной из области видимости


K>Что касается самого класса

K>1. Я правильно реализовал Impl — или может boost::function универсальнее передать прям в Thread
передать то можно и эот даже хорошо! но есть одна маленькая проблемка: в функтор еще нужно передеать параметры -- подумай вот над чем:
int foo(int, const std::string&) { ... }
...
thread_wrapper thr(&foo);
thr.start(10, "sample string");

как реализовать start?

K>2. Кто отвечает за выход из потоковой функции (когда Thread просит его остановиться)- код разработчика, или сам Thread

ну это зависит от реализации -- причем ТВОЕЙ

постарайся ответить для себя вот еще на какой вопрос:
void my_threaded_function(...)
{
    ...
    MyMegaObjectWithDestructor obj(...);
    some_mutex.lock();
    ...
    some_mutex.unlock();
    ...
}

представь что получить lock неудается долгое время и тут в другом thread'e тебе приспичивает сдалать thr.join()...
какаябы обертка не была над mutex гдето это все равно должно уперется в системный вызов зависящий от реализации, который будучи cancellation pointом замочит твой thread без вопросов и управление туда попросту больше не вернется! -- в результате имеем wrapper над mutexом в непонятном состоянии и неубитый obj...
Re[10]: класс-поток
От: zaufi Земля  
Дата: 07.08.06 10:11
Оценка:
Здравствуйте, k732, Вы писали:

K>Здравствуйте, zaufi, Вы писали:


Z>>ты в стандарте денить видел описание того как вызываются деструкторы в thread'ах??

Z>>можешь не листать -- там этого НЕТ
Z>>как правило (исключения таки есть реализация threadов (системнозависимая надо заметить) НИЧЕГО не знает о твоих объектах С++!

K>так как тогда правильно сделать

постаряйся сначала найти хоть какоенить решение -- а правильное оно или нет покажет опыт его применения
Re[10]: класс-поток
От: k732  
Дата: 07.08.06 12:16
Оценка:
Здравствуйте, zaufi, Вы писали:


K>>Что касается самого класса

K>>1. Я правильно реализовал Impl — или может boost::function универсальнее передать прям в Thread
Z>передать то можно и эот даже хорошо! но есть одна маленькая проблемка: в функтор еще нужно передеать параметры -- подумай вот над чем:
Z>
Z>int foo(int, const std::string&) { ... }
Z>...
Z>thread_wrapper thr(&foo);
Z>thr.start(10, "sample string");
Z>

Z>как реализовать start?

если использовать класс который я привел

class Caller : public ICaller {
private :
    boost::function <unsigned (void *)> m_func;

    Caller (const Caller&);
    Caller& operator = (const Caller&);

public :
    template <class T>
    Caller (T& obj, unsigned (T::*func)(void *))
        : m_func (boost::bind (func, &obj, _1)) {;}
    explicit Caller (unsigned (*func)(void *)) : m_func (func) {;}
    virtual ~Caller () {;}
    virtual unsigned call (void* arg) const
    {
        return m_func (arg);
    }

};


то тогда

class Thread : virtual public BaseThread {
private:

        void* m_arg;
    boost::shared_ptr<ICaller> m_caller;

    Thread (const Thread&);
    Thread& operator = (const Thread&);

    virtual unsigned execute (void)
        {
            return m_caller->call (m_arg);
        }

public:
    template <class T>
    Thread (T& obj, unsigned (T::*func)(void *), void* arg)
        : m_caller (new Caller (obj, func)), m_arg (arg) {;}
    virtual ~Thread ();
};


только уйти от
unsigned (*func)(void *)
уже не получится. Но впринципе и этого пока достаточно (через void* можно многое отдать



K>>2. Кто отвечает за выход из потоковой функции (когда Thread просит его остановиться)- код разработчика, или сам Thread

Z>ну это зависит от реализации -- причем ТВОЕЙ

Z>постарайся ответить для себя вот еще на какой вопрос:

Z>
Z>void my_threaded_function(...)
Z>{
Z>    ...
Z>    MyMegaObjectWithDestructor obj(...);
Z>    some_mutex.lock();
Z>    ...
Z>    some_mutex.unlock();
Z>    ...
Z>}
Z>

Z>представь что получить lock неудается долгое время и тут в другом thread'e тебе приспичивает сдалать thr.join()...
Z>какаябы обертка не была над mutex гдето это все равно должно уперется в системный вызов зависящий от реализации, который будучи cancellation pointом замочит твой thread без вопросов и управление туда попросту больше не вернется! -- в результате имеем wrapper над mutexом в непонятном состоянии и неубитый obj...


я думаю если зделать так

template <class BaseLock>
class Locker {

private :
    const BaseLock& m_lock;

    Locker (const Locker&);
    Locker operator = (const Locker&);

public :
    explicit Locker (const BaseLock& lock) : m_lock (lock)
    {
        m_lock.lock();
    }
    ~Locker ()
    {
        m_lock.unlock();
    }

};

class Mutex : public BaseLock {
private :
    HANDLE m_hMutex;

    Mutex (const Mutex&);
    Mutex& operator = (const Mutex&);

public :
    virtual bool lock (void) const;
    virtual bool unlock (void) const;

};


и тогда

void my_threaded_function(...)
{
    ...
    MyMegaObjectWithDestructor obj(...);
    Locker<Mutex> lock (m_mutex);
    ...
}



то проблемма снимется если правда поток не terminated
Re[11]: класс-поток
От: k732  
Дата: 07.08.06 12:18
Оценка:
Здравствуйте, zaufi, Вы писали:

Z>Здравствуйте, k732, Вы писали:


K>>Здравствуйте, zaufi, Вы писали:


Z>>>ты в стандарте денить видел описание того как вызываются деструкторы в thread'ах??

Z>>>можешь не листать -- там этого НЕТ
Z>>>как правило (исключения таки есть реализация threadов (системнозависимая надо заметить) НИЧЕГО не знает о твоих объектах С++!

K>>так как тогда правильно сделать

Z>постаряйся сначала найти хоть какоенить решение -- а правильное оно или нет покажет опыт его применения

решение было, но встала проблемма ожидания завершения потока в деструкторе порожденного класса, если он сам в базовом классе

тоесть проблемма вызова виртуальных функций из конструктора и деструктора
Re[11]: класс-поток
От: zaufi Земля  
Дата: 07.08.06 12:40
Оценка:
Здравствуйте, k732, Вы писали:


K>только уйти от

K>unsigned (*func)(void *)
K>уже не получится. Но впринципе и этого пока достаточно (через void* можно многое отдать

и это говорит тот кто мечтает о мифической "безопастности" своей обертки!!?
--
ты прости мя за прямоту конечно (ничо личного ) -- но ты нагородил такой overhead вокруг threadов и недобился НИКАКОГО СУЩЕСТВЕННОГО улучшения по сравнению с сишным API! И даже более того внес кучу ограничений заставляющих пользователя твоего класса делать противоестественные вещи


K>я думаю если зделать так


K>
K>void my_threaded_function(...)
K>{
K>    ...
K>    MyMegaObjectWithDestructor obj(...);
K>    Locker<Mutex> lock (m_mutex);
K>    ...
K>}
K>



K>то проблемма снимется если правда поток не terminated


никто никкуда не снимается! добавление еще бльшего overhead'a не отменяет вызов системнозависимого lock(&mutex) -- ты просто убрал его с глаз долой (закопав в очередной уровень оберток) и думаешь что проблема решена?
Re[12]: класс-поток
От: k732  
Дата: 07.08.06 12:57
Оценка:
Здравствуйте, zaufi, Вы писали:


Z>и это говорит тот кто мечтает о мифической "безопастности" своей обертки!!?

Z>--
Z>ты прости мя за прямоту конечно (ничо личного ) -- но ты нагородил такой overhead вокруг threadов и недобился НИКАКОГО СУЩЕСТВЕННОГО улучшения по сравнению с сишным API! И даже более того внес кучу ограничений заставляющих пользователя твоего класса делать противоестественные вещи


ну на самом деле этот клас нужен просто для удобства. Внутри себя естественно он сожержит WinAPI функции.

K>>я думаю если зделать так


K>>
K>>void my_threaded_function(...)
K>>{
K>>    ...
K>>    MyMegaObjectWithDestructor obj(...);
K>>    Locker<Mutex> lock (m_mutex);
K>>    ...
K>>}
K>>



K>>то проблемма снимется если правда поток не terminated


Z>никто никкуда не снимается! добавление еще бльшего overhead'a не отменяет вызов системнозависимого lock(&mutex) -- ты просто убрал его с глаз долой (закопав в очередной уровень оберток) и думаешь что проблема решена?



наверное я тогда не совсем понял что Вы мы имеете ввиду под безопасностью. Я понимаю это как откат в предыдущее состояние.
в приведенном примере деструктор всегда будет вызван, а значит mutex разлочен
Re[13]: класс-поток
От: zaufi Земля  
Дата: 07.08.06 13:09
Оценка:
Здравствуйте, k732, Вы писали:

K>Здравствуйте, zaufi, Вы писали:


Z>>и это говорит тот кто мечтает о мифической "безопастности" своей обертки!!?

Z>>--
Z>>ты прости мя за прямоту конечно (ничо личного ) -- но ты нагородил такой overhead вокруг threadов и недобился НИКАКОГО СУЩЕСТВЕННОГО улучшения по сравнению с сишным API! И даже более того внес кучу ограничений заставляющих пользователя твоего класса делать противоестественные вещи

K>ну на самом деле этот клас нужен просто для удобства. Внутри себя естественно он сожержит WinAPI функции.


тотвоему это "удобно" заставлять юзера наследоваться от какогото там интерфейса провайдя странную функцию первые действия которой всегда заключаются в вытаскивании неизвестно чего (и сколько) из воидного поинтера? и это все только лишь для того чтоб скрыть (инкапсулировать) 1(!!!) параметр (thread handler) и введя объекты туда где и без них все сложно ???

K>наверное я тогда не совсем понял что Вы мы имеете ввиду под безопасностью. Я понимаю это как откат в предыдущее состояние.

K>в приведенном примере деструктор всегда будет вызван, а значит mutex разлочен



интересно ктойта тебе пообещал вызвать деструктор??
твой thread умрет (!!) еще в конструкторе твоего Locker'a! -- и как уже было сказано не получит управления в зад (чтобы вызвать какиебы то ни было деструкторы!
Re[10]: класс-поток
От: zaufi Земля  
Дата: 07.08.06 13:10
Оценка:
Здравствуйте, k732, Вы писали:

K>так как тогда правильно сделать


постараюсь описать тебе как это могло бы быть:

[list]
  • threadом можно сделать любую пользовательскую функцию
    
    int foo(int, const std::string&, double) {...}
    
    class some_class
    {
        ...
        void bar() {...}
    };
    
    int main(void)
    {
        thread<int(int, const std::string&, double)> foo_thr(&foo);
        foo_thr.spawn(10, "my_string", 3.14);
        ...
        int foo_result = foo_thr.join();
        ...
        thread<void(some_class* const)> bar_thr(&some_class::bar);
        some_class s;
        bar_thr.spawn(&s);
        ...
    }
    -- не нужно ограничивать юзеру свободу в этом и заставлять его чтото делать (например наследовать чтолибо) -- это на сам деле излишне
  • проблемы с убиением рашаются если суметь преобразовать событие убиения в exception вылетающий в targetном thread'e:
    void threded_func(...)
    {
        try
        {
            MyMegaObjectWithDestructor obj(...);
            ...
        }
        catch (const thread_exception::thread_canceled&)
        {
            // это значит что нас вежливо (пока) просят умереть
            // если не делать ничего то все само собой поуничтожается... :)
            // просто выходим из функции...
        }
    }
  • Re[11]: класс-поток
    От: k732  
    Дата: 07.08.06 13:26
    Оценка:
    Здравствуйте, zaufi, Вы писали:

    Z>Здравствуйте, k732, Вы писали:


    K>>так как тогда правильно сделать


    Z>постараюсь описать тебе как это могло бы быть:


    Z>[list]

    Z>
  • threadом можно сделать любую пользовательскую функцию
    
    Z>int foo(int, const std::string&, double) {...}
    
    Z>class some_class
    Z>{
    Z>    ...
    Z>    void bar() {...}
    Z>};
    
    Z>int main(void)
    Z>{
    Z>    thread<int(int, const std::string&, double)> foo_thr(&foo);
    Z>    foo_thr.spawn(10, "my_string", 3.14);
    Z>    ...
    Z>    int foo_result = foo_thr.join();
    Z>    ...
    Z>    thread<void(some_class* const)> bar_thr(&some_class::bar);
    Z>    some_class s;
    Z>    bar_thr.spawn(&s);
    Z>    ...
    Z>}
    
    тоесть не нужны нафиг никакие обертки - boost::thread все решает ?
    
    Z>
    -- не нужно ограничивать юзеру свободу в этом и заставлять его чтото делать (например наследовать чтолибо) -- это на сам деле излишне
    Z>
  • проблемы с убиением рашаются если суметь преобразовать событие убиения в exception вылетающий в targetном thread'e:
    Z>void threded_func(...)
    Z>{
    Z>    try
    Z>    {
    Z>        MyMegaObjectWithDestructor obj(...);
    Z>        ...
    Z>    }
    Z>    catch (const thread_exception::thread_canceled&)
    Z>    {
    Z>        // это значит что нас вежливо (пока) просят умереть
    Z>        // если не делать ничего то все само собой поуничтожается... :)
    Z>        // просто выходим из функции...
    Z>    }
    Z>}
    Z>


    что-то не совсем понял. Но что-то очень похоже на .NET Thread, для которого чтоб остановить выбрасывают исключение.
    Можно здесь подробнее немного
  • Re[14]: класс-поток
    От: k732  
    Дата: 07.08.06 13:32
    Оценка:
    Здравствуйте, zaufi, Вы писали:

    Z>Здравствуйте, k732, Вы писали:


    K>>Здравствуйте, zaufi, Вы писали:


    Z>>>и это говорит тот кто мечтает о мифической "безопастности" своей обертки!!?

    Z>>>--
    Z>>>ты прости мя за прямоту конечно (ничо личного ) -- но ты нагородил такой overhead вокруг threadов и недобился НИКАКОГО СУЩЕСТВЕННОГО улучшения по сравнению с сишным API! И даже более того внес кучу ограничений заставляющих пользователя твоего класса делать противоестественные вещи

    K>>ну на самом деле этот клас нужен просто для удобства. Внутри себя естественно он сожержит WinAPI функции.


    Z>тотвоему это "удобно" заставлять юзера наследоваться от какогото там интерфейса провайдя странную функцию первые действия которой всегда заключаются в вытаскивании неизвестно чего (и сколько) из воидного поинтера? и это все только лишь для того чтоб скрыть (инкапсулировать) 1(!!!) параметр (thread handler) и введя объекты туда где и без них все сложно ???


    K>>наверное я тогда не совсем понял что Вы мы имеете ввиду под безопасностью. Я понимаю это как откат в предыдущее состояние.

    K>>в приведенном примере деструктор всегда будет вызван, а значит mutex разлочен

    Z>


    Z>интересно ктойта тебе пообещал вызвать деструктор??

    Z>твой thread умрет (!!) еще в конструкторе твоего Locker'a! -- и как уже было сказано не получит управления в зад (чтобы вызвать какиебы то ни было деструкторы!


    ну чесно говоря — это спорный вопрос. Если система захотела убить вообще весь процес — аминь (это уж Билл пусть заботиться о безопасности)

    а если это делают шаловливые руки разработчика — по рукам ему (Terminate просто настоятельно не рекомендуют вызывать)
    Re[12]: класс-поток
    От: zaufi Земля  
    Дата: 07.08.06 13:42
    Оценка:
    Здравствуйте, k732, Вы писали:

    K>тоесть не нужны нафиг никакие обертки — boost::thread все решает ?


    типа того! -- кроме того что это более кроссплатформенно чем твое доморощеное решение оно я думаю немнго более профессионально написано -- хотя как показывает баглист бустерный и не без грешков

    однако приводя пример я не имел вввввиду конкретно boost (если и получилоось какоето сходство с boost то это не нарочно! ) -- как я уже говорил boostерные threadы я не использую -- приведенный код следует рассмартивать как "псевдокод" весьма близкий к тому что хотелось бы видеть лично мне столкнись я с твоей проблемой...

    Z>>[/ccode] -- не нужно ограничивать юзеру свободу в этом и заставлять его чтото делать (например наследовать чтолибо) -- это на сам деле излишне

    Z>>
  • проблемы с убиением рашаются если суметь преобразовать событие убиения в exception вылетающий в targetном thread'e:
    Z>>void threded_func(...)
    Z>>{
    Z>>    try
    Z>>    {
    Z>>        MyMegaObjectWithDestructor obj(...);
    Z>>        ...
    Z>>    }
    Z>>    catch (const thread_exception::thread_canceled&)
    Z>>    {
    Z>>        // это значит что нас вежливо (пока) просят умереть
    Z>>        // если не делать ничего то все само собой поуничтожается... :)
    Z>>        // просто выходим из функции...
    Z>>    }
    Z>>}
    Z>>


    K>что-то не совсем понял. Но что-то очень похоже на .NET Thread, для которого чтоб остановить выбрасывают исключение.

    K>Можно здесь подробнее немного

    приведенный псевдокод выражает идею как можно было бы зарамсить проблему с cancellation pointами и вызовом деструкторов... (всякое сходство с чем быто ни было СЛУЧАЙНО -- я вааще под *nix все делаю и знать не знаю ничо про .net & etc )

    если быть побдробнее в данном месте то те нада разобраться с тем как обучить свой thread (в данном случае не класс а поток управления) понимать что пришло время умирать (обычно этого хотят другие (внешние по отношению к текущему) threadы) и выкидывать внутри себя исключение, таким образом программер сможет его поймать и поуничтожать все корректно... (ну или компилятор в большенстве случаем все сам сделает
  • Re[15]: класс-поток
    От: zaufi Земля  
    Дата: 07.08.06 13:58
    Оценка:
    Здравствуйте, k732, Вы писали:

    Z>>интересно ктойта тебе пообещал вызвать деструктор??

    Z>>твой thread умрет (!!) еще в конструкторе твоего Locker'a! -- и как уже было сказано не получит управления в зад (чтобы вызвать какиебы то ни было деструкторы!


    K>ну чесно говоря — это спорный вопрос. Если система захотела убить вообще весь процес — аминь (это уж Билл пусть заботиться о безопасности)


    ничо тут спорного нет -- ты видима не догоняешь тему -- попробуем в более жизненном примере рссмотреть происходящее:
    void worker_thread(...)
    {
        MyObjectWithDestructor obj(...);
        ...
        // в этой функции чтото долго и упорно вычисляется (или просто ктото притормаживает)
        // таким образом возникает timeout и worker_scheduler решает ее замочить...
        very_long_time_calculations_here();
        ...
    }
    
    void worker_scheduler(...)
    {
        while (ходим по списку запущеных обработчиков)
        {
            ...
            if (текущий обработчик задержатся с вычислениями)
                // убиваем голубчика! результат уже никому не нужен...
                worker_threads[i].join();
            ...
        }
    }

    тоесь када шедулер мочит worker_thread, тот находится гдето в глубине функции very_long_time_calculations_here() которая в процессе выполнения достигла cancellation point'a -- т.е. отдала управление ядру, и то видя что thread зашедулен на убиение (из worker_scheduler был вызван join) с чистой совестью убивает соответствующий entry в своих шедулерских табличках и УПС! -- твоего thread'а будто никада и не было! -- больше управление в него не вернется!!! ибо нет уже никакого thread'a! даже воспоминания о нем...
    --
    внимание вопрос... КТО ТУТ вызовет деструктор для obj (и прочих несчастных локеров-шмокеров & etc ???
    Re[16]: класс-поток
    От: k732  
    Дата: 07.08.06 14:18
    Оценка:
    Здравствуйте, zaufi, Вы писали:

    Z>Здравствуйте, k732, Вы писали:


    Z>>>интересно ктойта тебе пообещал вызвать деструктор??

    Z>>>твой thread умрет (!!) еще в конструкторе твоего Locker'a! -- и как уже было сказано не получит управления в зад (чтобы вызвать какиебы то ни было деструкторы!


    K>>ну чесно говоря — это спорный вопрос. Если система захотела убить вообще весь процес — аминь (это уж Билл пусть заботиться о безопасности)


    Z>ничо тут спорного нет -- ты видима не догоняешь тему -- попробуем в более жизненном примере рссмотреть происходящее:

    Z>
    Z>void worker_thread(...)
    Z>{
    Z>    MyObjectWithDestructor obj(...);
    Z>    ...
    Z>    // в этой функции чтото долго и упорно вычисляется (или просто ктото притормаживает)
    Z>    // таким образом возникает timeout и worker_scheduler решает ее замочить...
    Z>    very_long_time_calculations_here();
    Z>    ...
    Z>}
    
    Z>void worker_scheduler(...)
    Z>{
    Z>    while (ходим по списку запущеных обработчиков)
    Z>    {
    Z>        ...
    Z>        if (текущий обработчик задержатся с вычислениями)
    Z>            // убиваем голубчика! результат уже никому не нужен...
    Z>            worker_threads[i].join();
    Z>        ...
    Z>    }
    Z>}
    Z>

    Z>тоесь када шедулер мочит worker_thread, тот находится гдето в глубине функции very_long_time_calculations_here() которая в процессе выполнения достигла cancellation point'a -- т.е. отдала управление ядру, и то видя что thread зашедулен на убиение (из worker_scheduler был вызван join) с чистой совестью убивает соответствующий entry в своих шедулерских табличках и УПС! -- твоего thread'а будто никада и не было! -- больше управление в него не вернется!!! ибо нет уже никакого thread'a! даже воспоминания о нем...
    Z>--
    Z>внимание вопрос... КТО ТУТ вызовет деструктор для obj (и прочих несчастных локеров-шмокеров & etc ???


    ОК — убедил. Но мне не совсем понятно как можно поток заставить бросить исключение в своей потоковой функции.

    похоже нужно создавать новый топик по boost::thread (никогда не использовал)

    спасибо за продолжительную дискусcию
    Re[17]: класс-поток
    От: zaufi Земля  
    Дата: 07.08.06 14:27
    Оценка:
    Здравствуйте, k732, Вы писали:

    K>ОК — убедил. Но мне не совсем понятно как можно поток заставить бросить исключение в своей потоковой функции.


    а это также тема для отдельного топика
    Re[16]: класс-поток
    От: Sergey Россия  
    Дата: 07.08.06 15:55
    Оценка:
    > void worker_scheduler(...)
    > {
    > while (ходим по списку запущеных обработчиков)
    > {
    > ...
    > if (текущий обработчик задержатся с вычислениями)
    > // убиваем голубчика! результат уже никому не нужен...
    > worker_threads[i].join();
    > ...
    > }
    > }
    > [/ccode]
    > тоесь када шедулер мочит worker_thread, тот находится гдето в глубине функции very_long_time_calculations_here() которая в процессе выполнения достигла cancellation point'a -- т.е. отдала управление ядру, и то видя что thread зашедулен на убиение (из worker_scheduler был вызван join) с чистой совестью убивает соответствующий entry в своих шедулерских табличках и УПС! -- твоего thread'а будто никада и не было! -- больше управление в него не вернется!!! ибо нет уже никакого thread'a! даже воспоминания о нем...
    > --
    > внимание вопрос... КТО ТУТ вызовет деструктор для obj (и прочих несчастных локеров-шмокеров & etc ???

    Интересно, а join тут у вас обсуждается бустовый или какой-то другой? Просто boost::thread::join() под виндой никого не убивает, а ждет завершения потока. Та же ситуация, которую вы описали, равнозначна вызову виндовой TerminаteThread и в общем не должна возникать при отсутствии в программе фатальных ошибок. Не знаю, как под другими операционками, но под виндой так завершать нити не следует.
    Posted via RSDN NNTP Server 2.0
    Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
    Re[18]: класс-поток
    От: Kapone Украина  
    Дата: 07.08.06 16:14
    Оценка:
    Здравствуйте, zaufi, Вы писали:

    Z>Здравствуйте, k732, Вы писали:


    K>>ОК — убедил. Но мне не совсем понятно как можно поток заставить бросить исключение в своей потоковой функции.


    Z>а это также тема для отдельного топика


    Всё довольно очевидно — без callbacka тут не обойтись ну никак, просто потому что никак

    Я когда-то постил тему насчет как перенести однозадачное досовое приложение (допустим некий конвертор) на многопоточность.
    Думали мы думали и надумали то же, что и zaufi — а конкретно, бросать исключение из колбека, который вызывается для показания прогресса.
    Оказались и овцы целы, и волки сыты ... (касаемо удаления используемой памяти и тд)

    Как оказалось, довольно работоспособное решение, кроме некоторых тонких для винды моментов (если кому интересно, то тут
    Автор: Kapone
    Дата: 09.06.06
    ).

    Кроме того, с помощью такого вот многозадачного теста отловили баг catch(...).
    Вот так вот.
    ... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
    Re[17]: класс-поток
    От: Kapone Украина  
    Дата: 07.08.06 16:19
    Оценка:
    Здравствуйте, Sergey, Вы писали:

    S>Интересно, а join тут у вас обсуждается бустовый или какой-то другой? Просто boost::thread::join() под виндой никого не убивает, а ждет завершения потока. Та же ситуация, которую вы описали, равнозначна вызову виндовой TerminаteThread и в общем не должна возникать при отсутствии в программе фатальных ошибок. Не знаю, как под другими операционками, но под виндой так завершать нити не следует.


    Может недописано всё?
    У меня в доморошенном потоке в joine стоит некое разумное время завершения, после чего прога поток заверщает и ругается на мои кривые руки правда это токо в дебаг режиме ...
    ... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
    Re[18]: класс-поток
    От: Sergey Россия  
    Дата: 08.08.06 07:45
    Оценка:
    > S>Интересно, а join тут у вас обсуждается бустовый или какой-то другой? Просто boost::thread::join() под виндой никого не убивает, а ждет завершения потока. Та же ситуация, которую вы описали, равнозначна вызову виндовой TerminаteThread и в общем не должна возникать при отсутствии в программе фатальных ошибок. Не знаю, как под другими операционками, но под виндой так завершать нити не следует.
    >
    > Может недописано всё?
    > У меня в доморошенном потоке в joine стоит некое разумное время завершения, после чего прога поток заверщает и ругается на мои кривые руки правда это токо в дебаг режиме ...

    Чего не дописано? Под виндой нет ни одного безопасного способа остановить нить извне. Потому что никто не гарантирует, что при вызове той же TerminateThread операционка озаботится отпусканием захваченных этой нитью объектов синхронизации или выполнит еще какие-либо post mortem действия в контексте прерванной нити. Так что все там сделано правильно.
    Posted via RSDN NNTP Server 2.0
    Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
    Re[19]: класс-поток
    От: zaufi Земля  
    Дата: 08.08.06 08:05
    Оценка:
    Здравствуйте, Sergey, Вы писали:

    >> S>Интересно, а join тут у вас обсуждается бустовый или какой-то другой? Просто boost::thread::join() под виндой никого не убивает, а ждет завершения потока. Та же ситуация, которую вы описали, равнозначна вызову виндовой TerminаteThread и в общем не должна возникать при отсутствии в программе фатальных ошибок. Не знаю, как под другими операционками, но под виндой так завершать нити не следует.

    >>
    >> Может недописано всё?
    >> У меня в доморошенном потоке в joine стоит некое разумное время завершения, после чего прога поток заверщает и ругается на мои кривые руки правда это токо в дебаг режиме ...

    S>Чего не дописано? Под виндой нет ни одного безопасного способа остановить нить извне. Потому что никто не гарантирует, что при вызове той же TerminateThread операционка озаботится отпусканием захваченных этой нитью объектов синхронизации или выполнит еще какие-либо post mortem действия в контексте прерванной нити. Так что все там сделано правильно.


    PPL! читаем внимательно: все мои листинги в этом топике ПСЕВДОКОД таких вызовов и классов не существует! -- всем расслабица...

    ЗЫ: я и вправду немного ступил насчет join'a -- конечно же он не убивает thread... чтобы эстетам стало легче вообразите перед вызовом join'a такой псевдокод:
    ...
    thr.cancel();          // say 'DIE' to thread...
    thr.join();            // wait for thread death...
    ...
    Re[19]: класс-поток
    От: Kapone Украина  
    Дата: 08.08.06 08:07
    Оценка:
    Здравствуйте, Sergey, Вы писали:

    >> S>Интересно, а join тут у вас обсуждается бустовый или какой-то другой? Просто boost::thread::join() под виндой никого не убивает, а ждет завершения потока. Та же ситуация, которую вы описали, равнозначна вызову виндовой TerminаteThread и в общем не должна возникать при отсутствии в программе фатальных ошибок. Не знаю, как под другими операционками, но под виндой так завершать нити не следует.

    >>
    >> Может недописано всё?
    >> У меня в доморошенном потоке в joine стоит некое разумное время завершения, после чего прога поток заверщает и ругается на мои кривые руки правда это токо в дебаг режиме ...

    S>Чего не дописано? Под виндой нет ни одного безопасного способа остановить нить извне. Потому что никто не гарантирует, что при вызове той же TerminateThread операционка озаботится отпусканием захваченных этой нитью объектов синхронизации или выполнит еще какие-либо post mortem действия в контексте прерванной нити. Так что все там сделано правильно.


    Да никто и не говорит, что сделано неправильно.
    Меня не поняли
    Я просто сказал, что там может быть неполный код, вот и все.
    Насчет пост действий я тоже согласен, кроме объектов синхронизаций. Для некоторых (а конкретно для mutex-а) Windows гарантирует передачу ownership к одному из ожидающих объектов. Другой вопрос — а что же там в shared данных творится, но он выходит за пределы обсуждаемой темы

    С уважением.
    Роман.
    ... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
    Re[20]: класс-поток
    От: Sergey Россия  
    Дата: 08.08.06 08:17
    Оценка:
    > PPL! читаем внимательно: все мои листинги в этом топике ПСЕВДОКОД таких вызовов и классов не существует! -- всем расслабица...

    Т.е., мы обсуждаем код, который не может быть реализован?

    > ЗЫ: я и вправду немного ступил насчет join'a -- конечно же он не убивает thread... чтобы эстетам стало легче вообразите перед вызовом join'a такой псевдокод:
    > ...
    > thr.cancel();          // say 'DIE' to thread...
    > thr.join();            // wait for thread death...
    > ...
    >


    Как именно реализован cancel? Под виндой, естественно. И почему именно не будет вызван деструктор obj?
    Posted via RSDN NNTP Server 2.0
    Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
    Re[21]: класс-поток
    От: zaufi Земля  
    Дата: 08.08.06 08:34
    Оценка:
    Здравствуйте, Sergey, Вы писали:

    >> PPL! читаем внимательно: все мои листинги в этом топике ПСЕВДОКОД таких вызовов и классов не существует! -- всем расслабица...


    S>Т.е., мы обсуждаем код, который не может быть реализован?


    отчего же не может? но в рамках данного топика ДА -- этот код не существует... может быть пока аффтар топика его не напишет

    >> ЗЫ: я и вправду немного ступил насчет join'a -- конечно же он не убивает thread... чтобы эстетам стало легче вообразите перед вызовом join'a такой псевдокод:
    >> ...
    >> thr.cancel();          // say 'DIE' to thread...
    >> thr.join();            // wait for thread death...
    >> ...
    >>


    S>Как именно реализован cancel? Под виндой, естественно. И почему именно не будет вызван деструктор obj?


    давайте не буим скатываться до уровня операционок -- до сих пор мы поговорили об обобщенном подходе многих известных ОС к убийству threadов...

    и общая картина такова: большенству реализаций threadов накласть на то что происходит в убиваемом thread'e как только специальным API (TerminateThread/pthread_cancel/smth_else) запрошено убить когото -- тот умираит безвозвратно и все что было создано в контексте убитого thread'a превращается в leak...

    вот так в целом обстоит дело...
    поэтому если писать тупые врапперы скрывающие от их пользователя 1 параметр (thread id в том или ином виде) и подменяющие его "объектом" thread -- это не упрощает нелегкое дело написания multithreadных прог... какбы комуто наивно не казалось...

    мы тут попытались обсудить с какими проблемами придется столкнуться аффтору топика еси он хочет иметь не просто врапперы а нечто более интеллектуальное и призванное устранить некоторые известные проблемы в этой области... (точнее я пытался его на это подбить )
    Re[20]: класс-поток
    От: Sergey Россия  
    Дата: 08.08.06 08:42
    Оценка:
    > Насчет пост действий я тоже согласен, кроме объектов синхронизаций. Для некоторых (а конкретно для mutex-а) Windows гарантирует передачу ownership к одному из ожидающих объектов.

    Ни разу не встречал такой информации. Можно ссылку на источник? Хотя я имел в виду не мьютексы, а критические секции — "If the target thread owns a critical section, the critical section will not be released." Это из MSDN, из ремарок про TerminateThread. Еще там есть "If the target thread is allocating memory from the heap, the heap lock will not be released."
    Posted via RSDN NNTP Server 2.0
    Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
    Re[22]: класс-поток
    От: Sergey Россия  
    Дата: 08.08.06 09:06
    Оценка:
    >>> PPL! читаем внимательно: все мои листинги в этом топике ПСЕВДОКОД таких вызовов и классов не существует! -- всем расслабица...
    >
    > S>Т.е., мы обсуждаем код, который не может быть реализован?
    >
    > отчего же не может?

    Оттого, что под виндой данный код не может быть реализован (корректно реализован, естественно) в виду отсутствия гарантий операционной системы.

    >>> ЗЫ: я и вправду немного ступил насчет join'a -- конечно же он не убивает thread... чтобы эстетам стало легче вообразите перед вызовом join'a такой псевдокод:
    >>> ...
    >>> thr.cancel();          // say 'DIE' to thread...
    >>> thr.join();            // wait for thread death...
    >>> ...
    >>>

    >
    > S>Как именно реализован cancel? Под виндой, естественно. И почему именно не будет вызван деструктор obj?
    >
    > давайте не буим скатываться до уровня операционок -- до сих пор мы поговорили об обобщенном подходе многих известных ОС к убийству threadов...

    А давайте буим? Потому что конкретно под виндой ваш подход не работает.

    >

    > и общая картина такова: большенству реализаций threadов накласть на то что происходит в убиваемом thread'e как только специальным API (TerminateThread/pthread_cancel/smth_else) запрошено убить когото -- тот умираит безвозвратно и все что было создано в контексте убитого thread'a превращается в leak...

    Еще раз повторяю — вменяемые программисты используют TerminateThread очень осторожно. Ну а pthread_cancel подразумевает вызов cleanup handler'ов, что при желании позволяет организовать "закат солнца вручную". Это, кстати, принципиальная разница, которая как раз заставляет "скатываться до уровня операционок". И, между прочим, написание врапперов неплохо помогает эти самых хэндлеры регистрировать.

    >

    > вот так в целом обстоит дело...
    > поэтому если писать тупые врапперы скрывающие от их пользователя 1 параметр (thread id в том или ином виде) и подменяющие его "объектом" thread -- это не упрощает нелегкое дело написания multithreadных прог... какбы комуто наивно не казалось...

    Если нитку приходится ждать, то враппер очень даже полезен — хотя бы для того, чтобы не забыть закрыть ее хэндл. Ну а насчет void* в качестве параметра — это, конечно, худший вариант, гораздо приятнее работать с интерфейсом в стиле boost::thread.

    >

    > мы тут попытались обсудить с какими проблемами придется столкнуться аффтору топика еси он хочет иметь не просто врапперы а нечто более интеллектуальное и призванное устранить некоторые известные проблемы в этой области... (точнее я пытался его на это подбить )

    Если автор топика будет использовать TerminateThread, проблемы у него, безусловно, будут
    Posted via RSDN NNTP Server 2.0
    Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
    Re[23]: класс-поток
    От: zaufi Земля  
    Дата: 08.08.06 09:40
    Оценка:
    Здравствуйте, Sergey, Вы писали:

    >>>> PPL! читаем внимательно: все мои листинги в этом топике ПСЕВДОКОД таких вызовов и классов не существует! -- всем расслабица...

    >>
    >> S>Т.е., мы обсуждаем код, который не может быть реализован?
    >>
    >> отчего же не может?

    S>Оттого, что под виндой данный код не может быть реализован (корректно реализован, естественно) в виду отсутствия гарантий операционной системы.


    о каких гарантях речь?
    ---
    раз ОС ничего не гарантирует может надо написать код (реализацию threads with C++ support) который буит чтото гарантировать? -- просто надо подумать а не уповать на корявую ОС... моск программеру для этого и дан

    >>>> ЗЫ: я и вправду немного ступил насчет join'a -- конечно же он не убивает thread... чтобы эстетам стало легче вообразите перед вызовом join'a такой псевдокод:
    >>>> ...
    >>>> thr.cancel();          // say 'DIE' to thread...
    >>>> thr.join();            // wait for thread death...
    >>>> ...
    >>>>

    >>
    >> S>Как именно реализован cancel? Под виндой, естественно. И почему именно не будет вызван деструктор obj?
    >>
    >> давайте не буим скатываться до уровня операционок -- до сих пор мы поговорили об обобщенном подходе многих известных ОС к убийству threadов...

    S>А давайте буим? Потому что конкретно под виндой ваш подход не работает.


    я еще ничего не говорил о "моем подходе"... все что я сказал было о том как здорово былоб иметь вот такой код и ничего о том как этого добиться (я таки хотел аффтара подбить на размышления об этом)

    >>

    >> и общая картина такова: большенству реализаций threadов накласть на то что происходит в убиваемом thread'e как только специальным API (TerminateThread/pthread_cancel/smth_else) запрошено убить когото -- тот умираит безвозвратно и все что было создано в контексте убитого thread'a превращается в leak...

    S>Еще раз повторяю — вменяемые программисты используют TerminateThread очень осторожно. Ну а pthread_cancel подразумевает вызов cleanup handler'ов, что при желании позволяет организовать "закат солнца вручную". Это, кстати, принципиальная разница, которая как раз заставляет "скатываться до уровня операционок". И, между прочим, написание врапперов неплохо помогает эти самых хэндлеры регистрировать.


    Ох не надо самовнушать себе что cleanup handlerы решают все проблемы мира! подобный закат солнца далеко не простая процедура... и организовать с их помошью то что делает компилятор когда переменная выходит из области видимости не простая задача (а с ростом локальных переменных с нетривиальным удалением она превращаяется в АЦЦКУЮ )

    кстати в "моем подходе" никакие cleanup handlerы НЕ НУЖНЫ... что делает TerminateThread и pthread_cancel принципиально одинаковыми!

    >> вот так в целом обстоит дело...

    >> поэтому если писать тупые врапперы скрывающие от их пользователя 1 параметр (thread id в том или ином виде) и подменяющие его "объектом" thread -- это не упрощает нелегкое дело написания multithreadных прог... какбы комуто наивно не казалось...

    S>Если нитку приходится ждать, то враппер очень даже полезен — хотя бы для того, чтобы не забыть закрыть ее хэндл. Ну а насчет void* в качестве параметра — это, конечно, худший вариант, гораздо приятнее работать с интерфейсом в стиле boost::thread.


    никто не спорит что врапперы полезны... но зачем ограничивать себя всего лишь врапперами если можно сделать все гараздо кашернее?
    вот основная идея топика

    >>

    >> мы тут попытались обсудить с какими проблемами придется столкнуться аффтору топика еси он хочет иметь не просто врапперы а нечто более интеллектуальное и призванное устранить некоторые известные проблемы в этой области... (точнее я пытался его на это подбить )

    S>Если автор топика будет использовать TerminateThread, проблемы у него, безусловно, будут


    но их можно решить! заимплементив то о чем я говорил... и не нада еще раз повторять про вменяемых программеров и TerminateThread
    Re[24]: класс-поток
    От: Sergey Россия  
    Дата: 08.08.06 10:24
    Оценка:
    > раз ОС ничего не гарантирует может надо написать код (реализацию threads with C++ support) который буит чтото гарантировать? -- просто надо подумать а не уповать на корявую ОС... моск программеру для этого и дан

    Напиши, если моск позволяет Только учти, что для более-менее полноценной реализации cancel handler'ов драйвер писать придется (или использовать чужой, типа alertdrv.sys). Для не очень полноценной — использовать хак типа вызова на SetThreadContext.

    > S>А давайте буим? Потому что конкретно под виндой ваш подход не работает.

    >
    > я еще ничего не говорил о "моем подходе"... все что я сказал было о том как здорово былоб иметь вот такой код и ничего о том как этого добиться (я таки хотел аффтара подбить на размышления об этом)

    Тогда почему бы не продолжить маниловщину — как здорово было б, чтоб такой код еще и деструкторы вызывал? Кстати, реализация pthread_cancel, основанная на SetThreadContext, вполне может и деструкторы вызывать. Только это все равно всех проблем не решает.


    > Ох не надо самовнушать себе что cleanup handlerы решают все проблемы мира! подобный закат солнца далеко не простая процедура... и организовать с их помошью то что делает компилятор когда переменная выходит из области видимости не простая задача (а с ростом локальных переменных с нетривиальным удалением она превращаяется в АЦЦКУЮ )

    >
    > кстати в "моем подходе" никакие cleanup handlerы НЕ НУЖНЫ... что делает TerminateThread и pthread_cancel принципиально одинаковыми!

    А кто мьютексы/критические секции отпускать будет? В том числе, залоченные операционкой?

    > никто не спорит что врапперы полезны... но зачем ограничивать себя всего лишь врапперами если можно сделать все гараздо кашернее?


    Самый кошерный способ — завершать нитку "добровольно", поднимая из контекста другой нити флаг, который терминируемая нить достаточно часто проверяет. А вовсе не игры с RaiseException в стиле виндовой реализации pthreads.

    > S>Если автор топика будет использовать TerminateThread, проблемы у него, безусловно, будут

    >
    > но их можно решить!

    Их можно просто не иметь, в большинстве случаев

    > заимплементив то о чем я говорил... и не нада еще раз повторять про вменяемых программеров и TerminateThread


    Ну если заняться больше нечем — то почему бы и нет.
    Posted via RSDN NNTP Server 2.0
    Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
    Re[25]: класс-поток
    От: zaufi Земля  
    Дата: 08.08.06 12:08
    Оценка:
    Здравствуйте, Sergey, Вы писали:

    >> раз ОС ничего не гарантирует может надо написать код (реализацию threads with C++ support) который буит чтото гарантировать? -- просто надо подумать а не уповать на корявую ОС... моск программеру для этого и дан


    S>Напиши, если моск позволяет Только учти, что для более-менее полноценной реализации cancel handler'ов драйвер писать придется (или использовать чужой, типа alertdrv.sys). Для не очень полноценной — использовать хак типа вызова на SetThreadContext.


    уже! года 3 назад
    обошлось без описаных тобой ужасов...

    S>А кто мьютексы/критические секции отпускать будет? В том числе, залоченные операционкой?


    >> никто не спорит что врапперы полезны... но зачем ограничивать себя всего лишь врапперами если можно сделать все гараздо кашернее?


    S>Самый кошерный способ — завершать нитку "добровольно", поднимая из контекста другой нити флаг, который терминируемая нить достаточно часто проверяет. А вовсе не игры с RaiseException в стиле виндовой реализации pthreads.


    верной дорогой идете товарисч!

    >> S>Если автор топика будет использовать TerminateThread, проблемы у него, безусловно, будут

    >>
    >> но их можно решить!

    S>Их можно просто не иметь, в большинстве случаев


    тоже хороший подход -- но не всегда срабатывает...

    >> заимплементив то о чем я говорил... и не нада еще раз повторять про вменяемых программеров и TerminateThread


    S>Ну если заняться больше нечем — то почему бы и нет.


    в том то и дело что есть чем заняться кроме изобретения велосипедов -- поэтому лучше один раз сесть и написать себе библу чем заниматься постоянным написанием новых решений дурацкой проблемы...
    Re[26]: класс-поток
    От: Sergey Россия  
    Дата: 08.08.06 12:19
    Оценка:
    > S>Напиши, если моск позволяет Только учти, что для более-менее полноценной реализации cancel handler'ов драйвер писать придется (или использовать чужой, типа alertdrv.sys). Для не очень полноценной — использовать хак типа вызова на SetThreadContext.
    >
    > уже! года 3 назад
    > обошлось без описаных тобой ужасов...

    Под винду? Можно поинтересоваться, как реализовано убивание нити?
    Posted via RSDN NNTP Server 2.0
    Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
    Re[27]: класс-поток
    От: zaufi Земля  
    Дата: 08.08.06 12:32
    Оценка:
    Здравствуйте, Sergey, Вы писали:

    >> S>Напиши, если моск позволяет Только учти, что для более-менее полноценной реализации cancel handler'ов драйвер писать придется (или использовать чужой, типа alertdrv.sys). Для не очень полноценной — использовать хак типа вызова на SetThreadContext.

    >>
    >> уже! года 3 назад
    >> обошлось без описаных тобой ужасов...

    S>Под винду? Можно поинтересоваться, как реализовано убивание нити?


    нет я с виндой завязал 6 лет назад

    сделал максимально кроссплатформенно... разумеется есть system depended code и виндовая часть все еще ожидает своего аффтара

    Основная идея в том, что нить не убивается системными средствами, а сама покидает этот мир
    Конечно же у нее есть средства чтоб понять этот момент: вылетающий thread_cancel exception внутри thread'a одно из них, и самое действенное. И программер как существо разумное стремиться обезопасить себя от ликов и прочих неприятностей связаных со "смертью" thread'a используя при этом нативные С++ные средства (большенство из которых имплементит за него компилятор -- как то: вызов деструкторов)
    Re[21]: класс-поток
    От: Kapone Украина  
    Дата: 08.08.06 15:15
    Оценка:
    Здравствуйте, Sergey, Вы писали:

    >> Насчет пост действий я тоже согласен, кроме объектов синхронизаций. Для некоторых (а конкретно для mutex-а) Windows гарантирует передачу ownership к одному из ожидающих объектов.


    S>Ни разу не встречал такой информации. Можно ссылку на источник? Хотя я имел в виду не мьютексы, а критические секции — "If the target thread owns a critical section, the critical section will not be released." Это из MSDN, из ремарок про TerminateThread. Еще там есть "If the target thread is allocating memory from the heap, the heap lock will not be released."



    А вот что говорит MSDN о мутексах
    "Mutex Objects". Ищется в индексе. Предпоследний абзац снизу

    If a thread terminates without releasing its ownership of a mutex object, the mutex object is considered to be abandoned. A waiting thread can acquire ownership of an abandoned mutex object, but the wait function will return WAIT_ABANDONED to indicate that the mutex object is abandoned. An abandoned mutex object indicates that an error has occurred and that any shared resource being protected by the mutex object is in an undefined state.

    ... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
    Re[28]: класс-поток
    От: Kapone Украина  
    Дата: 08.08.06 15:28
    Оценка:
    Здравствуйте, zaufi, Вы писали:

    Z>Основная идея в том, что нить не убивается системными средствами, а сама покидает этот мир

    Z>Конечно же у нее есть средства чтоб понять этот момент: вылетающий thread_cancel exception внутри thread'a одно из них, и самое действенное. И программер как существо разумное стремиться обезопасить себя от ликов и прочих неприятностей связаных со "смертью" thread'a используя при этом нативные С++ные средства (большенство из которых имплементит за него компилятор -- как то: вызов деструкторов)

    Интересно ...
    Но тогда наверно при програмировании такого "волшебного" треда нужно помнить, что надолго зависать нельзя и постоянно отчитыватся глобальному судье — "а вот он я.. не завис", а судья тады милостиво будет разрешать тебе работать дальше (или не разрешать)
    Или ошибаюсь?
    ... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
    Re[29]: класс-поток
    От: zaufi Земля  
    Дата: 09.08.06 05:35
    Оценка:
    Здравствуйте, Kapone, Вы писали:

    K>Здравствуйте, zaufi, Вы писали:


    Z>>Основная идея в том, что нить не убивается системными средствами, а сама покидает этот мир

    Z>>Конечно же у нее есть средства чтоб понять этот момент: вылетающий thread_cancel exception внутри thread'a одно из них, и самое действенное. И программер как существо разумное стремиться обезопасить себя от ликов и прочих неприятностей связаных со "смертью" thread'a используя при этом нативные С++ные средства (большенство из которых имплементит за него компилятор -- как то: вызов деструкторов)

    K>Интересно ...

    K>Но тогда наверно при програмировании такого "волшебного" треда нужно помнить, что надолго зависать нельзя и постоянно отчитыватся глобальному судье — "а вот он я.. не завис", а судья тады милостиво будет разрешать тебе работать дальше (или не разрешать)
    K>Или ошибаюсь?

    да разумееца надолго зависать не хорошо... но отчитываться тоже ни перед кем не надо
    нужно всего лишь быть готовым обработать исключение thread_cancel и самозавершиться в случае его поимки
    хотя бывают моменты когда самаму приходится узнавать нужен ты комуто еще или нет -- для этого есть is_canceled() возвращающая true если ктото желает смерти текущему thread'у
    Re[30]: класс-поток
    От: Kapone Украина  
    Дата: 09.08.06 06:32
    Оценка:
    Здравствуйте, zaufi, Вы писали:

    Z>да разумееца надолго зависать не хорошо... но отчитываться тоже ни перед кем не надо

    Z>нужно всего лишь быть готовым обработать исключение thread_cancel и самозавершиться в случае его поимки
    Z>хотя бывают моменты когда самаму приходится узнавать нужен ты комуто еще или нет -- для этого есть is_canceled() возвращающая true если ктото желает смерти текущему thread'у

    Наверно ты не так меня понял
    Я имел ввиду, что все равно поток ДОЛЖЕН знать, что когда нибудь его кто-то захочет закенселить. Исходя из этого он постоянно (на там по ходу цикла наприер) вызывает ф-цию, которая может выбросить исключение.

    Это ведет к уже указанному мной колбеку.

    Подумав над проблемой глобально (то есть от нечего делать в эл-ке), я выделил для себя 3 момента, могущих заставить поток зависнуть всерьез и надолго. В конкретных случаях для всех этих случаев можно заранее придумать заготовки и аккуратно програмировать, напоминая себе постояно "Меня могут попросить свалить.Меня могут попросить свалить....."
    Вот какие случаи и выходы из них я выделил бы:



    Для общего же случая с "тупой" ОС боротся не получится и придется либо убивать поток лопатой(то есть Terminate), либо, засучив рукава, решать каждый конкретный случай отдельно.
    ... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
    Re[31]: класс-поток
    От: Sergey Россия  
    Дата: 09.08.06 07:46
    Оценка:
    > Z>да разумееца надолго зависать не хорошо... но отчитываться тоже ни перед кем не надо
    > Z>нужно всего лишь быть готовым обработать исключение thread_cancel и самозавершиться в случае его поимки
    > Z>хотя бывают моменты когда самаму приходится узнавать нужен ты комуто еще или нет -- для этого есть is_canceled() возвращающая true если ктото желает смерти текущему thread'у
    >
    > Наверно ты не так меня понял
    > Я имел ввиду, что все равно поток ДОЛЖЕН знать, что когда нибудь его кто-то захочет закенселить. Исходя из этого он постоянно (на там по ходу цикла наприер) вызывает ф-цию, которая может выбросить исключение.

    На самом деле в той же виндовой реализации pthreads все делается просто (при условии отсутствия драйвера, помогающего реализовать QueueUserAPCEx) — SuspendThread, SetThreadContext на коллбэк, ResumeThread. Ну а коллбэк просто кидает исключение (уже в контексте терминируемой нити). Для юзерского кода все хорошо и здорово (перехватил исключение, и дело с концом), а вот то, что операционка всегда нормально будет себя вести при таких финтах, никто не обещает.

    >
  • Блокирующий вызова в ядро (различного рода read, write и тд)
    >
    > Решение.
    > Это самый сложный случай из всех. И наверно именно из-за него советовали писать драйвер и другие подобные страхи (или покупать). Конечно, преимущество драйвера неоспоримо, ведь тогда он берет на себя работу по отслеживанию текущих блокировок и их корректному завершению, но тогда мы становимся его заложниками. Для большой системы это еще приемлемо, но не маленьких это неприемлемо.
    > Ну голь на выдумки емка, так что можно всего лишь обойтись локальным хранилищем хендлов. Разумеется, чтобы все это дело автоматизировать, придётся писать фремворк, в котором необходимо завести базовый класс HandleBase, в котором и будет проходить вся работа по помещению хендла в таблицу возможно зависших хендлов MegaThreada.
    > Многие скажут, что это гемор и всё такое, но на самом деле — не такой уж и гемор.
    > Ведь есть всего несколько видов блокирующих хендлов — File, Socket, Pipe. Но всё равно всё сходится к файлам, к ним родимым.

    Про dll'ки забыл. Допустим, в убиваемой нити осуществляется загрузка какой-нибудь юзерской dll и всех dll, которые она тянет за собой. Перед вызовом DllMain Win2000 и XP блокируют какую-то свою критическую секцию. И как раз после окончания вызова DllMain (который наверняка обложен exception fraim'ом), но до отпускания критической секции осуществляется наше прибивание нити. В каком состоянии останется та критическая секция и сможет ли процесс нормально продолжить работу — фиг его знает. И это только один, самый простой, пример.
    Ну а про драйвер я говорил тоже наглядевшись на pthreads — там используется вот это: http://www.codeproject.com/threads/queueuserapcex.asp?df=100&amp;forumid=15653&amp;exp=0&amp;select=597532 Решение более грамотное, но не всегда приемлемое.
    Posted via RSDN NNTP Server 2.0
  • Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
    Re[32]: класс-поток
    От: Kapone Украина  
    Дата: 09.08.06 08:18
    Оценка:
    Здравствуйте, Sergey, Вы писали:


    S>Про dll'ки забыл. Допустим, в убиваемой нити осуществляется загрузка какой-нибудь юзерской dll и всех dll, которые она тянет за собой. Перед вызовом DllMain Win2000 и XP блокируют какую-то свою критическую секцию. И как раз после окончания вызова DllMain (который наверняка обложен exception fraim'ом), но до отпускания критической секции осуществляется наше прибивание нити. В каком состоянии останется та критическая секция и сможет ли процесс нормально продолжить работу — фиг его знает. И это только один, самый простой, пример.

    S>Ну а про драйвер я говорил тоже наглядевшись на pthreads — там используется вот это: http://www.codeproject.com/threads/queueuserapcex.asp?df=100&amp;forumid=15653&amp;exp=0&amp;select=597532 Решение более грамотное, но не всегда приемлемое.

    Можно привести в пример еще многое (та же подсистема user32 сос своими очередями сообщение и SendMessage-ами и тд и тп).
    Но я постарался выделить наиболее основные моменты, когда используются доп. потоки.
    Ведь это по большей части паралельный ввод/вывод или паралельная обработка информации. По крайней мере у меня в 98% процентах случаев нужно именно это.
    И лечил я все эти случаи описанными способами. Но до написания единого фреймворка руки не доходили. Потому как много времени нужно, чтобы осознать всю глубину глубин и реализовать ее...

    Про критические секции принципиально не писал, потому как зависание в них еще не разу не было (дай бог здоровья Александреску, у которого я прочитал про Lock классы).
    Уж слишком быстро работают участки с их участием...
    ... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
    Re[31]: класс-поток
    От: zaufi Земля  
    Дата: 09.08.06 08:45
    Оценка:
    Здравствуйте, Kapone, Вы писали:

    K>Наверно ты не так меня понял

    я понял правильно -- ты туманно объяснил просто

    K>Я имел ввиду, что все равно поток ДОЛЖЕН знать, что когда нибудь его кто-то захочет закенселить. Исходя из этого он постоянно (на там по ходу цикла наприер) вызывает ф-цию, которая может выбросить исключение.


    на сам деле таких функций может быть не одна -- каждая из них называется cancelation point -- т.е. точка выходом из которой может стать исключение thread_canceled... т.е. фактически мы забиваем на системную поддержку cancelation pointов (делая неканцелябельные с точки зрения системы threadы -- чтоб ни одна сволоч не смогла нас убить без нашего ведома -- уж не знаю есь ли подобное в виндюках)

    K>
  • Какой нить длииииииинный цикл, чего делающий

    зачот

    K>
  • Ожидание какого нить события (ну там в очередь пришли данные или еще чего). В этом обычно учавствуют ф-ции Wait... для Винды или select тд для Уникс

    почти зачот
    так как мы пишем не один тупой враппер для thread'a а семейcтво классов помогающее при разработке MT прог -- нам в том или ином виде придется делать обертки (или не тaкие уж они обертки ) над синхронизационными примитивами
    реимплементя их мы встраиваем в их работу проверку на is_cancel() и выкидываем исключение...

    в большенстве случаев этого ДОСТАТОЧНО -- т.к. трудно себе представить multithreaded прогу не работающую с mutex'ами и condition'ами !! -- и естественно предлагая юзеру этот stuff мы уж позаботимся о том чтоб исключения таки долетали

    как было отмечено в первом пункте бывают долгие цыклы без вызовов cancellation pointов -- для этого программер (если он вменяемый расставит is_canceled() в нужных местах (т.е. это все специфично для конкретной задачи и поделать с этим мы ни чего не можем...) Однако как показывает опыт для программера вписать это в условие своих циклов сапсем не напряжно -- т.е. решение вполне удобоваримое

    K>
  • Блокирующий вызова в ядро (различного рода read, write и тд)

    проблемы с блокирующимися вызовами довольно легко объезжаются -- на моей практике не было ни одного такого случая

    K>Для общего же случая с "тупой" ОС боротся не получится и придется либо убивать поток лопатой(то есть Terminate), либо, засучив рукава, решать каждый конкретный случай отдельно.

    насколько "тупой" должна быть ОС предоставляыющая threadы и не предоставляющаяя mutex & condition ? -- IMHO таких не бывает -- а значит для любой ОС мы сможем выкрутиться!
  • Re[32]: УЖОС!
    От: zaufi Земля  
    Дата: 09.08.06 08:46
    Оценка:
    как не просто программировать под винды!
    Re[32]: класс-поток
    От: Kapone Украина  
    Дата: 09.08.06 12:51
    Оценка:
    Здравствуйте, zaufi, Вы писали:

    Z>т.е. фактически мы забиваем на системную поддержку cancelation pointов (делая неканцелябельные с точки зрения системы threadы -- чтоб ни одна сволоч не смогла нас убить без нашего ведома -- уж не знаю есь ли подобное в виндюках)


    Честно говоря, не понял, что имелось ввиду под этой пространной фразой.
    Если не влом, то можно поподробнее, плз

    Z>почти зачот

    Z>так как мы пишем не один тупой враппер для thread'a а семейcтво классов помогающее при разработке MT прог -- нам в том или ином виде придется делать обертки (или не тaкие уж они обертки ) над синхронизационными примитивами
    Z>реимплементя их мы встраиваем в их работу проверку на is_cancel() и выкидываем исключение...

    Ну я вообще это и имел ввиду, только написал чуть позже...

    K>>Для общего же случая с "тупой" ОС боротся не получится и придется либо убивать поток лопатой(то есть Terminate), либо, засучив рукава, решать каждый конкретный случай отдельно.

    Z>насколько "тупой" должна быть ОС предоставляыющая threadы и не предоставляющаяя mutex & condition ? -- IMHO таких не бывает -- а значит для любой ОС мы сможем выкрутиться!

    Это даже не ИМХО. Теоретически доказано Дейкстрой, что в многопоточной среде не обойтись без объектов синхронизации.
    Другое дело, чтобы добится требуемой ф-ости только с помощью средств ОС, не гемороясь, не танцуя с бубнами и не делая фактически работу разработчиков ОС, мы требуемой ф-ости добится не можем ...

    Всё равно мы приходим к тому, что остановить, кроме как ЛОПАТОЙ (или злобных и неизведанных хаков), течение потока, который даже не подозревает о том, что он работает в многопоточной среде, невозможно. А жаль ...
    Так что вопрос закрыт.
    Точка.

    НО!
    Старый код то всё равно придется модифицировать!
    А это чревато новыми неизведаными багами!
    так что работа у нас будет и это не может не радовать !
    ... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
     
    Подождите ...
    Wait...
    Пока на собственное сообщение не было ответов, его можно удалить.