GCS::GAgent Class Reference

Defines the behaviour of an element. More...

#include <GAgent.h>

Inheritance diagram for GCS::GAgent:

Inheritance graph
[legend]
Collaboration diagram for GCS::GAgent:

Collaboration graph
[legend]
List of all members.

Public Member Functions

 GAgent ()
virtual ~GAgent ()
const GElementIDgetElementID () 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

GObjectObject
QList< GAgent * > * Agents

Friends

class GElement

Detailed Description

Defines the behaviour of an element.

Author:
Raphael Langerhorst
Agents are used to give the element functionality or life. All behaviour of the element come from its agents, even all laws (gravity, ...) that the element adhers to are implemented by agents;

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.

Todo:
Changed signals such as energyChanged() should also be received by the agent since other agents could emit these and it should be possible to react to these events.


Constructor & Destructor Documentation

GCS::GAgent::GAgent (  ) 

GAgent constructor. By default sets parent to NULL and name to

 this->className() 
.

virtual GCS::GAgent::~GAgent (  )  [inline, virtual]

The virtual destructor makes sure that inherited classes are cleanly destroyed when only a pointer to GAgent is used for freeing memory. Please make sure that all subclasses of GAgent have a virtual destructor.


Member Function Documentation

QString GCS::GAgent::getActionDescription ( const QString &  action  )  const [virtual]

Needs to be reimplemented in a subclass.

Returns:
Informal description of given action and its parameters.
See also:
getAvailableActions, performAction

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.

Returns:
unique agent name used for identification of agent type. QObject::className() by default

QStringList GCS::GAgent::getAvailableActions (  )  const [virtual]

By default this returns an empty list. It needs to be reimplemented in a subclass.

Note:
Please keep in sync with performAction.
Returns:
list of available actions for this agent
See also:
performAction, getActionDescription

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

Returns:
the element's ID (const reference)

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.

See also:
GAgent::receiveInfluence

GAgent::shutdown

Reimplemented in GBE::GEnergyFormAgent, GBE::GMoveAgent, GBE::GOrbitingAgent, GBE::GPhysicsAgent, and GBE::GRadiatingAgent.


Friends And Related Function Documentation

friend class GElement [friend]

GElement needs to set private properties and connect to protected slots.


Member Data Documentation

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.

Note:
When an agent was never added to an element this pointer is NULL!! Such agents should never be executed on their own.
See also:
GElement::addAgent()

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;

Note:
When an agent was never added to an element this pointer is NULL!! Such agents should never be executed on their own.
See also:
GElement::addAgent()

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)
   }
 }


The documentation for this class was generated from the following files:
Generated on Thu Nov 16 07:49:32 2006 for G System by  doxygen 1.4.7