класс-поток
От: 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х лет успешно этим решением пользуюсь
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.