Re[13]: чисто виртуальная функция
От: cthutq00  
Дата: 02.05.06 18:18
Оценка:
R>
R>class ThreadHandler
R>{
R>public:
R>  virtual ~ThreadHandler() = 0;

R>  bool is_active() const = 0;

R>  virtual void start() = 0;
R>  virtual void terminate() = 0;
R>  virtual void suspend() = 0;
R>  virtual void resume() = 0;
R>};

R>class ThreadFacade
R>{
R>public:
R>   Thread(boost::shared_ptr<ThreadHandler>) 
R>   : m_thread_handler(thread_handler)
R>   {
R>      m_thread_handler->start();
R>   }

R>   virtual ~ThreadFacade()
R>   {
R>#ifdef MY_FORCE_TERMINATE_THREAD
R>      m_thread_handler->terminate();  
R>#else
R>      while(m_thread_handler->is_active())
R>          Sleep(2);
R>#endif   
R>   }

R>  bool is_active() const                 {return m_thread_handler->is_active();}
R>  void suspend();                 {m_thread_handler->suspend();}  
R>  void resume();                   {m_thread_handler->resume();} 

R>private:
R>  boost::shared_ptr<ThreadHandler> m_thread_handler;
R>};
R>


хм... не совсем понял что мне даст этот класс ThreadFacade

ведь вопрос в том, что если класс А наследуется от ThreadHandler и определяет чисто виртуальную функцию
и класс В наследуется он А переопределяя ее, то при ожидании потока в ~ThreadHandler таблица vtbl для В будет
разрушена (как и сказано выше)
Re[14]: чисто виртуальная функция
От: rg45 СССР  
Дата: 02.05.06 18:33
Оценка:
"cthutq00" <53488@users.rsdn.ru> wrote in message news:1877039@news.rsdn.ru...
>
> хм... не совсем понял что мне даст этот класс ThreadFacade
>
> ведь вопрос в том, что если класс А наследуется от ThreadHandler и определяет чисто виртуальную функцию
> и класс В наследуется он А переопределяя ее, то при ожидании потока в ~ThreadHandler таблица vtbl для В будет
> разрушена (как и сказано выше)

Так именно для этого ThreadFacade, чтоб ожидать потока в его деструкторе, а не в деструкторе ThreadHandler, при этом vtbl B будет целой. Да и сам поток создавать нужно при создании объекта ThreadFacade, это я в своем примере не показал в попыхах. Объекты-наследники ThreadHandler реализуют только сам код потока, но не делают никакой работы по созданию самих потоков. Собственно ThreadFacade правильнее было бы назвать просто Thread, поскольку реальная работа по созданию потока выполняется именно в нем.
Posted via RSDN NNTP Server 2.0
Я жду, когда этот пидарас
Автор: Bj777x
Дата: 22.06.20
либо удалит свое хамство здесь
Автор: Bj777x
Дата: 14.10 21:26
и здесь
Автор: Bj777x
Дата: 27.09 11:34
, либо восстановит ответы.
Re[15]: чисто виртуальная функция
От: cthutq00  
Дата: 02.05.06 19:05
Оценка:
Здравствуйте, rg45, Вы писали:


R>"cthutq00" <53488@users.rsdn.ru> wrote in message news:1877039@news.rsdn.ru...

>>
>> хм... не совсем понял что мне даст этот класс ThreadFacade
>>
>> ведь вопрос в том, что если класс А наследуется от ThreadHandler и определяет чисто виртуальную функцию
>> и класс В наследуется он А переопределяя ее, то при ожидании потока в ~ThreadHandler таблица vtbl для В будет
>> разрушена (как и сказано выше)

R>Так именно для этого ThreadFacade, чтоб ожидать потока в его деструкторе, а не в деструкторе ThreadHandler, при этом vtbl B будет целой. Да и сам поток создавать нужно при создании объекта ThreadFacade, это я в своем примере не показал в попыхах. Объекты-наследники ThreadHandler реализуют только сам код потока, но не делают никакой работы по созданию самих потоков. Собственно ThreadFacade правильнее было бы назвать просто Thread, поскольку реальная работа по созданию потока выполняется именно в нем.


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

