Здравствуйте, Кодт, Вы писали:
К>Использовать функторы, например, boost::function + boost::bind.
Сочинил вот такой код, только вот почему-то не могу скомпилить его.
class IRefCounter
{
public:
virtual void AddRef() = 0 ;
virtual void Release() = 0 ;
};
// Макросы - фукнции реализации IRefCounter
#define REF_COUNTER_IMPLEMENTATION \
private: \
int m_iCntr ; \
public: \
virtual void AddRef() \
{ \
++m_iCntr ; \
} \
virtual void Release() \
{ \
if ( --m_iCntr <= 0 ) \
{ \
delete this ; \
} \
}
#define REF_COUNTER_INIT m_iCntr( 0 )
// Поток будет вызывать эту функцию
class ICall : public IRefCounter
{
public:
virtual void Call() = 0 ;
// virtual void Exception( std::exception& st ) = 0 ; ... наметки
};
// Это фукнция потока
enum { WM_CALL = WM_USER } ;
DWORD WINAPI ThrFunc( LPVOID pParam )
{
MSG msg ;
while ( GetMessage( &msg, 0, 0, 0 ) )
{
if ( msg.message == WM_CALL ) // Надо совершить вызов
{
ICall * pCall = ( ICall * ) msg.lParam ;
try
{
pCall->Call() ; // совершаем
if ( msg.wParam )
{
SetEvent( (HANDLE) msg.wParam ) ;
}
pCall->Release() ;
}
catch ( std::exception& )
{
//pCall->Exception( st ) ;
}
}
}
return 0 ;
}
// Вызов неконстантной фукнции, возвращающей значение (не void), с двумя параметрами.
template< class _R, class BinOp, class _A1, class _A2 >
class CFunction2 : public ICall
{
REF_COUNTER_IMPLEMENTATION
public:
CFunction2( const BinOp& obj, _R ( BinOp::*pfn)(_A1,_A2), _A1 arg1, _A2 arg2 )
: m_obj( obj )
, m_pfn( pfn )
, m_arg1( arg1 )
, m_arg2( arg2 )
, REF_COUNTER_INIT
{}
virtual void Call()
{
m_result = (m_obj.*m_pfn)( m_arg1, m_arg2 ) ;
}
typedef _R result_type ;
_R m_result ;
protected:
BinOp m_obj ;
_R ( BinOp::*m_pfn )(_A1,_A2) ;
_A1 m_arg1 ;
_A2 m_arg2 ;
} ;
template< class _R, class BinOp, class _A1, class _A2 >
CFunction2< _R, BinOp, _A1, _A2 > * Function2( const BinOp& obj, _R ( BinOp::*pfn)(_A1,_A2), _A1 arg1, _A2 arg2 )
{
CFunction2< _R, BinOp, _A1, _A2 > * p = new CFunction2< _R, BinOp, _A1, _A2 >( obj, pfn, arg1, arg2 ) ;
p->AddRef() ;
return p ;
}
// Также надо сделать.
// const_Function2, void_Function2, const_void_Function2... или механизм для void использовать (я уже встречал варианты реализации)
// И тоже самое для Function0, Function1, Function3 и, далее по мере необходимости.
class CTmp
{
public:
int func2( int a, int b )
{
return a+b ;
}
};
// Поток обслуживающий эти вызовы.
class CCaller
{
DWORD dwThrId ;
HANDLE hThread ;
public:
// Конструктор - создаем поток.
CCaller()
{
hThread = CreateThread( NULL, 0, ThrFunc, NULL, 0, &dwThrId ) ;
Sleep( 1000 ) ;
}
// Деструктор - завершаем его.
~CCaller()
{
PostThreadMessage( dwThrId, WM_QUIT, 0, 0 ) ;
WaitForSingleObject( hThread, INFINITE ) ;
CloseHandle( hThread ) ;
}
// Совершить вывов функции нашем потоке.
template< class BinObj >
void Call( BinObj * pCall )
{
PostThreadMessage( dwThrId, WM_CALL, 0, ( LPARAM ) ( ICall * ) pCall ) ;
}
// Совершить вызов функции в потоке с ожиданием результата.
template< class BinObj >
typename BinObj::result_type Call_Wait( BinObj * pCall )
{
HANDLE hEvent = CreateEvent( NULL, FALSE, FALSE, NULL ) ;
pCall->AddRef() ;
PostThreadMessage( dwThrId, WM_CALL, ( WPARAM )hEvent, ( LPARAM ) ( ICall * ) & pCall ) ;
WaitForSingleObject( hEvent, INFINITE ) ;
CloseHandle( hEvent ) ;
typename BinObj::result_type res = rCall.m_result ;
rCall.Release() ;
return res ;
}
};
int main(int argc, char* argv[])
{
CTmp tmp ;
CCaller caller ;
int res = caller.Call_Wait( Function2( tmp, &CTmp::func2, 2, 2 ) ) ;
/*
В строке выше - ошибка.
error C2893: Failed to specialize function template 'generic-type-271 __thiscall CCaller::Call_Wait(BinObj *)'
With the following template arguments:
'class CFunction2<int,class CTmp,int,int>'
*/
caller.Call( Function2( tmp, &CTmp::func2, 2, 2 ) ) ;
return 0;
}
В чем ошибка, подскажите, а то у меня уже....
Как вам вообще такая реализация.
Заранее благодарен.