Boost logo

Boost :

From: Ninel Evol (myLC_at_[hidden])
Date: 2007-07-05 08:19:54


Dear Boosters and C++ affectionados,

one thing that C++ is missing amongst many others is the
possibility to abort a thread in a clean fashion (so that
the thread itself, i.e. the object will do the cleanup).
The need for this arises virtually every time you use a
background thread for doing the work (for example
computations).
Currently, you can have the thread check for an abort
request every once in a while (bad), or you can just kill
that sucker and do the cleanup in the main thread (not that
nice either).
A clean alternative would be if the main thread were able to
"provoke" an exception in the worker thread. This "abort-
request-exception" could than be caught by the worker
thread. It could thereby do the entire cleanup itself
(object-oriented).

I added a little example below. The example is for Windows
and VCPP (sorry for that). You can do the same in Linux by
stopping the thread via pthread_kill(id,SIGSTOP) and then
manipulating the EIP (see thread_info.h), but of course it's
a bit messy due to the kernel includes, etc...

Once you think about it, all you need in triggering
exceptions in another thread is really an abort request.
It could be either asynchronous or synchronized (mutex, with
return value?). That's all you need - almost always though.
The main thread handles the GUI and you almost always want
the user to be able to abort operations. The smoothest way
to implement this GUI-scheme is with worker threads, the
downside being the lack of C++ support, currently.

Different topic:
================
I read that some folks thought about the wxWidgets and the
Boost (C-0x) team joining forces.
I think that would be a marvelous idea!

Currently the STL is quite useless. It basically serves for
supporting book examples. For everything else you need
either thread, network or GUI support (often all of them).
As a result you have to use some library (wxWidgets, Qt).
These of course all replace the STL completely - usually
lacking some of those nice things the STL comes with (like
exceptions). In other words: C-0x without GUI, thread and
network support will just as well remain in the shadows of
libraries providing that crucial functionality, sadly
ignoring various accomplishments.

Hold on, just cut my finger... Xo|
Well, that's it anyway. Feel free to comment, as you like
(as long as it doesn't relate to cutting fingers)!

Blood waving,
                               LC (myLC_at_[hidden])

Windows example (VCPP):
=======================

#define WIN32_LEAN_AND_MEAN
#include <tchar.h>
#include <iostream>
#include <windows.h>
#include <signal.h>

enum ThreadException { THREAD_ABORT_REQUEST };
DWORD threadID;
unsigned long i;
DWORD WINAPI ThreadFunction( LPVOID lpParam ) {
        try {
                for( ; i < 50; ++i) {
                        std::cout << "Thead counting " << i << "..."
                                  << std::endl;
                        Sleep( 1000 );
                }
                std::cout << "Thead has finished counting." << std::endl;
                return 0;
        } catch( ThreadException e ) {
                if( e == THREAD_ABORT_REQUEST ) {
                        std::cout << "Thread aborted." << std::endl;
                        return 42;
                }
                else
                        std::cerr << "Oops - unknown thread-exception"
                                  << std::endl;
        } catch( ... ) {
                std::cerr << "Unknown exception caught in thread!"
                          << std::endl;
        }
        return 1;
}

__declspec( naked ) void throwAbort( void ) {
        throw THREAD_ABORT_REQUEST;
}

int _tmain( int argc, _TCHAR* argv[] ) {
        HANDLE threadHandle =
                CreateThread( 0, 0, ThreadFunction, 0, 0, &threadID );
        if( !threadHandle ) {
                std::cerr << "Failed to create thread." << std::endl;
                return -1;
        }
        Sleep( 5000 );
        if( SuspendThread( threadHandle ) == 0xFFFFFFFF ) {
                std::cerr << "Failed to suspend thread." << std::endl;
                return -2;
        }
        CONTEXT threadContext;
        threadContext.ContextFlags = CONTEXT_CONTROL;
        if( !GetThreadContext( threadHandle, &threadContext ) ) {
                std::cerr << "Failed to retrieve thread context."
                          << std::endl;
                return -3;
        }
        threadContext.Eip = ( DWORD )throwAbort;
        if( !SetThreadContext( threadHandle, &threadContext ) ) {
                std::cerr << "Failed to set a new thread context."
                          << std::endl;
                return -4;
        }
        if( ResumeThread( threadHandle ) == 0xFFFFFFFF ) {
                std::cerr << "Failed to resume thread." << std::endl;
                return -5;
        }
        Sleep( 3000 );
        DWORD threadExitCode;
        if( !GetExitCodeThread( threadHandle, &threadExitCode ) ) {
                std::cerr << "Failed to get the thread's exit code."
                          << std::endl;
                return -6;
        }
        std::cout << "The thread returned the exit code "
                  << threadExitCode << "." << std::endl;
        return 0;
}

-- 
Ist Ihr Browser Vista-kompatibel? Jetzt die neuesten 
Browser-Versionen downloaden: http://www.gmx.net/de/go/browser

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk