Вопрос

Я пишу программу MT для Linux в C ++, и я хочу знать, как выполняется отмена потока.

Насколько я понимаю, когда потока отменена функциями очистки, называются функцией потока, а функция потока вынуждена выйти. Это означает две вещи:

  1. Когда резьба отменяется, она все еще вызывает разрушители для всех объектов C ++, созданные внутри функции потока.
  2. Я могу перейти к функциям очистки указателей на объекты, созданные в функции потока.

Я прав и код ниже плохо работаю просто хорошо?


Еще один вопрос в коде ниже, когда нить отменится где-то в Раздел А., second_Thread_cleanup_function () будет называться первым, верно?

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);
}
Это было полезно?

Решение

При любом современном распределении Linux с использованием NPTL (который на практике означает любое запуск ядра 2.6), NPTL будет вызывать разрушитель и раскрутить стек псевдо исключением.

На самом деле NPTL настаивает на этом, реализуя то, что он называет вынужденным раскручиванием стека. Вы можете поймать псевдо исключение с CALL (...), но если вы это сделаете, вы должны впоследствии, вы должны впоследствии его обратиться или весь процесс будет прекращен.

Крис

Другие советы

Деструкторы будут призваны только предполагать, что вам бесплатные выделенные объекты в методах очистки. В противном случае нет.

И да, у вас есть порядок вызовов очистки в разделе правильный.

Утверждение о том, что стек отмененного потока не размотал - в результате чего не разрушается локальные объекты - несовместимо с утверждением @chris, что стек потока расстегивается и со следующим приведенным в систему:

#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();
}

При выполнении вышеуказанная программа указывает, что деструктор локального объекта, действительно, вызывается, когда поток отменяется:

$ ./a.out 
Obj() called
cleanup() called
~Obj() called
$ 
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top