¿Por qué no puedo interrumpir este boost::thread en particular?

Tengo dos pruebas para interrumpir un boost::thread. Uno funciona, el otro no. puede alguien decirme por que?

Trabajando:

#include <iostream>
#include <string>
#include <boost/thread.hpp>
#include <boost/chrono.hpp>
#include <unistd.h>

using namespace std;

void Run(void)
{
    try
    {
        cout << "Run()\n";
        for ( int i = 0; i < 1000; i++ )
        {
            cout << "Thread: " << i << endl;
            boost::this_thread::sleep(boost::posix_time::milliseconds(500));
        }
    } catch (...)
    {
        cout << "INTERRUPTED!\n";
    }
    cout << "Thread returning.\n";
};

int main()
{
    boost::thread my_thread(Run);
    sleep(1);
    cout << "Main() sleeping\n";
    sleep(1);
    cout << "Main() interrupting the thread\n";
    my_thread.interrupt();
    sleep(1);
    cout << "Main() bye!!\n";
}

Compile así: g++ test1.cpp -lboost_thread -lboost_system; ./a.out

La salida es:

Run()
Thread: 0
Thread: 1
Main() sleeping
Thread: 2
Thread: 3
Main() interrupting the thread
INTERRUPTED!
Thread returning.
Main() bye!!

roto:

#include <iostream>
#include <string>
#include <boost/thread.hpp>
#include <boost/chrono.hpp>
#include <unistd.h>

using namespace std;

class CThread
{
public:
    void Interrupt() { cout << "calling interrupt\n"; ThreadHandle.interrupt(); }

protected:
    static unsigned int Init(void * process);
    virtual int Run(void) =0;
    void StartThread(void);
    boost::thread ThreadHandle;
};

unsigned int CThread::Init(void * process)
{
    cout << "Init()\n";
    return ((CThread *)process)->Run();
}

void CThread::StartThread(void)
{
    boost::thread ThreadHandle(CThread::Init, this);
}

class my_thread_class : public CThread
{
    public:
    my_thread_class();

    int Run(void)
    {
       cout << "Run(), thread running\n";
        for ( int i = 0; i < 1000; i++ )
        {
            cout << "Thread: " << i << endl;
            boost::this_thread::sleep(boost::posix_time::milliseconds(200));
        }
        cout << "Thread returning.\n";
        return 0;
    };
};

my_thread_class::my_thread_class()
{
    StartThread();
}

int main()
{
    my_thread_class my_thread;
    sleep(1);
    cout << "Main() sleeping\n";
    sleep(2);
    cout << "Main() interrupting the thread\n";
    my_thread.Interrupt();
    sleep(5);
    cout << "Main() bye!!\n";
}

La misma compilación, y la salida rota es:

Init()
Run(), thread running
Thread: 0
Thread: 1
Main() sleeping
Thread: 2
Thread: 3
Main() interrupting the thread
calling interrupt
Thread: 4
Thread: 5
Main() bye!!

Así que no parece interrumpir en mi caso roto.

preguntado el 27 de julio de 12 a las 16:07

1 Respuestas

Debido a que el ThreadHandle el objeto no es el que comenzaste para el hilo.

class CThread
{
public:
    void Interrupt() { cout << "calling interrupt\n"; ThreadHandle.interrupt(); }

protected:
    static unsigned int Init(void * process);
    virtual int Run(void) =0;
    void StartThread(void);

    // This is a member object
    boost::thread ThreadHandle;
};

void CThread::StartThread(void)
{
    // This is _not_ the member object, you have just hidden
    // the member object with an automatic object of the same
    // name.  This works, because boost::thread doesn't stop
    // the thread when it goes out of scope, it just disconnects
    // boost::thread ThreadHandle(CThread::Init, this);

    // renamed to avoid hiding the member variable.
    boost::thread started_thread(CThread::Init, this);

    // Since you want your member object to actually represent the 
    // thread you started, you should be able to do this:
    ThreadHandle.swap(started_thread);

    // Now your member ThreadHandle, should be associated with the 
    // thread as you expected.
}

Respondido 27 Jul 12, 16:07

Sí... después de publicarlo me obligó a volver a leer mi código. Solo he estado haciendo C ++ durante unos días, por lo que todavía estoy un poco inseguro sobre cómo funciona la "magia". ¿Debo almacenar una referencia de puntero a él en su lugar? ¿Puedo crear una &referencia a él? - señor apestoso

He actualizado mi respuesta. Puede almacenar un puntero (sugiero boost::scoped_ptr or std::unique_ptr), o utilice el swap método que he descrito anteriormente. - Chad

El método de intercambio funciona. Gracias por ayudarme, muy apreciado. Es bueno terminar el trabajo un viernes con algo funcionando. ;) - señor apestoso

Además, puedo decir: ThreadHandle = boost::thread(CThread::Init, this); para pasar el objeto hilo fuera del contexto. - señor apestoso

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.