2009-06-05 22:08:53 +02:00
|
|
|
package se.scalablesolutions.akka.kernel.reactor
|
|
|
|
|
|
|
|
|
|
import java.util.concurrent.CountDownLatch
|
|
|
|
|
import java.util.concurrent.CyclicBarrier
|
|
|
|
|
import java.util.concurrent.TimeUnit
|
|
|
|
|
import java.util.concurrent.atomic.AtomicBoolean
|
|
|
|
|
import java.util.concurrent.locks.Lock
|
|
|
|
|
import java.util.concurrent.locks.ReentrantLock
|
|
|
|
|
import org.junit.Before
|
|
|
|
|
import org.junit.Test
|
|
|
|
|
import org.junit.Assert._
|
|
|
|
|
|
|
|
|
|
class ThreadBasedDispatcherTest {
|
|
|
|
|
private var threadingIssueDetected: AtomicBoolean = null
|
|
|
|
|
|
|
|
|
|
@Before
|
|
|
|
|
def setUp = {
|
|
|
|
|
threadingIssueDetected = new AtomicBoolean(false)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
def testMessagesDispatchedToTheSameHandlerAreExecutedSequentially = {
|
|
|
|
|
internalTestMessagesDispatchedToTheSameHandlerAreExecutedSequentially
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
def testMessagesDispatchedToDifferentHandlersAreExecutedConcurrently = {
|
|
|
|
|
internalTestMessagesDispatchedToDifferentHandlersAreExecutedConcurrently
|
|
|
|
|
}
|
|
|
|
|
|
2009-06-25 13:07:58 +02:00
|
|
|
@Test
|
2009-06-05 22:08:53 +02:00
|
|
|
def testMessagesDispatchedToHandlersAreExecutedInFIFOOrder = {
|
|
|
|
|
internalTestMessagesDispatchedToHandlersAreExecutedInFIFOOrder
|
|
|
|
|
}
|
|
|
|
|
|
2009-06-25 13:07:58 +02:00
|
|
|
class TestMessageHandle(handleLatch: CountDownLatch) extends MessageHandler {
|
|
|
|
|
val guardLock: Lock = new ReentrantLock
|
|
|
|
|
|
|
|
|
|
def handle(message: MessageHandle) {
|
|
|
|
|
try {
|
|
|
|
|
if (threadingIssueDetected.get) return
|
|
|
|
|
if (guardLock.tryLock) {
|
|
|
|
|
handleLatch.countDown
|
|
|
|
|
} else {
|
|
|
|
|
threadingIssueDetected.set(true)
|
|
|
|
|
}
|
|
|
|
|
} catch {
|
|
|
|
|
case e: Exception => threadingIssueDetected.set(true)
|
|
|
|
|
} finally {
|
|
|
|
|
guardLock.unlock
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-06-05 22:08:53 +02:00
|
|
|
private def internalTestMessagesDispatchedToTheSameHandlerAreExecutedSequentially: Unit = {
|
|
|
|
|
val guardLock = new ReentrantLock
|
2009-06-10 20:04:33 +02:00
|
|
|
val handleLatch = new CountDownLatch(100)
|
2009-06-05 22:08:53 +02:00
|
|
|
val key = "key"
|
2009-06-25 13:07:58 +02:00
|
|
|
val dispatcher = new EventBasedSingleThreadDispatcher
|
|
|
|
|
dispatcher.registerHandler(key, new TestMessageHandle(handleLatch))
|
2009-06-10 20:04:33 +02:00
|
|
|
dispatcher.start
|
2009-06-05 22:08:53 +02:00
|
|
|
for (i <- 0 until 100) {
|
2009-06-30 16:01:50 +02:00
|
|
|
dispatcher.messageQueue.append(new MessageHandle(key, new Object, None, None))
|
2009-06-05 22:08:53 +02:00
|
|
|
}
|
2009-06-25 13:07:58 +02:00
|
|
|
assertTrue(handleLatch.await(5, TimeUnit.SECONDS))
|
2009-06-05 22:08:53 +02:00
|
|
|
assertFalse(threadingIssueDetected.get)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private def internalTestMessagesDispatchedToDifferentHandlersAreExecutedConcurrently: Unit = {
|
|
|
|
|
val handlersBarrier = new CyclicBarrier(3)
|
|
|
|
|
val key1 = "key1"
|
|
|
|
|
val key2 = "key2"
|
2009-06-11 13:52:22 +02:00
|
|
|
val dispatcher = new EventBasedThreadPoolDispatcher
|
2009-06-10 20:04:33 +02:00
|
|
|
dispatcher.registerHandler(key1, new MessageHandler {
|
2009-06-05 22:08:53 +02:00
|
|
|
def handle(message: MessageHandle) = synchronized {
|
|
|
|
|
try {handlersBarrier.await(1, TimeUnit.SECONDS)}
|
|
|
|
|
catch {case e: Exception => threadingIssueDetected.set(true)}
|
|
|
|
|
}
|
|
|
|
|
})
|
2009-06-10 20:04:33 +02:00
|
|
|
dispatcher.registerHandler(key2, new MessageHandler {
|
2009-06-05 22:08:53 +02:00
|
|
|
def handle(message: MessageHandle) = synchronized {
|
|
|
|
|
try {handlersBarrier.await(1, TimeUnit.SECONDS)}
|
|
|
|
|
catch {case e: Exception => threadingIssueDetected.set(true)}
|
|
|
|
|
}
|
|
|
|
|
})
|
2009-06-10 20:04:33 +02:00
|
|
|
dispatcher.start
|
2009-06-30 16:01:50 +02:00
|
|
|
dispatcher.messageQueue.append(new MessageHandle(key1, "Sending Message 1", None, None))
|
|
|
|
|
dispatcher.messageQueue.append(new MessageHandle(key2, "Sending Message 2", None, None))
|
2009-06-10 20:04:33 +02:00
|
|
|
handlersBarrier.await(5, TimeUnit.SECONDS)
|
2009-06-05 22:08:53 +02:00
|
|
|
assertFalse(threadingIssueDetected.get)
|
2009-06-10 20:04:33 +02:00
|
|
|
//dispatcher.shutdown
|
2009-06-05 22:08:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private def internalTestMessagesDispatchedToHandlersAreExecutedInFIFOOrder: Unit = {
|
|
|
|
|
val handleLatch = new CountDownLatch(200)
|
|
|
|
|
val key1 = "key1"
|
|
|
|
|
val key2 = "key2"
|
2009-06-25 13:07:58 +02:00
|
|
|
val dispatcher = new EventBasedSingleThreadDispatcher
|
2009-06-10 20:04:33 +02:00
|
|
|
dispatcher.registerHandler(key1, new MessageHandler {
|
2009-06-05 22:08:53 +02:00
|
|
|
var currentValue = -1;
|
|
|
|
|
def handle(message: MessageHandle) {
|
|
|
|
|
if (threadingIssueDetected.get) return
|
|
|
|
|
val messageValue = message.message.asInstanceOf[Int]
|
|
|
|
|
if (messageValue.intValue == currentValue + 1) {
|
|
|
|
|
currentValue = messageValue.intValue
|
|
|
|
|
handleLatch.countDown
|
|
|
|
|
} else threadingIssueDetected.set(true)
|
|
|
|
|
}
|
|
|
|
|
})
|
2009-06-10 20:04:33 +02:00
|
|
|
dispatcher.registerHandler(key2, new MessageHandler {
|
2009-06-05 22:08:53 +02:00
|
|
|
var currentValue = -1;
|
|
|
|
|
def handle(message: MessageHandle) {
|
|
|
|
|
if (threadingIssueDetected.get) return
|
|
|
|
|
val messageValue = message.message.asInstanceOf[Int]
|
|
|
|
|
if (messageValue.intValue == currentValue + 1) {
|
2009-06-25 13:07:58 +02:00
|
|
|
currentValue = messageValue.intValue
|
2009-06-05 22:08:53 +02:00
|
|
|
handleLatch.countDown
|
|
|
|
|
} else threadingIssueDetected.set(true)
|
|
|
|
|
}
|
|
|
|
|
})
|
2009-06-10 20:04:33 +02:00
|
|
|
dispatcher.start
|
2009-06-05 22:08:53 +02:00
|
|
|
for (i <- 0 until 100) {
|
2009-06-30 16:01:50 +02:00
|
|
|
dispatcher.messageQueue.append(new MessageHandle(key1, new Integer(i), None, None))
|
|
|
|
|
dispatcher.messageQueue.append(new MessageHandle(key2, new Integer(i), None, None))
|
2009-06-05 22:08:53 +02:00
|
|
|
}
|
2009-06-25 13:07:58 +02:00
|
|
|
assertTrue(handleLatch.await(5, TimeUnit.SECONDS))
|
2009-06-05 22:08:53 +02:00
|
|
|
assertFalse(threadingIssueDetected.get)
|
2009-06-10 20:04:33 +02:00
|
|
|
dispatcher.shutdown
|
2009-06-05 22:08:53 +02:00
|
|
|
}
|
|
|
|
|
}
|