?? agent.java
字號(hào):
@see jade.core.Agent#setEnabledO2ACommunication(boolean enabled, int queueSize)
*/
public Object getO2AObject() {
// Return 'null' if object-to-agent communication is disabled
if(o2aQueue == null)
return null;
CondVar cond = null;
Object result = null;
synchronized (o2aQueue) {
if(o2aQueue.isEmpty())
return null;
// Retrieve the first object from the object-to-agent
// communication queue
result = o2aQueue.remove(0);
// If some thread issued a blocking putO2AObject() call with this
// object, wake it up. cond.set is synchronized on CondVar object
cond = (CondVar)o2aLocks.remove(result);
}
if(cond != null) {
cond.set();
}
return result;
}
/**
This method declares this agent attitude towards object-to-agent
communication, that is, whether the agent accepts to communicate
with other non-JADE components living within the same JVM.
<br>
<b>NOT available in MIDP</b>
<br>
@param enabled Tells whether Java objects inserted with
<code>putO2AObject()</code> will be accepted.
@param queueSize If the object-to-agent communication is enabled,
this parameter specifiies the maximum number of Java objects that
will be queued. If the passed value is 0, no maximum limit is set
up for the queue.
@see jade.wrapper.Agent#putO2AObject(Object o, boolean blocking)
@see jade.core.Agent#getO2AObject()
*/
public void setEnabledO2ACommunication(boolean enabled, int queueSize) {
if(enabled) {
if(o2aQueue == null)
o2aQueue = new ArrayList(queueSize);
// Ignore a negative value
if(queueSize >= 0)
o2aQueueSize = queueSize;
}
else {
// Wake up all threads blocked in putO2AObject() calls
Iterator it = o2aLocks.values().iterator();
while(it.hasNext()) {
CondVar cv = (CondVar)it.next();
if (cv != null) cv.set();
}
o2aQueue = null;
}
}
//#MIDP_EXCLUDE_END
//#APIDOC_EXCLUDE_BEGIN
/**
This method is the main body of every agent. It
provides startup and cleanup hooks for application
programmers to put their specific code into.
@see jade.core.Agent#setup()
@see jade.core.Agent#takeDown()
*/
public final void run() {
try {
myLifeCycle.init();
while (myLifeCycle.alive()) {
try {
myLifeCycle.execute();
// Let other agents go on
Thread.yield();
}
catch (JADESecurityException jse) {
// FIXME: maybe we should send a message to the agent
System.out.println("JADESecurityException: "+jse.getMessage());
}
catch (InterruptedException ie) {
// Change LC state request from the outside. Just do nothing
// and let the new LC state do its job
}
catch (InterruptedIOException ie) {
// Change LC state request from the outside. Just do nothing
// and let the new LC state do its job
}
catch (Interrupted i) {
// Change LC state request from the outside. Just do nothing
// and let the new LC state do its job
}
}
}
catch(Throwable t) {
System.err.println("*** Uncaught Exception for agent " + myName + " ***");
t.printStackTrace();
}
terminating = true;
myLifeCycle.end();
}
//#APIDOC_EXCLUDE_END
/**
Inner class ActiveLifeCycle
*/
private class ActiveLifeCycle extends LifeCycle {
private static final long serialVersionUID = 11111;
private ActiveLifeCycle() {
super(AP_INITIATED);
}
public void setState(int s) {
myState = s;
}
public void init() {
setActiveState(AP_ACTIVE);
//#MIDP_EXCLUDE_BEGIN
notifyStarted();
//#MIDP_EXCLUDE_END
setup();
restarting = false;
}
public void execute() throws JADESecurityException, InterruptedException, InterruptedIOException {
// Select the next behaviour to execute
Behaviour currentBehaviour = myScheduler.schedule();
// Remember how many messages arrived
int oldMsgCounter = messageCounter;
// Just do it!
currentBehaviour.actionWrapper();
// If the current Behaviour has blocked and more messages arrived
// in the meanwhile, restart the behaviour to give it another chance
if((oldMsgCounter != messageCounter) && (!currentBehaviour.isRunnable())) {
currentBehaviour.restart();
}
// When it is needed no more, delete it from the behaviours queue
if(currentBehaviour.done()) {
currentBehaviour.onEnd();
myScheduler.remove(currentBehaviour);
currentBehaviour = null;
}
else {
synchronized(myScheduler) {
// Need synchronized block (Crais Sayers, HP): What if
// 1) it checks to see if its runnable, sees its not,
// so it begins to enter the body of the if clause
// 2) meanwhile, in another thread, a message arrives, so
// the behaviour is restarted and moved to the ready list.
// 3) now back in the first thread, the agent executes the
// body of the if clause and, by calling block(), moves
// the behaviour back to the blocked list.
if(!currentBehaviour.isRunnable()) {
// Remove blocked behaviour from ready behaviours queue
// and put it in blocked behaviours queue
myScheduler.block(currentBehaviour);
currentBehaviour = null;
}
}
}
}
public void end() {
clean(false);
}
public boolean transitionTo(LifeCycle to) {
// We can go to whatever state unless we are terminating
if (!terminating) {
// The agent is going to leave this state. When
// the agent will enter this state again it must be
// in AP_ACTIVE
myState = AP_ACTIVE;
return true;
}
else {
return false;
}
}
public void transitionFrom(LifeCycle from) {
activateAllBehaviours();
}
public boolean isMessageAware() {
return true;
}
} // END of inner class ActiveLifeCycle
/**
Inner class DeletedLifeCycle
*/
private class DeletedLifeCycle extends LifeCycle {
private static final long serialVersionUID = 11112;
private DeletedLifeCycle() {
super(AP_DELETED);
}
public void end() {
clean(true);
}
public boolean alive() {
return false;
}
} // END of inner class DeletedLifeCycle
//#MIDP_EXCLUDE_BEGIN
/**
Inner class SuspendedLifeCycle
*/
private class SuspendedLifeCycle extends LifeCycle {
private static final long serialVersionUID = 11113;
private SuspendedLifeCycle() {
super(AP_SUSPENDED);
}
public void execute() throws JADESecurityException, InterruptedException, InterruptedIOException {
waitUntilActivate();
}
public void end() {
clean(false);
}
public boolean transitionTo(LifeCycle to) {
// We can only die or resume
return (to.getState() == AP_ACTIVE || to.getState() == AP_DELETED);
}
} // END of inner class SuspendedLifeCycle
//#MIDP_EXCLUDE_END
//#APIDOC_EXCLUDE_BEGIN
public void clean(boolean ok) {
if (!ok) {
System.out.println("ERROR: Agent " + myName + " died without being properly terminated !!!");
System.out.println("State was " + myLifeCycle.getState());
}
//#MIDP_EXCLUDE_BEGIN
// Reset the interrupted state of the Agent Thread
Thread.interrupted();
//#MIDP_EXCLUDE_END
myBufferedLifeCycle = myLifeCycle;
myLifeCycle = myActiveLifeCycle;
takeDown();
pendingTimers.clear();
myToolkit.handleEnd(myAID);
myLifeCycle = myBufferedLifeCycle;
}
//#APIDOC_EXCLUDE_END
/**
This protected method is an empty placeholder for application
specific startup code. Agent developers can override it to
provide necessary behaviour. When this method is called the agent
has been already registered with the Agent Platform <b>AMS</b>
and is able to send and receive messages. However, the agent
execution model is still sequential and no behaviour scheduling
is active yet.
This method can be used for ordinary startup tasks such as
<b>DF</b> registration, but is essential to add at least a
<code>Behaviour</code> object to the agent, in order for it to be
able to do anything.
@see jade.core.Agent#addBehaviour(Behaviour b)
@see jade.core.behaviours.Behaviour
*/
protected void setup() {}
/**
This protected method is an empty placeholder for application
specific cleanup code. Agent developers can override it to
provide necessary behaviour. When this method is called the agent
has not deregistered itself with the Agent Platform <b>AMS</b>
and is still able to exchange messages with other
agents. However, no behaviour scheduling is active anymore and
the Agent Platform Life Cycle state is already set to
<em>deleted</em>.
This method can be used for ordinary cleanup tasks such as
<b>DF</b> deregistration, but explicit removal of all agent
behaviours is not needed.
*/
protected void takeDown() {}
//#MIDP_EXCLUDE_BEGIN
/**
* This empty placeholder shall be overridden by user defined agents
* to execute some actions before the original agent instance on the
* source container is stopped (e.g. releasing local resources such
* as a GUI).<br>
* <b>IMPORTANT:</b> At this point, it is ensured that the move process
* is successful and that a moved agent instance has been created on the
* destination container
* Therefore setting the value of a class field in this method will have
* no impact on the moved agent instance. Such parameters must indeed be
* set <b>before</b> the <code>doMove()</code> method is called.
<br>
<b>NOT available in MIDP</b>
<br>
*/
protected void beforeMove() {}
/**
Actions to perform after moving. This empty placeholder method can be
overridden by user defined agents to execute some actions just after
arriving to the destination agent container for a migration.
<br>
<b>NOT available in MIDP</b>
<br>
*/
protected void afterMove() {}
/**
* This empty placeholder method shall be overridden by user defined agents
* to execute some actions before copying an agent to another agent container.
* <br>
* <b>NOT available in MIDP</b>
* <br>
* @see beforeMove()
* @see afterClone()
*/
protected void beforeClone() {}
/**
Actions to perform after cloning. This empty placeholder method can be
overridden by user defined agents to execute some actions just after
creating an agent copy to the destination agent container.
<br>
<b>NOT available in MIDP</b>
<br>
*/
protected void afterClone() {}
//#MIDP_EXCLUDE_END
// This method is used by the Agent Container to fire up a new agent for the first time
// Mutual exclusion with itself and Agent.addPlatformAddress()
synchronized void powerUp(AID id, Thread t) {
if (myThread == null) {
// Set this agent's name and address and start its embedded thread
myName = id.getLocalName();
myHap = id.getHap();
myAID = id;
myToolkit.setPlatformAddresses(myAID);
myThread = t;
myThread.start();
}
}
//#J2ME_EXCLUDE_BEGIN
// Return agent thread
// Package scooped as it is called by JadeMisc add-on for container monitor purpose
Thread getThread() {
return myThread;
}
//#J2ME_EXCLUDE_END
//#MIDP_EXCLUDE_BEGIN
private void writeObject(ObjectOutputStream out) throws IOException {
// Updates the queue maximum size field, before serialising
msgQueueMaxSize = msgQueue.getMaxSize();
out.defaultWriteObject();
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
// Restore transient fields (apart from myThread, which will be set when the agent will be powered up)
msgQueue = new MessageQueue(msgQueueMaxSize);
stateLock = new Object();
suspendLock = new Object();
pendingTimers = new AssociationTB();
theDispatcher = TimerDispatcher.getTimerDispatcher();
// restore O2AQueue
if (o2aQueueSize > 0)
o2aQueue = new ArrayList(o2aQueueSize);
o2aLocks = new HashMap();
myToolkit = DummyToolkit.instance();
//#PJAVA_EXCLUDE_BEGIN
//For persistence service
persistentPendingTimers = new java.util.HashSet();
//#PJAVA_EXCLUDE_END
}
//#MIDP_EXCLUDE_END
/**
This method is executed when blockingReceive() is called
from a separate Thread.
It does not affect the agent state.
*/
private void waitUntilWake(long millis) {
synchronized(msgQueue) {
try {
// Blocks on msgQueue monitor for a while
waitOn(msgQueue, millis);
}
catch (InterruptedException ie) {
throw new Interrupted();
}
}
}
//#MIDP_EXCLUDE_BEGIN
private void waitUntilActivate() throws InterruptedException {
synchronized(suspendLock) {
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -