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...
    ...
    Подождите ...
    Wait...
    Пока на собственное сообщение не было ответов, его можно удалить.