From: <jom...@us...> - 2009-02-19 16:00:22
|
Revision: 1451 http://jason.svn.sourceforge.net/jason/?rev=1451&view=rev Author: jomifred Date: 2009-02-19 16:00:17 +0000 (Thu, 19 Feb 2009) Log Message: ----------- another solution for the problem fixed in previous commit: changes in C are postponed to the begin of next reasoning cycle, so that only the TS thread changes C Modified Paths: -------------- trunk/src/jason/asSemantics/ConcurrentInternalAction.java trunk/src/jason/asSemantics/TransitionSystem.java trunk/src/jason/stdlib/drop_all_intentions.java trunk/src/jason/stdlib/drop_intention.java trunk/src/jason/stdlib/intend.java trunk/src/jason/stdlib/wait.java Modified: trunk/src/jason/asSemantics/ConcurrentInternalAction.java =================================================================== --- trunk/src/jason/asSemantics/ConcurrentInternalAction.java 2009-02-19 10:50:55 UTC (rev 1450) +++ trunk/src/jason/asSemantics/ConcurrentInternalAction.java 2009-02-19 16:00:17 UTC (rev 1451) @@ -113,24 +113,29 @@ resume(ts, intentionKey, true); } - synchronized private void resume(TransitionSystem ts, String intentionKey, boolean abort) { - Circumstance C = ts.getC(); - Intention pi = C.getPendingIntentions().remove(intentionKey); - if (pi != null) { - pi.setSuspended(false); - try { - if (abort) { - // fail the IA - ts.generateGoalDeletion(pi, null); - } else { - pi.peek().removeCurrentStep(); // remove the internal action that put the intention in suspend - ts.applyClrInt(pi); - C.addIntention(pi); // add it back in I + synchronized private void resume(final TransitionSystem ts, final String intentionKey, final boolean abort) { + // invoke changes in C latter, so to avoid concurrent changes in C + ts.runAtBeginOfNextCycle(new Runnable() { + public void run() { + Circumstance C = ts.getC(); + Intention pi = C.getPendingIntentions().remove(intentionKey); + if (pi != null) { + pi.setSuspended(false); + try { + if (abort) { + // fail the IA + ts.generateGoalDeletion(pi, null); + } else { + pi.peek().removeCurrentStep(); // remove the internal action that put the intention in suspend + ts.applyClrInt(pi); + C.addIntention(pi); // add it back in I + } + } catch (JasonException e) { + ts.getLogger().log(Level.SEVERE, "Error resuming intention", e); + } } - } catch (JasonException e) { - ts.getLogger().log(Level.SEVERE, "Error resuming intention", e); } - ts.getUserAgArch().getArchInfraTier().wake(); - } + }); + ts.getUserAgArch().getArchInfraTier().wake(); } } Modified: trunk/src/jason/asSemantics/TransitionSystem.java =================================================================== --- trunk/src/jason/asSemantics/TransitionSystem.java 2009-02-19 10:50:55 UTC (rev 1450) +++ trunk/src/jason/asSemantics/TransitionSystem.java 2009-02-19 16:00:17 UTC (rev 1451) @@ -52,6 +52,8 @@ import java.util.LinkedList; import java.util.List; import java.util.ListIterator; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.logging.Level; import java.util.logging.Logger; @@ -80,6 +82,8 @@ // object, this is just to make it look more like the SOS private TransitionSystem conf; + private Queue<Runnable> taskForBeginOfCycle = new ConcurrentLinkedQueue<Runnable>(); + public TransitionSystem(Agent a, Circumstance c, Settings s, AgArch ar) { ag = a; C = c; @@ -912,6 +916,14 @@ agArch.canSleep(); } + /** + * Schedule a task to be executed in the begin of the next reasoning cycle. + * It is used mostly to change the C only by the TS thread (e.g. by .wait) + */ + public void runAtBeginOfNextCycle(Runnable r) { + taskForBeginOfCycle.offer(r); + } + /**********************************************************************/ /* MAIN LOOP */ /**********************************************************************/ @@ -923,6 +935,13 @@ try { C.reset(); + // run tasks allocated to be performed in the begin of the cycle + Runnable r = taskForBeginOfCycle.poll(); + while (r != null) { + r.run(); + r = taskForBeginOfCycle.poll(); + } + if (nrcslbr >= setts.nrcbp()) { nrcslbr = 0; ag.buf(agArch.perceive()); Modified: trunk/src/jason/stdlib/drop_all_intentions.java =================================================================== --- trunk/src/jason/stdlib/drop_all_intentions.java 2009-02-19 10:50:55 UTC (rev 1450) +++ trunk/src/jason/stdlib/drop_all_intentions.java 2009-02-19 16:00:17 UTC (rev 1451) @@ -74,10 +74,8 @@ checkArguments(args); Circumstance C = ts.getC(); - synchronized (C) { // do not allow other threads (.wait) to change C meanwhile - C.clearIntentions(); - C.clearPendingIntentions(); - } + C.clearIntentions(); + C.clearPendingIntentions(); C.clearPendingActions(); // drop intentions in E Modified: trunk/src/jason/stdlib/drop_intention.java =================================================================== --- trunk/src/jason/stdlib/drop_intention.java 2009-02-19 10:50:55 UTC (rev 1450) +++ trunk/src/jason/stdlib/drop_intention.java 2009-02-19 16:00:17 UTC (rev 1451) @@ -107,20 +107,18 @@ } } - synchronized (C) { // do not allow other threads (.wait) to change the C meanwhile - for (Intention i: C.getIntentions()) { - if (i.hasTrigger(g, un)) { - C.removeIntention(i); - un = bak.clone(); - } + for (Intention i: C.getIntentions()) { + if (i.hasTrigger(g, un)) { + C.removeIntention(i); + un = bak.clone(); } - - // intention may be suspended in PI! (in the new semantics) - for (Intention i: C.getPendingIntentions().values()) { - if (i.hasTrigger(g, un)) { - C.dropPendingIntention(i); - un = bak.clone(); - } + } + + // intention may be suspended in PI! (in the new semantics) + for (Intention i: C.getPendingIntentions().values()) { + if (i.hasTrigger(g, un)) { + C.dropPendingIntention(i); + un = bak.clone(); } } } Modified: trunk/src/jason/stdlib/intend.java =================================================================== --- trunk/src/jason/stdlib/intend.java 2009-02-19 10:50:55 UTC (rev 1450) +++ trunk/src/jason/stdlib/intend.java 2009-02-19 16:00:17 UTC (rev 1451) @@ -117,21 +117,19 @@ } } - synchronized (C) { // do not allow other threads (.wait) to change C meanwhile - // intention may be suspended in PI! (in the new semantics) - if (C.hasPendingIntention()) { - for (Intention intention: C.getPendingIntentions().values()) { - if (intention.hasTrigger(g, un)) - return true; - } - } - - for (Intention i : C.getIntentions()) { - if (i.hasTrigger(g, un)) + // intention may be suspended in PI! (in the new semantics) + if (C.hasPendingIntention()) { + for (Intention intention: C.getPendingIntentions().values()) { + if (intention.hasTrigger(g, un)) return true; } } + for (Intention i : C.getIntentions()) { + if (i.hasTrigger(g, un)) + return true; + } + return false; } Modified: trunk/src/jason/stdlib/wait.java =================================================================== --- trunk/src/jason/stdlib/wait.java 2009-02-19 10:50:55 UTC (rev 1450) +++ trunk/src/jason/stdlib/wait.java 2009-02-19 16:00:17 UTC (rev 1451) @@ -162,44 +162,45 @@ } } - void resume(boolean stopByTimeout) { - try { - // unregister (for not to receive intentionAdded again) - c.removeEventListener(this); + void resume(final boolean stopByTimeout) { + // unregister (for not to receive intentionAdded again) + c.removeEventListener(this); - synchronized (c) { // block access to C, so that .drop_desire, for instance, will wait this operation to finish; - // otherwise the intention disappears between 'remove from PI' and 'add back to I' - - // add SI again in C.I if it was not removed and this wait was not dropped - if (c.getPendingIntentions().remove(sTE) == si && !c.getIntentions().contains(si) && !dropped) { - if (stopByTimeout && te != null && elapsedTimeTerm == null) { - // fail the .wait by timeout - if (si.isSuspended()) { // if the intention was suspended by .suspend - PlanBody body = si.peek().getPlan().getBody(); - body.add(1, new PlanBodyImpl(BodyType.internalAction, new InternalActionLiteral(".fail"))); - c.getPendingIntentions().put(suspend.SUSPENDED_INT+si.getId(), si); + // invoke changes in C latter, so to avoid concurrent changes in C + ts.runAtBeginOfNextCycle(new Runnable() { + public void run() { + try { + // add SI again in C.I if it was not removed and this wait was not dropped + if (c.getPendingIntentions().remove(sTE) == si && !c.getIntentions().contains(si) && !dropped) { + if (stopByTimeout && te != null && elapsedTimeTerm == null) { + // fail the .wait by timeout + if (si.isSuspended()) { // if the intention was suspended by .suspend + PlanBody body = si.peek().getPlan().getBody(); + body.add(1, new PlanBodyImpl(BodyType.internalAction, new InternalActionLiteral(".fail"))); + c.getPendingIntentions().put(suspend.SUSPENDED_INT+si.getId(), si); + } else { + ts.generateGoalDeletion(si, JasonException.createBasicErrorAnnots("wait_timeout", "timeout in .wait")); + } } else { - ts.generateGoalDeletion(si, JasonException.createBasicErrorAnnots("wait_timeout", "timeout in .wait")); + si.peek().removeCurrentStep(); + + if (elapsedTimeTerm != null) { + long elapsedTime = System.currentTimeMillis() - startTime; + un.unifies(elapsedTimeTerm, new NumberTermImpl(elapsedTime)); + } + if (si.isSuspended()) { // if the intention was suspended by .suspend + c.getPendingIntentions().put(suspend.SUSPENDED_INT+si.getId(), si); + } else { + c.addIntention(si); + } } - } else { - si.peek().removeCurrentStep(); - - if (elapsedTimeTerm != null) { - long elapsedTime = System.currentTimeMillis() - startTime; - un.unifies(elapsedTimeTerm, new NumberTermImpl(elapsedTime)); - } - if (si.isSuspended()) { // if the intention was suspended by .suspend - c.getPendingIntentions().put(suspend.SUSPENDED_INT+si.getId(), si); - } else { - c.addIntention(si); - } - } - ts.getUserAgArch().getArchInfraTier().wake(); + } + } catch (Exception e) { + ts.getLogger().log(Level.SEVERE, "Error at .wait thread", e); } } - } catch (Exception e) { - ts.getLogger().log(Level.SEVERE, "Error at .wait thread", e); - } + }); + ts.getUserAgArch().getArchInfraTier().wake(); } public void eventAdded(Event e) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |