Je veux tuer un std:: thread en utilisant son objet thread? [dupliquer]

possibilité de dupliquer:

C++0x interruption du fil

j'essaie de tuer/arrêter un c++ std::thread en utilisant son objet thread.

Comment faire?

24
demandé sur Community 2012-12-15 18:28:40

2 réponses

la réponse de @bamboon est bonne, mais je pense que cela mérite une déclaration plus forte.

quelle que soit la langue que vous utilisez, votre programme va acquérir et libérer des ressources: mémoire, descripteurs de fichiers, ... Pour les programmes simples qui sont tirés en un coup, la fuite des ressources n'a pas beaucoup d'importance: lorsque le programme se termine OSS moderne automatiquement reprendre les ressources; cependant, pour les programmes à long terme une exigence de base est de ne pas laisser des ressources, ou du moins pas répétitive.

par conséquent, vous auriez dû être enseigné dès le début que lorsque vous acquerrez une ressource, vous devrez vous assurer qu'elle est libérée à un moment donné:

void foo(int i) {
    int* array = malloc(sizeof(int) * i);

    /* do something */

    free(array);
}

alors, posez-vous la question:

  • ce qui se passe quand je tue le programme ?
  • que se passe-t-il quand je coupe le fil ?

Eh bien, comme nous l'avons dit, quand un programme se termine l'OS rassemble les ressources de retour, donc en supposant (et c'est une certaine hypothèse) que vous n'avez pas acquis une ressource sur un autre système ou que ce système est bien protégé contre un tel abus, aucun mal, aucune faute.

cependant, quand vous tuez un thread, le programme tourne toujours, donc le système D'exploitation ne récupère pas les ressources. Vous avez laissé échapper de la mémoire, vous avez verrouillé un fichier pour écrire que vous ne pouvez plus déverrouiller,... Tu ne tueras pas threads .

les langues de niveau supérieur ont un moyen de gérer cela: les exceptions. Parce que les programmes doivent être sûrs d'exception de toute façon, Java (par exemple) va tuer un thread en le mettant en pause, en lançant une exception au point d'exécution, et décompresser doucement la pile. Cependant, il n'y a pas encore de telle facilité en C++.

est-ce impossible ? Non, non, évidemment. En fait, vous pourriez parfaitement réutiliser la même idée:

  • encapsulé std::thread , interruptible_thread classe contiendra également un drapeau d'interruption
  • passer l'adresse du drapeau à std::thread lors de sa mise à l'eau, et le stocker dans un thread-local way
  • enregistrez votre code avec des check-points où vous vérifiez si le drapeau d'interruption est activé ou non, et quand il est jeté une exception

C'est-à-dire:

// Synopsis
class interrupt_thread_exception;
class interruptible_thread;
void check_for_interrupt();

// Interrupt exception
class interrupt_thread_exception: public virtual std::exception {
public:
    virtual char const* what() const override { return "interrupt"; }
}; // class interrupt_thread_exception

// Interruptible thread
class interruptible_thread {
public:
    friend void check_for_interrupt();

    template <typename Function, typename... Args>
    interruptible_thread(Function&& fun, Args&&... args):
        _thread([](std::atomic_bool& f, Function&& fun, Args&&... args) {
                    _flag_ref = &f; fun(std::forward<Args>(args)...);
                },
                _flag,
                std::forward<Function>(fun),
                std::forward<Args>(args)...)
    {}

    bool stopping() const { return _flag.load(); }

    void stop() { _flag.store(true); }

private:
    static thread_local std::atomic_bool* _flag_ref = nullptr;

    std::atomic_bool _flag = false;
    std::thread _thread;
}; // class interruptible_thread

// Interruption checker
inline void check_for_interrupt() noexcept(false) {
    if (not interruptible_thread::_flag_ref) { return; }
    if (not interruptible_thread::_flag_ref->load()) { return; }

    throw interrupt_thread_exception();
} // check_for_interrupt

maintenant vous pouvez simplement saupoudrer votre code fileté avec vérifier l'interruption aux endroits appropriés.

37
répondu Matthieu M. 2012-12-15 17:58:56

vous ne pouvez pas.

std::threads ne sont pas interruptibles. Vous pouvez utiliser boost::thread qui offre cette fonctionnalité.

Boost le fait en définissant les "points d'interruption" sur lesquels le fil se terminera s'il est interrompu et atteint un tel point.

néanmoins, la plupart du temps de penser à une refonte pourrait être le moyen le plus propre et le plus facile d'atteindre ce que vous essayez d'atteindre.

si vous êtes toujours à la recherche d'une implémentation C++11 de threads interruptibles vérifier le livre D'Anthony Williams (propriétaire de boost thread) "C++ concurrence en Action". Il passe par une mise en œuvre de base de la façon dont une telle chose peut être réalisée.

std::thread::native_handle vous donne accès à la poignée de thread sous-jacente spécifique à la plate-forme qui pourrait supporter l'interruption, mais cette approche rend votre code non portable et probablement pas plus propre d'aucune façon.

23
répondu inf 2015-10-13 16:23:48