2012-08-17 3 views
0

J'ai une implémentation de rappel dans laquelle une tierce partie inconnue appelle un pointeur de fonction dans mon code. Cependant, un problème dans plusieurs langues déclenche le code après le retour d'une fonction. Par exemple, lorsqu'un rappel est appelé et que je dois supprimer l'objet appelant (et, dans ce cas, le ré-initialiser), le retour du rappel entraînerait une exception.Stratégie d'exécution différée en C++

En supposant que je ne puisse pas connecter et que je ne possède pas/ne puisse pas modifier le code appelant le rappel, quelle est la meilleure façon d'exécuter du code après le retour d'une fonction?

La seule façon réelle de faire cela est de mettre en place une sorte de machine d'état et de faire vérifier par un thread de travail l'état. Cependant, le problème que je prévois avec ceci est celui d'une condition de concurrence, où un rappel est appelé entre le moment où le rappel de réinitialisation revient et le point où l'objet appelant est réinitialisé.

Y at-il une sorte de fonctionnalité que je ne connais pas, ou ce serait le moyen le plus efficace d'atteindre un tel résultat?

+1

Quel est exactement le « objet appelant »? Êtes-vous en train de dire qu'un code faisant partie de l'objet X appelle une fonction dans votre code et que votre fonction est censée supprimer l'objet X? Si oui, * quand *? L'objet X est clairement encore utilisé lorsque la fonction est appelée, alors certainement pas. –

+0

@DavidSchwartz - C'est exactement ce qui se passe. – Qix

+1

Oui, vous avez donc un problème de conception. Votre API ne vous donne aucun moyen de savoir quand l'objet peut être supprimé en toute sécurité. Donc, soit corriger l'API ou accepter que vous aurez toujours une condition de concurrence. –

Répondre

1

Cela nécessite C++ 11 ou plus récent. Mais voici comment je le ferais. Vous pouvez réécrire à utiliser des pointeurs de fonction à la place de telle sorte que cela fonctionne sur les anciennes versions C++

#include <functional> 
#include <iostream> 

#define CONCACT_IMPL(x , y) x##y 
#define CONCAT(x, y) CONCACT_IMPL(x, y) 
#define deffered(x) auto CONCAT(__deffered, __COUNTER__) = Defer(x); 

struct Defer { 
    Defer(std::function<void(void)> pFunc) : func(pFunc) {}; 
    std::function<void(void)> func; 
    virtual ~Defer(){ 
     func(); 
    } 
}; 

int main() { 

    deffered([]() { 
     std::cout << "deffered" << std::endl; 
    }); 

    std::cout << "now" << std::endl; 
} 

sorties ->

now 
deffered 
+1

Cela ne correspond pas à la cas d'utilisation dans l'OP spécifiquement (je me souviens du problème que j'avais il y a quelques temps et il n'est tout simplement pas possible de faire ce que je voulais). Je vais accepter cela car c'est un modèle que j'ai utilisé auparavant. – Qix