если не сложно — можно схематично примерчик как связать все это хозяйство
Re[16]: чисто виртуальная функция
От: rg45 СССР  
Дата: 02.05.06 21:01
Оценка: :)
"cthutq00" <53488@users.rsdn.ru> wrote in message news:1877087@news.rsdn.ru...
> блин... что-то я запутался
> (твой код меня немного сбил с толку, так как в нем ничего нет про виртуальную функцию и я так и не могу понять его полезность)
>
> если не сложно — можно схематично примерчик как связать все это хозяйство

Вот пример, в самом приблизительном схематичном виде. Работа с потоками реализована через boost::thread. Синхронизацию доступа к переменным из разных потоков не стал делать ради краткости и простоты восприятия.


#include <cstdlib>
#include <iostream>
#include <boost\shared_ptr.hpp>
#include <boost\function.hpp>
#include <boost\bind.hpp>
#include <boost\thread.hpp>

//Базовый класс обработчиков потоков
class ThreadHandler
{
public:
  virtual ~ThreadHandler(){}
  
  virtual bool still_active() const = 0; //если функция потока выполняется, true иначе - false
  
  virtual void execute() = 0;            //запустить поток
  virtual void ask_for_exit() = 0;       //вежливо попросить о завершении
};

//Класс потока
class Thread
{
public:

  Thread(boost::shared_ptr<ThreadHandler> handler)
  : m_handler(handler)
  , m_thread(boost::bind(&ThreadHandler::execute, handler.get()))
  {
  }
  
  virtual ~Thread()
  {
    //просим поток завершиться
    m_handler->ask_for_exit();

    //ждем завершения потока
    while(m_handler->still_active())
      Sleep(2);
  }

private:
  boost::shared_ptr<ThreadHandler>  m_handler;  //обработчик потока
  boost::thread                     m_thread;   //объект потока
};

//Пробный класс обработчика потока
class TestThreadHandler : public ThreadHandler
{
public:
  
  TestThreadHandler()
  : m_steel_active(true)
  , m_need_exit(false)
  {}

  virtual bool still_active() const {return m_steel_active;}
  virtual void ask_for_exit()       {m_need_exit = true;}

  virtual void execute()
  {
    //выводим случайные числа пока не прийдет запрос на завершение
    while(!m_need_exit)
      std::cout << rand() << std::endl;

    m_steel_active = false;
  }
        
private:
  bool m_steel_active;  
  bool m_need_exit;  
};

int main()
{
  boost::shared_ptr<ThreadHandler> handler(new TestThreadHandler);
  Thread thread(handler);
  Sleep(100);
}
Posted via RSDN NNTP Server 2.0
Я жду, когда этот пидарас
Автор: Bj777x
Дата: 22.06.20
либо удалит свое хамство здесь
Автор: Bj777x
Дата: 14.10 21:26
и здесь
Автор: Bj777x
Дата: 27.09 11:34
, либо восстановит ответы.
Re[17]: чисто виртуальная функция
От: Константин Л. Россия  
Дата: 03.05.06 09:29
Оценка:
Здравствуйте, rg45, Вы писали:

>>

>> R>Тоже вариант, конечно, но не совсем надежно: кому-нибудь стукнет в голову унаследоваться от A и в наследнике дать свою реализацию func_ и вся идея наворачивается.
>>
>> Нечего от A наследоваться
>>
>> А такое извращение?
>>
>>
>> template <class Impl>
>> class A : public BaseImpl<Impl>
>> {
>> private:/*public*/
>> 
>>   void func_()
>>   {
>>      Impl::func_();
>>   }
>> };
>> 
>> class B : public A<B>
>> {
>>  void func_()
>>  { /**/ }
>> };
>> 
>>

>>
>>

R> Ну а теперь нечего наследоваться от B

и A нечем инстанциировать
Estuve en Granada y me acorde' de ti
Re[17]: чисто виртуальная функция
От: cthutq00  
Дата: 07.05.06 07:29
Оценка:
Здравствуйте, rg45, Вы писали:


R>Вот пример, в самом приблизительном схематичном виде. Работа с потоками реализована через boost::thread. Синхронизацию доступа к переменным из разных потоков не стал делать ради краткости и простоты восприятия.


R>

R>#include <cstdlib>
R>#include <iostream>
R>#include <boost\shared_ptr.hpp>
R>#include <boost\function.hpp>
R>#include <boost\bind.hpp>
R>#include <boost\thread.hpp>

R>//Базовый класс обработчиков потоков
R>class ThreadHandler
R>{
R>public:
R>  virtual ~ThreadHandler(){}
  
R>  virtual bool still_active() const = 0; //если функция потока выполняется, true иначе - false
  
R>  virtual void execute() = 0;            //запустить поток
R>  virtual void ask_for_exit() = 0;       //вежливо попросить о завершении
R>};

R>//Класс потока
R>class Thread
R>{
R>public:

R>  Thread(boost::shared_ptr<ThreadHandler> handler)
R>  : m_handler(handler)
R>  , m_thread(boost::bind(&ThreadHandler::execute, handler.get()))
R>  {
R>  }
  
R>  virtual ~Thread()
R>  {
R>    //просим поток завершиться
R>    m_handler->ask_for_exit();

R>    //ждем завершения потока
R>    while(m_handler->still_active())
R>      Sleep(2);
R>  }

R>private:
R>  boost::shared_ptr<ThreadHandler>  m_handler;  //обработчик потока
R>  boost::thread                     m_thread;   //объект потока
R>};

R>//Пробный класс обработчика потока
R>class TestThreadHandler : public ThreadHandler
R>{
R>public:
  
R>  TestThreadHandler()
R>  : m_steel_active(true)
R>  , m_need_exit(false)
R>  {}

R>  virtual bool still_active() const {return m_steel_active;}
R>  virtual void ask_for_exit()       {m_need_exit = true;}

R>  virtual void execute()
R>  {
R>    //выводим случайные числа пока не прийдет запрос на завершение
R>    while(!m_need_exit)
R>      std::cout << rand() << std::endl;

R>    m_steel_active = false;
R>  }
        
R>private:
R>  bool m_steel_active;  
R>  bool m_need_exit;  
R>};

R>int main()
R>{
R>  boost::shared_ptr<ThreadHandler> handler(new TestThreadHandler);
R>  Thread thread(handler);
R>  Sleep(100);
R>}
R>


rg45, я немного не то имел ввиду.

У тебя есть интерфейс (я его обзову IThread)
Есть Thread, который дергает методы IThread. Ты предлагаешь наследоваться от IThread и отдавать его
Thread.

Но весь фокус в том, что если из execute вызвать чисто виртуальный метод, а потом его переопределить, то все накроется

У меня есть подозрение, что из потока нельзя вызывать виртуальные методы. Или я что-то упустил ?


class IThread;
class Thread;

class Base : public IThread{
    virtual void vfunc () = 0;
    virtual void execute{
        vfunc();
    }
}

class SClass : public Base{
    virtual void vfunc (){
        ...
    }
}

main(){
    Thread thread (SClass);
    Sleep(100); // <--- здесь деструктор Thread будет ждать завершения потока Base, а SClass::vfunc() уже может быть разрушен
}


Или я не прав ?
Re[18]: чисто виртуальная функция
От: Константин Л. Россия  
Дата: 07.05.06 14:07
Оценка:
Здравствуйте, cthutq00, Вы писали:

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



R>>Вот пример, в самом приблизительном схематичном виде. Работа с потоками реализована через boost::thread. Синхронизацию доступа к переменным из разных потоков не стал делать ради краткости и простоты восприятия.


R>>

R>>#include <cstdlib>
R>>#include <iostream>
R>>#include <boost\shared_ptr.hpp>
R>>#include <boost\function.hpp>
R>>#include <boost\bind.hpp>
R>>#include <boost\thread.hpp>

