Skip to content

Commit

Permalink
Added async Ping/Pong test, and JLPCActor patch against StackOverflow…
Browse files Browse the repository at this point in the history
…Error.
  • Loading branch information
skunkiferous committed Mar 16, 2013
1 parent 7435b7f commit ded6ee1
Show file tree
Hide file tree
Showing 5 changed files with 236 additions and 5 deletions.
18 changes: 15 additions & 3 deletions src/main/java/org/agilewiki/jactor/lpc/JLPCActor.java
Expand Up @@ -242,7 +242,11 @@ final public void acceptRequest(final APCRequestSource apcRequestSource,
final RequestSource rs = (RequestSource) apcRequestSource; final RequestSource rs = (RequestSource) apcRequestSource;
final Mailbox sourceMailbox = rs.getMailbox(); final Mailbox sourceMailbox = rs.getMailbox();
if (sourceMailbox == mailbox) { if (sourceMailbox == mailbox) {
syncSend(rs, request, rp); try {
syncSend(rs, request, rp);
} catch (StackOverflowError e) {
asyncSend(rs, request, rp);
}
return; return;
} }
if (sourceMailbox == null) { if (sourceMailbox == null) {
Expand All @@ -260,15 +264,23 @@ private void acceptOtherRequest(final Mailbox sourceMailbox,
final EventQueue<List<JAMessage>> srcController = sourceMailbox final EventQueue<List<JAMessage>> srcController = sourceMailbox
.getEventQueue().getController(); .getEventQueue().getController();
if (eventQueue.getController() == srcController) { if (eventQueue.getController() == srcController) {
syncSend(rs, request, rp); try {
syncSend(rs, request, rp);
} catch (StackOverflowError e) {
asyncSend(rs, request, rp);
}
return; return;
} }
if (!eventQueue.acquireControl(srcController)) { if (!eventQueue.acquireControl(srcController)) {
asyncSend(rs, request, rp); asyncSend(rs, request, rp);
return; return;
} }
try { try {
syncSend(rs, request, rp); try {
syncSend(rs, request, rp);
} catch (StackOverflowError e) {
asyncSend(rs, request, rp);
}
} finally { } finally {
mailbox.dispatchEvents(); mailbox.dispatchEvents();
mailbox.sendPendingMessages(); mailbox.sendPendingMessages();
Expand Down
4 changes: 2 additions & 2 deletions src/test/java/org/agilewiki/jactor/pingpong/PingPongTest.java
Expand Up @@ -19,9 +19,9 @@ public void testRequestReplyCycleSpeed() throws Exception {
double duration = 0.0d; double duration = 0.0d;
for (int i = 1; i <= REPEATS; i++) { for (int i = 1; i <= REPEATS; i++) {
System.out.println("Run #" + i + "/" + REPEATS); System.out.println("Run #" + i + "/" + REPEATS);
final Pinger pinger = new Pinger(mailboxFactory.createAsyncMailbox(), final Pinger pinger = new Pinger(mailboxFactory.createMailbox(),
"Pinger"); "Pinger");
final Ponger ponger = new Ponger(mailboxFactory.createAsyncMailbox()); final Ponger ponger = new Ponger(mailboxFactory.createMailbox());
final Pinger.HammerResult result = pinger.hammer(ponger); final Pinger.HammerResult result = pinger.hammer(ponger);
count += result.pings(); count += result.pings();
duration += result.duration(); duration += result.duration();
Expand Down
35 changes: 35 additions & 0 deletions src/test/java/org/agilewiki/jactor/pingpong/PingPongTest2.java
@@ -0,0 +1,35 @@
package org.agilewiki.jactor.pingpong;

import org.agilewiki.jactor.JAMailboxFactory;
import org.agilewiki.jactor.MailboxFactory;

import junit.framework.TestCase;

/**
* Tests the number of request/reply cycles per second.
*/
public class PingPongTest2 extends TestCase {
/** How many repeats? */
private static final int REPEATS = 10;

public void testRequestReplyCycleSpeed() throws Exception {
final MailboxFactory mailboxFactory = JAMailboxFactory.newMailboxFactory(2);

int count = 0;
double duration = 0.0d;
for (int i = 1; i <= REPEATS; i++) {
System.out.println("Run #" + i + "/" + REPEATS);
final Pinger2 pinger = new Pinger2(mailboxFactory.createMailbox(),
"Pinger");
final Ponger2 ponger = new Ponger2(mailboxFactory.createMailbox());
final Pinger2.HammerResult2 result = pinger.hammer(ponger);
count += result.pings();
duration += result.duration();
System.out.println(result);
}
System.out.println("Average Request/Reply Cycles/sec = "
+ (count / duration));

mailboxFactory.close();
}
}
132 changes: 132 additions & 0 deletions src/test/java/org/agilewiki/jactor/pingpong/Pinger2.java
@@ -0,0 +1,132 @@
package org.agilewiki.jactor.pingpong;

import org.agilewiki.jactor.Actor;
import org.agilewiki.jactor.JAFuture;
import org.agilewiki.jactor.Mailbox;
import org.agilewiki.jactor.RP;
import org.agilewiki.jactor.lpc.JLPCActor;
import org.agilewiki.jactor.lpc.Request;

/**
* The Pinger's job is to hammer the Ponger with ping() request,
* to count how many can be done in one second.
*/
public class Pinger2 extends JLPCActor {
/* Hammer request result */
public static final class HammerResult2 {
/** Number of pings sent. */
private final int pings;

/** Duration. */
private final double duration;

/** Constructor */
public HammerResult2(final int _pings, final double _duration) {
pings = _pings;
duration = _duration;
}

/** toString */
@Override
public String toString() {
return "Sent " + pings + " pings in " + duration + " seconds";
}

/** Number of pings sent. */
public int pings() {
return pings;
}

/** Duration. */
public double duration() {
return duration;
}
}

/** How long to send pings? */
private static final long PING_FOR_IN_MS = 1000L;

/** The name of the pinger. */
private final String name;

/** A Hammer request, targeted at Pinger. */
private static class HammerRequest2 extends Request<HammerResult2,Pinger2> {
private static final long DELAY = PING_FOR_IN_MS * 1000000L;

/** The Ponger to hammer. */
private final Ponger2 ponger;

/** The responseProcessor from the test, to call when done. */
private RP<HammerResult2> responseProcessor;

/** Arival from hammer request. */
private long start;

/** The number of pings. */
private int count;

/** The pinger */
private Pinger2 pinger;

/** Creates a hammer request, with the targeted Ponger. */
public HammerRequest2(final Ponger2 _ponger) {
ponger = _ponger;
}

private void ping() throws Exception {
ponger.ping(pinger, new RP<String>() {
@Override
public void processResponse(String response)
throws Exception {
final long now = System.nanoTime();
count++;
if (now - start < DELAY) {
// again ...
ping();
} else {
responseProcessor.processResponse(new HammerResult2(count,
((now - start) / 1000000000.0d)));
}

}
});
}

/** Process the hammer request. */
@SuppressWarnings("unchecked")
@Override
public void processRequest(final JLPCActor targetActor,
@SuppressWarnings("rawtypes") final RP _responseProcessor)
throws Exception {
pinger = (Pinger2) targetActor;
responseProcessor = (RP<HammerResult2>) _responseProcessor;
start = System.nanoTime();
ping();
}

@Override
public boolean isTargetType(Actor targetActor) {
return Pinger2.class.isInstance(targetActor);
}
}

/** Creates a Pinger, with it's own mailbox and name.
* @throws Exception */
public Pinger2(final Mailbox mbox, final String _name) throws Exception {
initialize(mbox);
name = _name;
}

/** Tells the pinger to hammer the Ponger. Describes the speed in the result. */
public HammerResult2 hammer(final Ponger2 ponger) throws Exception {
final JAFuture future = new JAFuture();
return new HammerRequest2(ponger).send(future, this);
}

/**
* @return the name
*/
public String getName() {
return name;
}
}
52 changes: 52 additions & 0 deletions src/test/java/org/agilewiki/jactor/pingpong/Ponger2.java
@@ -0,0 +1,52 @@
package org.agilewiki.jactor.pingpong;

import org.agilewiki.jactor.Actor;
import org.agilewiki.jactor.JAFuture;
import org.agilewiki.jactor.Mailbox;
import org.agilewiki.jactor.RP;
import org.agilewiki.jactor.lpc.JLPCActor;
import org.agilewiki.jactor.lpc.Request;

/**
* Receives Pings, and send Pongs back.
*/
public class Ponger2 extends JLPCActor {
/** Some mutable data of Ponger, which must be access in a thread-safe way. */
private int pings;

/** A Ping request, targeted at Ponger. */
private static class PingRequest2 extends Request<String,Ponger2> {
private final String from;

public PingRequest2(final String _from) {
from = _from;
}

/** Processes the ping(String) request, from within the Thread of the Ponger. */
@SuppressWarnings("unchecked")
@Override
public void processRequest(final JLPCActor targetActor,
@SuppressWarnings("rawtypes") final RP responseProcessor)
throws Exception {
final Ponger2 ponger = (Ponger2) targetActor;
responseProcessor.processResponse("Pong " + (ponger.pings++) + " to "
+ from + "!");
}

@Override
public boolean isTargetType(Actor targetActor) {
return Ponger2.class.isInstance(targetActor);
}
}

/** Creates a Ponger, with it's own mailbox.
* @throws Exception */
public Ponger2(final Mailbox mbox) throws Exception {
initialize(mbox);
}

/** Sends a ping(String) request to the Ponger. Blocks and returns response. */
public void ping(final Pinger2 pinger, final RP<String> rp) throws Exception {
new PingRequest2(pinger.getName()).send(pinger, this, rp);
}
}

0 comments on commit ded6ee1

Please sign in to comment.