Domanda

Sto scrivendo programma di MT per Linux in C ++ e voglio sapere come viene eseguita la cancellazione thread.

Per quanto comprendo quando il filo è cancellata funzioni di pulizia vengono chiamate all'interno funzione del filo e la funzione del filo è costretto a uscire. Questo significa due cose:

  1. Quando il filo viene annullata chiama ancora distruttori fo tutti C ++ oggetti creati all'interno funzione del thread.
  2. I può passare a funzioni di pulizia puntatori a oggetti creati in funzione del thread.

Ho ragione e il codice sottostante il lavoro male che bene?


Ancora una domanda in codice qui sotto, quando il filo viene annullata da qualche parte nel A , second_thread_cleanup_function () sarà chiamato prima, giusto?

class SomeObject
{
    public:
        ~SimpleObject (void); // <- free dynamically allocated memory

        void finalize (void);

        // ...
}

void first_thread_cleanup_function (void* argument)
{
    SomeObject* object (argument);

    object->finalize ();
}

void second_thread_cleanup_function (void* argument)
{
    // ... do something ...
}

void* thread_function (viod* argument)
{
    SomeObject object;

    pthread_cleanup_push (first_thread_cleanup_function, &object);

    // ... some code ...

    pthread_cleanup_push (second_thread_cleanup_function, NULL);
    // ... SECTION A ...
    pthread_cleanup_pop (0);

    // .. some code ...

    pthread_cleanup_pop (1);
}
È stato utile?

Soluzione

Con qualsiasi moderna distribuzione Linux usando NPTL (che in pratica significa qualsiasi esecuzione di un kernel 2.6), NPTL chiamerà distruttori e distendersi lo stack con uno pseudo-eccezione.

Infatti NPTL insiste su di esso, attuando ciò che definisce pila forzato svolgimento. È possibile prendere la pseudo-eccezione con catch (...), ma se lo fate è necessario in seguito rigenerare o l'intero processo sarà terminato.

Chris

Altri suggerimenti

I distruttori sarà chiamato solo a patto di liberare gli oggetti allocati nei metodi di pulizia. In caso contrario, no.

E sì, avete l'ordine delle chiamate di pulizia nella sezione A corretta.

L'asserzione che stack di un thread cancellato non viene srotolato - conseguente non distruzione di oggetti locali - è incompatibile con l'affermazione @ Chris che stack del thread viene svolta e con il seguente controesempio:

#include <climits>
#include <iostream>
#include <pthread.h>
#include <thread>
#include <unistd.h>

class Obj {
public:
    Obj()  { std::clog << "Obj() called\n"; }
    ~Obj() { std::clog << "~Obj() called\n"; }
};

static void cleanup(void* arg) {
    std::clog << "cleanup() called\n";
}

static void run() {
    Obj obj{}; // Local object
    pthread_cleanup_push(cleanup, nullptr);
    ::pause(); // Thread cancelled here
    pthread_cleanup_pop(1);
}

int main(int argc, char **argv) {
    std::thread thread([]{run();});
    ::sleep(1);
    ::pthread_cancel(thread.native_handle());
    thread.join();
}

Quando viene eseguito, il programma precedente indica che il distruttore dell'oggetto locale è, infatti, chiamata quando il filo viene annullata:

$ ./a.out 
Obj() called
cleanup() called
~Obj() called
$ 
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top