#include <GAgent.h>
Inheritance diagram for GCS::GAgent:


Public Member Functions | |
| GAgent () | |
| virtual | ~GAgent () |
| const GElementID & | getElementID () const |
| virtual QString | getAgentName () const |
| virtual QStringList | getAvailableActions () const |
| virtual QString | getActionDescription (const QString &action) const |
Protected Member Functions | |
| virtual void | run () |
| virtual bool | isParked () const |
Protected Attributes | |
| bool | shutdown |
Private Attributes | |
| GObject * | Object |
| QList< GAgent * > * | Agents |
Friends | |
| class | GElement |
To implement an agent this class must be inherited and all desired abstract methods have to be implemented. In particular GAgent::run() and GAgent::receiveInfluence() are of interest. If your agent supports actions that should be externally available you should also reimplement getAvailableActions() and performAction(). Additionally the virtual methods for parking and resuming execution can be used for various purposes. Especially threadStart() can be used to react to the time passed between parking the agent and resuming execution.
Implementing agents directly on top of this class is of course the most powerful way for agent implementation. But it could be a wise idea to create another agent interface layer that is for example capable of scripting and runtime code morphing. In this case you should also make sure you reimplement GAgent::getAgentName() to provide unique names for each agent.
Signals that represent data changes such as energyChanged() have to be emitted by the agent on purpose, they are not automated.
This gives greater control over message broadcasting and thus it is easier to minimize overhead when the agent makes multiple changes. But this also means more responsibility for the agent developer.
| GCS::GAgent::GAgent | ( | ) |
GAgent constructor. By default sets parent to NULL and name to
this->className()
| virtual GCS::GAgent::~GAgent | ( | ) | [inline, virtual] |
| QString GCS::GAgent::getActionDescription | ( | const QString & | action | ) | const [virtual] |
Needs to be reimplemented in a subclass.
Reimplemented in GBE::GCreatorAgent, GBE::GKolabAgent, GBE::GMoveAgent, and GBE::GRadiatingAgent.
| QString GCS::GAgent::getAgentName | ( | ) | const [virtual] |
The Agent name is used by the GWE to recognize the correct type of agent for deserialization of elements. The returned name must be unique among all existing agents. For this purpose, agent namespaces are introduced.
Agent namespaces are separated by two colons ::
Any number of hierarchy depth is allowed.
Some top level namespaces are defined and taken by the G System project.
The default behaviour is to return the class name. If, however, the agent is used as a base for various other agents (for example interpreted scripts) then this method must be reimplemented to provided the correct agent name in any case.
| QStringList GCS::GAgent::getAvailableActions | ( | ) | const [virtual] |
By default this returns an empty list. It needs to be reimplemented in a subclass.
Reimplemented in GBE::GCreatorAgent, GBE::GKolabAgent, GBE::GMoveAgent, and GBE::GRadiatingAgent.
| const GElementID & GCS::GAgent::getElementID | ( | ) | const |
This is public because it can be useful to look to which element this agent belongs
| bool GCS::GAgent::isParked | ( | ) | const [protected, virtual] |
Sleeps for the given amount of time but regularly checks whether a shutdown of the agent has been requested to speed up parking.
If a shutdown request is detected during the given sleep period the call will return with false at the next check. In this case the agent should return from run() as soon as possible.
Keep in mind that only the data stored into the GElementData is preserved in case the agent gets removed from memory and restored later. Thus all relevant data should be stored there.
For performance reasons the checkinterval should be as large as possible, but for speeding up shutdown requests it should be as small as possible. The optimum depends on the actual application.
It is recommended to use this sleep function especially for very long sleep times.
Example run method that sleeps for 50 seconds and checks every 3 seconds if a shutdown has been requested. So the longest theoretical time it takes to shutdown is 3 seconds, instead of 50:
void MyAgent::run() { while (msleepCheckShutdown( 50000, 3000)) { //do whatever you usually do within this agent } //store important stuff to GElementData } @param msecs the amount of milliseconds to sleep in total @param checkinterval the time between shutdown checks @return false when sleep is interrupted because of a shutdown requested, true if no shutdown is requested. @see run() @see shutdown @see GElementData @todo unit test - this is not yet tested */ bool msleepCheckShutdown(unsigned long msecs, unsigned long checkinterval = 5000); GObject* requestObject(); const GObject* requestObject() const; GEnergy* requestEnergy(); const GEnergy* requestEnergy() const; GForm* requestForm(); const GForm* requestForm() const; GElementData* requestElementData(); const GElementData* requestElementData() const; QList<const GAgent*> requestAgents() const; const GElementID& getConnectionID() const; protected slots: virtual void beginPark(); virtual void threadStart(double seconds_elapsed); public slots: virtual void receiveInfluence(const GCS::GElementInfluence&); virtual void performAction(const QString& action, QStringList params); virtual void reparented(const GCS::GElementID& old_parent, const GCS::GElementID& new_parent, const GCS::GMatrix44& transformation); signals: void sendInfluence(const GCS::GElementInfluence& influence, const GCS::GElementID& destination); void radiateInfluence(const GCS::GElementInfluence& influence, double radius_factor); void parentChanged(const GCS::GElementID& newParent, const GCS::GElementID& oldParent, const GCS::GMatrix44& transformation); void energyChanged(const GCS::GEnergy& changedEnergy); void formChanged(const GCS::GForm& changedForm); void elementDataChanged(const QString& xmlpath); void childElementCreated(GCS::GElement* newElement); void childElementRemoved(const GCS::GElementID& childID); public:
Normally you don't need to reimplement this but it might be possible that a subclass of GAgent uses several threads and then a simple check of the agent's main thread wouldn't be enough.
| void GCS::GAgent::run | ( | ) | [protected, virtual] |
When agents are started this code is executed as a thread. This is where the agent's functionality is defined.
Reimplemented in GBE::GEnergyFormAgent, GBE::GMoveAgent, GBE::GOrbitingAgent, GBE::GPhysicsAgent, and GBE::GRadiatingAgent.
friend class GElement [friend] |
GElement needs to set private properties and connect to protected slots.
QList<GAgent*>* GCS::GAgent::Agents [private] |
This list stores all agents that are in the same element. Since it is not clean code to change other agents directly they are accessible read only.
GObject* GCS::GAgent::Object [private] |
This is a pointer to the element's object; all changes to the element are done by accessing the object through this pointer; all requestXXXX() methods use it;
bool GCS::GAgent::shutdown [protected] |
The default implementation of beginPark() sets this value to true. It can be used inside the run() method to check if the agent should park (this is done by returning from the run method).
A standard run() method would look like this:
void CustomAgent::run() { while(!shutdown) { //do something msleep(breaktime); //take a nap (very important) } }
1.4.7