R>>//Базовый класс обработчиков потоков
R>>class ThreadHandler
R>>{
R>>public:
R>>  virtual ~ThreadHandler(){}
  
R>>  virtual bool still_active() const = 0; //если функция потока выполняется, true иначе - false
  
R>>  virtual void execute() = 0;            //запустить поток
R>>  virtual void ask_for_exit() = 0;       //вежливо попросить о завершении
R>>};

R>>//Класс потока
R>>class Thread
R>>{
R>>public:

R>>  Thread(boost::shared_ptr<ThreadHandler> handler)
R>>  : m_handler(handler)
R>>  , m_thread(boost::bind(&ThreadHandler::execute, handler.get()))
R>>  {
R>>  }
  
R>>  virtual ~Thread()
R>>  {
R>>    //просим поток завершиться
R>>    m_handler->ask_for_exit();

R>>    //ждем завершения потока
R>>    while(m_handler->still_active())
R>>      Sleep(2);
R>>  }

R>>private:
R>>  boost::shared_ptr<ThreadHandler>  m_handler;  //обработчик потока
R>>  boost::thread                     m_thread;   //объект потока
R>>};

R>>//Пробный класс обработчика потока
R>>class TestThreadHandler : public ThreadHandler
R>>{
R>>public:
  
R>>  TestThreadHandler()
R>>  : m_steel_active(true)
R>>  , m_need_exit(false)
R>>  {}

R>>  virtual bool still_active() const {return m_steel_active;}
R>>  virtual void ask_for_exit()       {m_need_exit = true;}

R>>  virtual void execute()
R>>  {
R>>    //выводим случайные числа пока не прийдет запрос на завершение
R>>    while(!m_need_exit)
R>>      std::cout << rand() << std::endl;

R>>    m_steel_active = false;
R>>  }
        
R>>private:
R>>  bool m_steel_active;  
R>>  bool m_need_exit;  
R>>};

R>>int main()
R>>{
R>>  boost::shared_ptr<ThreadHandler> handler(new TestThreadHandler);
R>>  Thread thread(handler);
R>>  Sleep(100);
R>>}
R>>


C>rg45, я немного не то имел ввиду.


C>У тебя есть интерфейс (я его обзову IThread)

C>Есть Thread, который дергает методы IThread. Ты предлагаешь наследоваться от IThread и отдавать его
C>Thread.

C>Но весь фокус в том, что если из execute вызвать чисто виртуальный метод, а потом его переопределить, то все накроется


C>У меня есть подозрение, что из потока нельзя вызывать виртуальные методы. Или я что-то упустил ?



C>
C>class IThread;
C>class Thread;

C>class Base : public IThread{
C>    virtual void vfunc () = 0;
C>    virtual void execute{
C>        vfunc();
C>    }
C>}

C>class SClass : public Base{
C>    virtual void vfunc (){
C>        ...
C>    }
C>}

C>main(){
C>    Thread thread (SClass);
C>    Sleep(100); // <--- здесь деструктор Thread будет ждать завершения потока Base, а SClass::vfunc() уже может быть разрушен
C>}
C>


C>Или я не прав ?


Не прав. В деструкторе Thread объект IThread еще будет живее всех живых
Estuve en Granada y me acorde' de ti
Re[19]: чисто виртуальная функция
От: cthutq00  
Дата: 07.05.06 15:39
Оценка:
КЛ>Не прав. В деструкторе Thread объект IThread еще будет живее всех живых

В том-то и дело, что IThread будет жить с его чисто выиртуальным методом.
А Base и SClass с реализацией метода могут умереть (и скорее всего умрут).

Что изначально и привело у меня к непоняткам
Re[20]: чисто виртуальная функция
От: Константин Л. Россия  
Дата: 07.05.06 20:55
Оценка:
Здравствуйте, cthutq00, Вы писали:

КЛ>>Не прав. В деструкторе Thread объект IThread еще будет живее всех живых


