Prev: Whole program optimization and debug symbols
Next: Static linking to MFC/CRT and Standard C++ libraries
From: Jack on 8 Apr 2010 08:08 Dear all, First some code snippets, ////////////////////////////////////////////////////////////////////////// class Thread { public: Thread(std::auto_ptr<Runnable> runnable_); Thread(); virtual ~Thread(); void start(); void *join(); private: HANDLE hThread; unsigned winThreadID; std::auto_ptr<Runnable> runnable; Thread(const Thread&); const Thread& operator = (const Thread&); void setCompleted(); void *result; virtual void *run() { return 0; } static unsigned WINAPI startThreadRunnable(LPVOID pVoid); static unsigned WINAPI startThread(LPVOID pVoid); void PrintError(LPTSTR lpszFunction, LPSTR fileName, int lineNumber); }; Thread::Thread(std::auto_ptr<Runnable> runnable_) : runnable(runnable_) { if (runnable.get() == NULL) PrintError("Thread(std::auto_ptr<Runnable> runnable_) failed at ", __FILE__, __LINE__); hThread = (HANDLE) _beginthreadex(NULL, 0, Thread::startThreadRunnable, (LPVOID) this, CREATE_SUSPENDED, &winThreadID); if (!hThread) PrintError("_beginthreadex failed at ", __FILE__, __LINE__); } Thread::Thread() : runnable(NULL) { hThread = (HANDLE) _beginthreadex(NULL, 0, Thread::startThread, (LPVOID)this, CREATE_SUSPENDED, &winThreadID); if (!hThread) PrintError("_beginthreadex failed at ", __FILE__, __LINE__); } unsigned WINAPI Thread::startThreadRunnable(LPVOID pVoid) { Thread *runnableThread = static_cast<Thread *>(pVoid); runnableThread->setCompleted(); return reinterpret_cast<unsigned>(runnableThread->result); } //// Destructor called before this function is. //// so the whole context gets destroyed //// but why did that happen? unsigned WINAPI Thread::startThread(LPVOID pVoid) { Thread *aThread = static_cast<Thread *>(pVoid); aThread->result = aThread->run(); aThread->setCompleted(); return reinterpret_cast<unsigned>(aThread->result); } Thread::~Thread() { if (winThreadID != GetCurrentThreadId()) { DWORD rc = CloseHandle(hThread); if (!rc) PrintError ("CloseHandle failed at ", __FILE__, __LINE__); } } void Thread::start() { assert(hThread != NULL); DWORD rc = ResumeThread(hThread); if (!rc) PrintError("ResumeThread failed at ", __FILE__, __LINE__); } void *Thread::join() { return result; } void Thread::setCompleted() { } ///////////////////////////////////////////////////////////////////////////////////////// class BFThread : public Thread { public: BFThread(int ID) : myID(ID) { } virtual void *run() { return reinterpret_cast<void *>(myID); } private: int myID; }; ////////////////////////////////////////////////////////////////////////////////// // main module std::auto_ptr<BFThread> thread1(new BFThread(1)); thread1->start(); int result1 = reinterpret_cast<int>(thread1->join()); /////////////////////////////////////////////////////////////////////////////// The errors are: First-chance exception at 0x004177c7 in GridPartition.exe: 0xC0000005: Access violation reading location 0xfeeefef2. Unhandled exception at 0x004177c7 in GridPartition.exe: 0xC0000005: Access violation reading location 0xfeeefef2. I wrote the comments above. Could anyone please check my code why the destructor is called before the startThread function is? Thanks Jack
From: Ulrich Eckhardt on 8 Apr 2010 08:47 Jack wrote: > void *Thread::join() > { > return result; > } This is missing a WaitForSingleObject() call to wait for the thread to terminate. Another comment: Take a look at Boost.Thread, which uses a slightly different design. There, you don't derive from a thread class in order to add your code to run in that thread. Similar to a file, its thread class is just a means to communicate with a thread, but the lifetime of the thread itself is independent thereof. Also, it doesn't require any code to derive from a "Runnable" baseclass either, it only requires the passed argument to be callable (e.g. a function pointer or a class with overloaded operator()) and copyable (so it can be given to the thread to start). Lastly, if e.g. a passed pointer is incorrectly zero, I would either assert or throw an exception. Just printing an error (PrintError) and continuing isn't going to help. Uli -- C++ FAQ: http://parashift.com/c++-faq-lite Sator Laser GmbH Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932
From: Jack on 8 Apr 2010 08:59 Thanks Ulrich for sheding lights on this!!! Jack
From: Alexander Grigoriev on 8 Apr 2010 10:32 Are you by any chance using Thread object on the stack? "Jack" <jl(a)knight.com> wrote in message news:Okgq%23Px1KHA.140(a)TK2MSFTNGP05.phx.gbl... > Dear all, > > First some code snippets, > ////////////////////////////////////////////////////////////////////////// > class Thread > { > public: > Thread(std::auto_ptr<Runnable> runnable_); > Thread(); > virtual ~Thread(); > void start(); > void *join(); > > private: > HANDLE hThread; > unsigned winThreadID; > std::auto_ptr<Runnable> runnable; > Thread(const Thread&); > const Thread& operator = (const Thread&); > void setCompleted(); > void *result; > virtual void *run() { return 0; } > static unsigned WINAPI startThreadRunnable(LPVOID pVoid); > static unsigned WINAPI startThread(LPVOID pVoid); > void PrintError(LPTSTR lpszFunction, LPSTR fileName, int lineNumber); > }; > > Thread::Thread(std::auto_ptr<Runnable> runnable_) : runnable(runnable_) > { > if (runnable.get() == NULL) > PrintError("Thread(std::auto_ptr<Runnable> runnable_) failed at ", > __FILE__, __LINE__); > hThread = (HANDLE) _beginthreadex(NULL, 0, Thread::startThreadRunnable, > (LPVOID) this, CREATE_SUSPENDED, &winThreadID); > if (!hThread) > PrintError("_beginthreadex failed at ", __FILE__, __LINE__); > } > > Thread::Thread() : runnable(NULL) > { > hThread = (HANDLE) _beginthreadex(NULL, 0, Thread::startThread, > (LPVOID)this, CREATE_SUSPENDED, &winThreadID); > if (!hThread) > PrintError("_beginthreadex failed at ", __FILE__, __LINE__); > } > > > unsigned WINAPI Thread::startThreadRunnable(LPVOID pVoid) > { > Thread *runnableThread = static_cast<Thread *>(pVoid); > runnableThread->setCompleted(); > return reinterpret_cast<unsigned>(runnableThread->result); > } > > //// Destructor called before this function is. > //// so the whole context gets destroyed > //// but why did that happen? > unsigned WINAPI Thread::startThread(LPVOID pVoid) > { > Thread *aThread = static_cast<Thread *>(pVoid); > aThread->result = aThread->run(); > aThread->setCompleted(); > return reinterpret_cast<unsigned>(aThread->result); > } > > Thread::~Thread() > { > if (winThreadID != GetCurrentThreadId()) > { > DWORD rc = CloseHandle(hThread); > if (!rc) > PrintError ("CloseHandle failed at ", __FILE__, __LINE__); > } > } > > void Thread::start() > { > assert(hThread != NULL); > DWORD rc = ResumeThread(hThread); > if (!rc) > PrintError("ResumeThread failed at ", __FILE__, __LINE__); > } > > void *Thread::join() > { > return result; > } > > void Thread::setCompleted() > { > } > ///////////////////////////////////////////////////////////////////////////////////////// > > class BFThread : public Thread > { > public: > BFThread(int ID) : myID(ID) { } > virtual void *run() > { > return reinterpret_cast<void *>(myID); > > > } > private: > > > int myID; > }; > > ////////////////////////////////////////////////////////////////////////////////// > > // main module > std::auto_ptr<BFThread> thread1(new BFThread(1)); > > thread1->start(); > > int result1 = reinterpret_cast<int>(thread1->join()); > > /////////////////////////////////////////////////////////////////////////////// > > The errors are: > First-chance exception at 0x004177c7 in GridPartition.exe: 0xC0000005: > Access violation reading location 0xfeeefef2. > Unhandled exception at 0x004177c7 in GridPartition.exe: 0xC0000005: Access > violation reading location 0xfeeefef2. > > > I wrote the comments above. Could anyone please check my code why the > destructor is called before the startThread function is? > Thanks > Jack > > >
From: Jack on 9 Apr 2010 06:37 Hi Alex, > Are you by any chance using Thread object on the stack? Ummm.... I set out the thread as a local variable of the method, I vaguely remember one of you said that although the var is on the stack, the thread itself should be on the heap... no? correct me if I am wrong... Thanks Jack
|
Next
|
Last
Pages: 1 2 3 Prev: Whole program optimization and debug symbols Next: Static linking to MFC/CRT and Standard C++ libraries |