Просьба не пинать ногами, уверен, что уже обсуждали эту тему и не раз, до меня даже доносились обрывки этих разговоров в форумах, только вот я не понял по каким словам их искать в поиске. Попробовал — не получилось. Подскажите, плиз, эти ключевые слова, или ссылки, либо чем-нить еще.
Задача:
Есть ряд вызовов в общем виде.
ret = pobj->func( param1, ..., param2 ) ;
ret = obj.func( param1, ..., param2 ) ;
ret = func( param1, ..., param2 ) ;
Нужно создать такой механизм, чтобы выполнить этот вызов в отдельном потоке. А еще лучше в конкретном потоке, который уже работает (схожие наверно задачи, если первая будет, то и до второй недалеко).
1. Желательно, чтобы вызов был как наименее громоздким. Т.е. что-то типа такого:
2. Учитывать виртуальные фукцнии объектов.
3. Определить возможность обратного вызова с полученным результатом и возможность ожидания исполнения (т.е. возврат после того как функция выполнит свою работу).
A>Нужно создать такой механизм, чтобы выполнить этот вызов в отдельном потоке. А еще лучше в конкретном потоке, который уже работает (схожие наверно задачи, если первая будет, то и до второй недалеко).
A>1. Желательно, чтобы вызов был как наименее громоздким. Т.е. что-то типа такого: A>
A>RUN_IN_OTHER_THREAD( pobj, func, param1, ..., param2) ;
A>
A>2. Учитывать виртуальные фукцнии объектов. A>3. Определить возможность обратного вызова с полученным результатом и возможность ожидания исполнения (т.е. возврат после того как функция выполнит свою работу).
Использовать функторы, например, boost::function + boost::bind.
A> // Совершить вызов функции в потоке с ожиданием результата.
A> template< class BinObj >
A> typename BinObj::result_type Call_Wait( BinObj * pCall )
A> {
A> HANDLE hEvent = CreateEvent( NULL, FALSE, FALSE, NULL ) ;
A> pCall->AddRef() ;
A> PostThreadMessage( dwThrId, WM_CALL, ( WPARAM )hEvent, ( LPARAM ) ( ICall * ) & pCall ) ;
A> WaitForSingleObject( hEvent, INFINITE ) ;
A> CloseHandle( hEvent ) ;
A> typename BinObj::result_type res = rCall.m_result ;
A> rCall.Release() ;
A> return res ;
A> }
A>
Здравствуйте, PoM-PoM 40mm, Вы писали:
PP4>А напишите ПЛЗ пример использования. Допустим с парой параметров.
PP4>Попутно вопрос -- допустим есть некоторый класс, имеющий оператор ().
PP4>
PP4>допустим мы хотим вызвать его через boost::function0<void>
PP4>
PP4>boost::function0<void> func;
PP4> {
PP4> SomeCleverClass stupid;
PP4> func=stupid;
PP4> }
PP4>func(); // а не рухнет ли тут из-за вызова по разрушенному объекту!
PP4>
PP4>Если рухнет, то оно у Вас не очень удобно -- все вызовы только через Send, впрочем проблема вообще философская
Это ко мне вопрос?
Често, я в бустах вообще не разбираюсь. Никогда им не пользовался. Может и зря
PP4>boost::function0<void> func;
PP4> {
PP4> SomeCleverClass stupid;
PP4> func=stupid; // (*)
PP4> }
PP4>func(); // а не рухнет ли тут из-за вызова по разрушенному объекту!
PP4>
Не рухнет. (*) Будет создана копия объекта SomeCleverClass.
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, PoM-PoM 40mm, Вы писали:
PP4>>
PP4>>boost::function0<void> func;
PP4>> {
PP4>> SomeCleverClass stupid;
PP4>> func=stupid; // (*)
PP4>> }
PP4>>func(); // а не рухнет ли тут из-за вызова по разрушенному объекту!
PP4>>
К>Не рухнет. (*) Будет создана копия объекта SomeCleverClass.
Замечательно. А Вы не просветите меня как это чудо реализовано? Немного покопался в исходниках, понял ничтожно мало.
Здравствуйте, PoM-PoM 40mm, Вы писали:
К>>Не рухнет. (*) Будет создана копия объекта SomeCleverClass.
PP4>Замечательно. А Вы не просветите меня как это чудо реализовано? Немного покопался в исходниках, понял ничтожно мало.
О, это страшное дело.
Вкратце, так (исключительно вольное переложение устройства boost::function) :
Сперва — избавимся от излишнего ассортимента типов, приводя все функторы к одному виду
Естественно, что при этом мы потеряли три важных метода — вызов operator(), конструктор копирования и деструктор (для функциональных объектов).
Поэтому вынесем это умение...
void destroy_fun(any_ptr ap) {} // глобоальные функции невозможно разрушатьtemplate<class T> void destroy_ptr(any_ptr ap) { delete (T*)(ap.p); } // объекты - разрушаем с помощью delete
any_ptr copy_fun(any_ptr ap) { return ap; } // копирование сводится к копированию указателяtemplate<class T> any_ptr copy_ptr(any_ptr ap) { return make_any(new T(*(T*)(ap.p))); } // объект - конструируемtemplate<class R, class A1, class A2, .....>
R invoke_fun(any_ptr ap, A1 a1, A2 a2, ...) { return ((R(*)(A1,A2,...))(ap.f))(a1,a2,...); }
template<class T, class R, class A1, class A2, .....>
R invoke_ptr(any_ptr ap, A1 a1, A2 a2, ...) { return ((T*)(ap.p))->operator()(a1,a2,...); }
// обратите внимание: по типу T невозможно вывести типы аргументов и результата,
// поскольку у объекта могут быть несколько сигнатур operator().
... и будем хранить рядом с any_ptr
struct function_base_
{
any_ptr ap;
vfun copier; // здесь мы не теряем информацию о типе: её знает класс function<...>
vfun destroyer;
vfun invoker;
};
Поскольку эти три метода выступают вместе, можно сделать компактнее
enum action { to_copy, to_destroy, to_invoke };
template<class R, class A1, class A2, ...>
vfun manage_fun(any_ptr ap, action act)
{
switch(act)
{
case to_copy: return ap; // возвращает копиюcase to_destroy: return ap; // возвращает бессодержательное значениеcase to_invoke: return invoke_fun<R,A1,A2,...>; // возвращает функцию-пускатель
}
}
template<class T, class R, class A1, class A2, ...>
vfun manage_ptr(any_ptr ap, action act)
{
switch(act)
{
case to_copy: return make_any(new T(*(T*)ap.p));
case to_destroy: delete (T*)ap.p; return ap;
case to_invoke: return invoke_ptr<T,R,A1,A2,...>;
}
}
(Поскольку вызов функционального объекта нельзя свести к вызову функции — промежуточная N+1-арная функция-пускатель нам нужна).