Cycle de vie d’un agent
Un agent gAgent passe par une série d”états bien définis, du démarrage jusqu’à la suppression. Comprendre ces états est essentiel pour concevoir des agents robustes.
Les états d’un agent
┌─────────┐ init() ┌────────┐ doActivate() ┌────────┐
│ CREATED │────────────►│ INITED │───────────────►│ ACTIVE │
└─────────┘ └────────┘ └────┬───┘
│
┌─────────────────────────────────────┤
│ │
doSuspend() doWait()
│ │
▼ ▼
┌───────────┐ ┌─────────┐
│ SUSPENDED │ │ WAITING │
└─────┬─────┘ └────┬────┘
│ doWake() │ doWake()
└──────────────┐ ┌────────────────┘
▼ ▼
┌────────┐ doDelete() ┌─────────┐
│ ACTIVE │─────────────►│ DELETED │
└────────┘ └─────────┘
État |
Signification |
|---|---|
|
Agent créé, behaviours démarrés, en attente d’enregistrement AMS |
|
Agent enregistré, toutes ses activités tournent normalement |
|
Tous les behaviours sont mis en pause (conservent leur état interne) |
|
L’agent attend un événement extérieur avant de reprendre |
|
L’agent est en cours de migration vers une autre machine |
|
L’agent a terminé son cycle de vie, ses ressources sont libérées |
Suspendre et reprendre
doSuspend() met en pause tous les behaviours de l’agent. Ils ne
consomment plus de ressources mais conservent leur état interne. Utile
pour « mettre sur pause » un agent le temps qu’une condition externe
soit remplie.
doWake() reprend l’exécution depuis l’état où elle avait été
suspendue.
#include <gagent/core/Agent.hpp>
#include <gagent/core/Behaviour.hpp>
#include <gagent/core/AgentCore.hpp>
using namespace gagent;
class TravailPeriodique : public TickerBehaviour {
int compteur_ = 0;
public:
TravailPeriodique(Agent* ag)
: TickerBehaviour(ag, 1000) {} // tick toutes les secondes
void onTick() override {
compteur_++;
std::cout << "[Agent] tick n°" << compteur_ << "\n";
if (compteur_ == 3) {
std::cout << "[Agent] je me suspends 5 secondes\n";
this_agent->doSuspend();
// Dans un vrai système : un autre thread ou agent
// appellera doWake() 5 secondes plus tard.
// Ici on simule avec un thread séparé :
std::thread([ag = this_agent]() {
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "[External] réveil de l'agent\n";
ag->doWake();
}).detach();
}
if (compteur_ == 6) {
std::cout << "[Agent] travail terminé, suppression\n";
this_agent->doDelete();
}
}
};
class MonAgent : public Agent {
public:
void setup() override {
addBehaviour(new TravailPeriodique(this));
}
};
Résultat attendu :
[Agent] tick n°1
[Agent] tick n°2
[Agent] tick n°3
[Agent] je me suspends 5 secondes
[External] réveil de l'agent
[Agent] tick n°4
[Agent] tick n°5
[Agent] tick n°6
[Agent] travail terminé, suppression
Attendre un événement avec doWait()
doWait() est sémantiquement proche de doSuspend() mais signale
explicitement que l’agent attend un événement (une réponse, une
ressource disponible, un verrou libéré). Un autre agent peut alors
envoyer un message de réveil.
class AgentCoordinateur : public Agent {
public:
void setup() override {
addBehaviour(new AttenteDeFichier(this));
}
};
class AttenteDeFichier : public CyclicBehaviour {
bool fichier_disponible_ = false;
public:
AttenteDeFichier(Agent* ag) : CyclicBehaviour(ag) {}
void action() override {
if (!fichier_disponible_) {
std::cout << "[Coord] en attente du fichier...\n";
this_agent->doWait();
// L'exécution reprend ici quand doWake() est appelé
}
std::cout << "[Coord] fichier disponible, traitement\n";
fichier_disponible_ = false; // réinitialiser pour prochaine fois
}
};
Supprimer un agent avec doDelete()
doDelete() termine l’agent proprement : les behaviours reçoivent
leurs onEnd(), takeDown() est appelé, puis le processus se
termine.
Toujours libérer les ressources dans takeDown() avant la
suppression :
#include <gagent/messaging/AclMQ.hpp>
using namespace gagent::messaging;
class MonAgent : public Agent {
public:
void setup() override {
setAgentName("mon-agent");
addBehaviour(new MonBehaviour(this));
}
void takeDown() override {
// Libérer la queue de messagerie
acl_unlink("mon-agent");
// Désenregistrer du DF si l'agent avait annoncé des services
// DFClient df; df.deregisterAgent("mon-agent");
std::cout << "[MonAgent] ressources libérées\n";
}
};
Lire l’état courant
L’état courant est accessible via agentStatus :
void action() override {
if (this_agent->agentStatus == Agent::AGENT_ACTIVE) {
// agent actif, traitement normal
} else if (this_agent->agentStatus == Agent::AGENT_SUSPENDED) {
// ne devrait pas arriver (behaviours suspendus)
}
}
Constante |
Valeur |
|---|---|
|
Agent démarré, non encore enregistré AMS |
|
Actif et enregistré |
|
Tous behaviours en pause |
|
En attente d’un événement |
|
En cours de migration |
|
Supprimé |
Contrôle externe via agentmanager
Un agent peut aussi être suspendu/réveillé depuis la ligne de commande sans modifier son code (voir tutoriel 19 — agentmanager et agentmonitor) :
# Suspendre un agent
agentmanager suspend mon-agent
# Le réveiller
agentmanager wake mon-agent
# Le supprimer
agentmanager kill mon-agent
Résumé
Méthode |
Effet |
|---|---|
|
Pause tous les behaviours (état conservé) |
|
Pause en signalant l’attente d’un événement |
|
Reprend depuis SUSPENDED ou WAITING |
|
Arrêt propre : takeDown() puis fin du processus |
|
Réactive un agent INITED (normalement automatique) |