thread function ohne boost::bind



  • hi,

    #include <process.h>
    #include <windows.h>
    #include <iostream> 
    using namespace std;
    
    class MyThreadClass
    {
    public:
     void WorkFunction(void);
    };
    
    void MyThreadClass::WorkFunction(void)
    {
     cout << "Thread called" << endl;
    }
    
    void ThreadFunction(void *pParam)
    {
     MyThreadClass *mt = (MyThreadClass*)pParam;
     mt->WorkFunction();
    
     _endthread();
    }
    
    void main(void)        // Primary Thread
    {
     MyThreadClass mt;
    
     _beginthread(ThreadFunction,   // Pointer to Thread Function
         0,     // Stack Size set automatically
         &mt);    // Parameter: Pointer to Instance
    
     Sleep(10000);
    }
    

    ich moechte im obrigen beispiel diesen unschoenen cast verhindern:
    MyThreadClass *mt = (MyThreadClass*)pParam;
    mt->WorkFunction();
    die thread function soll aber auch nicht static in der class sein!!!

    dachte an sowas like boost::bind:

    #include <process.h>
    #include <windows.h>
    #include <iostream> 
    #include <functional>
    #include <algorithm> 
    using namespace std;
    
    class MyThreadClass
    {
    public:
    	void WorkFunction(void) {
    		cout << "Thread called" << endl;
    	}
    };
    
    void main(void)								// Primary Thread
    {
    	MyThreadClass mt;
    
    	_beginthread(std::bind1st (std::mem_fun1 (&MyThreadClass::WorkFunction), &mt),			// Pointer to Thread Function
    				 0,					// Stack Size set automatically
    				 &mt);				// Parameter: Pointer to Instance
    
    	Sleep(10000);
    }
    

    error:

    c:\temp\thread_test\thread_test\main.cpp(26) : error C2784: 'std::mem_fun1_t<_Result,_Ty,_Arg> std::mem_fun1(_Result (__thiscall _Ty::* )(_Arg))' : could not deduce template argument for '_Result (__thiscall _Ty::* )(_Arg)' from 'void (__thiscall IMyThreadClass::* )(void)'
            c:\program files\microsoft visual studio 8\vc\include\functional(604) : see declaration of 'std::mem_fun1'
    


  • Kann man nicht verhindern



  • koennte ja ne art boost::bind nachbauen?

    die verwenden ja intern auch ne art: std::bind1st (std::mem_fun1 ... ?

    cu



  • Wird dir nichts bringen, weil _beginthread keinen Fuktor annehmen wird.



  • soll ich createThread nehmen? hm. was ruft boost unter windows dann auf? createThread?



  • Boost regelts auch über eine einfache Funktion:

    DWORD WINAPI ThreadProxy(LPVOID args)
    {
        ThreadProxyData* data=reinterpret_cast<ThreadProxyData*>(args);
        DWORD ret=data->start_address_(data->arglist_);
        delete data;
        return ret;
    }
    
    // ...
    
    HANDLE hthread=CreateThread(static_cast<LPSECURITY_ATTRIBUTES>(security),stack_size,ThreadProxy,
            new ThreadProxyData(start_address,arglist),initflag,&threadID);
    
    // ...
    

    Zu deinem Compilierfehler. Du kannst bind1st nicht auf eine Methode mit keinem Parameter anwenden! 😉



  • das ist ja genau was ich verhindern wollte:)

    MyThreadClass *mt = (MyThreadClass*)pParam;
    mt->WorkFunction();
    


  • cpp1 schrieb:

    das ist ja genau was ich verhindern wollte:)

    MyThreadClass *mt = (MyThreadClass*)pParam;
    mt->WorkFunction();
    

    Das ist genau das was du nicht verhindern kannst!



  • @cpp1:
    Die "trampoline-function" brauchst du immer, ob nun in einer library gekapselt oder selbst geschrieben, aber ohne die geht nix - das OS kennt nunmal kein C++, und damit kennen OS-threads auch kein C++.

    @David_pb:
    Boost.Thread verwendet normalerweise _beginthreadex und nicht CreateThread. Die Stelle mit CreateThread die du gepostet hast ist Teil der Ersatzfunktion für Windows CE, wo es _beginthreadex nicht gibt 😉

    (Ich hab's nachgesehen weil es mir komisch vorkam, ich hab' mir den Boost.Thread Code schon vor längerem etwas angesehen und hatte noch in Erinnerung dass da _beginthreadex und nicht CreateThread verwendet wird.)



  • Ups, stimmt! 🙂 Aber _beginthreadex verwendet genauso eine Funktion:

    extern "C" {
    #if defined(BOOST_HAS_WINTHREADS)
        unsigned __stdcall thread_proxy(void* param)
    #elif defined(BOOST_HAS_PTHREADS)
            static void* thread_proxy(void* param)
    #elif defined(BOOST_HAS_MPTASKS)
            static OSStatus thread_proxy(void* param)
    #endif
        {
            try
            {
                thread_param* p = static_cast<thread_param*>(param);
                boost::function0<void> threadfunc = p->m_threadfunc;
                p->started();
                threadfunc();
    #if defined(BOOST_HAS_WINTHREADS)
                on_thread_exit();
    #endif
            }
            catch (...)
            {
    #if defined(BOOST_HAS_WINTHREADS)
                on_thread_exit();
    #endif
            }
    #if defined(BOOST_HAS_MPTASKS)
            ::boost::detail::thread_cleanup();
    #endif
            return 0;
        }
    
    }
    

    Im Prinzip kommts also quasi aufs Gleiche raus! 😉


Log in to reply