C>В том-то и дело, что IThread будет жить с его чисто выиртуальным методом.

C>А Base и SClass с реализацией метода могут умереть (и скорее всего умрут).

C>Что изначально и привело у меня к непоняткам


так, еще раз:

SClass умрет тогда, когда умрет Thread -> в деструкторе Thread SClass будет жив.
Читай теорию
Estuve en Granada y me acorde' de ti
Re[17]: UAH (RUR) 0,05
От: Roman Odaisky Украина  
Дата: 08.05.06 08:57
Оценка:
Здравствуйте, rg45, Вы писали:

R>
  virtual void execute()
  {
    //выводим случайные числа пока не прийдет запрос на завершение
    while(!m_need_exit)
      std::cout << rand() << std::endl;

    m_steel_active = false;
  }

надо
  virtual void execute()
  {
    ScopeGuard g(boost::bind(_1 = false, m_steel_active));

    //выводим случайные числа пока не прийдет запрос на завершение
    while(!m_need_exit)
      std::cout << rand() << std::endl;
  }
До последнего не верил в пирамиду Лебедева.
Re[18]: чисто виртуальная функция
От: rg45 СССР  
Дата: 10.05.06 06:08
Оценка:
"cthutq00" <53488@users.rsdn.ru> wrote in message news:1887217@news.rsdn.ru...
>
> rg45, я немного не то имел ввиду.
>
> У тебя есть интерфейс (я его обзову IThread)
> Есть Thread, который дергает методы IThread. Ты предлагаешь наследоваться от IThread и отдавать его
> Thread.
>
> Но весь фокус в том, что если из execute вызвать чисто виртуальный метод, а потом его переопределить, то все накроется
>
> У меня есть подозрение, что из потока нельзя вызывать виртуальные методы. Или я что-то упустил ?
>
>
>
> class IThread;
> class Thread;
> 
> class Base : public IThread{
>    virtual void vfunc () = 0;
>    virtual void execute{
>        vfunc();
>    }
> }
> 
> class SClass : public Base{
>    virtual void vfunc (){
>        ...
>    }
> }
> 
> main(){
>    Thread thread (SClass);
>    Sleep(100); // <--- здесь деструктор Thread будет ждать завершения потока Base, а SClass::vfunc() уже может быть разрушен
> }
>

>
> Или я не прав ?

Извини, что не ответил сразу, не было возможности.
Здесь динамическая диаграмма такова:
1. Создается объект класса SClass;
2. Создается объект класса Thread и принимает во владение объект SClass через объект типа boost::shared_ptr<IThread>;
3. Создается новый поток, в котором выполняется виртуальная функция execute() объекта SClass , объявленная в классе IThread как чито виртуальная и определенная в классе Base;
4. В то время, когда главный поток находится в состоянии ожидания (Sleep(100)), в параллельном потоке, выполняется функция execute(), из которой вызывается виртуальная функция vfunc(), объявленная в классе Base как чисто виртуальная и переопределенная в классе SClass. Проблем здесь никаких нет: виртуальный механизм работает одинаково как в главном потоке процесса, так и в любом другом;
5. После завершения вызова Sleep(100), при завершени функции main() вызывается деструктор объекта Thread;
6. В деструкторе объекта Thread выполняется оповещение параллельного потока о необходимости завершения, и выполняется ожидание его завершения;
7. Вызывается деструктор объекта boost::shared_ptr<IThread>, который является членом класса Thread, при этом происходит удаление объекта SClass.

Как видно из этой диаграммы, разрушение объекта SClass происходит при выходе из main() с ожиданием завершения параллельного потока. Так что все корректно, если не принимать во внимание отсутвие синхронизации доступа к объектам из разных потоков.
Posted via RSDN NNTP Server 2.0
Я жду, когда этот пидарас
Автор: Bj777x
Дата: 22.06.20
либо удалит свое хамство здесь
Автор: Bj777x
Дата: 14.10 21:26
и здесь
Автор: Bj777x
Дата: 27.09 11:34
, либо восстановит ответы.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.