// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
package jodd.cache;
import org.junit.Test;
import java.util.ConcurrentModificationException;
import java.util.concurrent.Semaphore;
import static org.junit.Assert.*;
public class ConcurrencyTest {
/**
* http://code.google.com/p/jodd/issues/detail?id=4
*/
@Test
public void testPutGetAndPrune() throws InterruptedException {
LFUCache<String, String> lfuCache = new LFUCache<>(2, 0);
lfuCache.put("1", "value");
assertFalse(lfuCache.isFull());
lfuCache.put("2", "value");
assertTrue(lfuCache.isFull());
lfuCache.get("2");
lfuCache.get("2");
assertEquals(2, lfuCache.size());
Semaphore semaphore = new Semaphore(2);
Thread1 t1 = new Thread1(semaphore, lfuCache);
Thread2 t2 = new Thread2(semaphore, lfuCache);
t1.start();
t2.start();
semaphore.acquire();
if (t1.exception != null) {
t1.exception.printStackTrace();
}
assertNull(t1.exception);
if (t2.exception != null) {
t2.exception.printStackTrace();
}
assertNull(t2.exception);
}
public static class Thread1 extends SemaphoreThread {
public Thread1(Semaphore semaphore, Cache<String, String> cache) {
super(semaphore, cache);
}
@Override
public void work() {
long l = 100000;
while (l-- > 0) {
cache.put("3", "new value");
}
}
}
public static class Thread2 extends SemaphoreThread {
public Thread2(Semaphore semaphore, Cache<String, String> cache) {
super(semaphore, cache);
}
@Override
public void work() {
long l = 100000;
while (l-- > 0) {
cache.put("1", "back");
cache.get("1");
cache.put("2", "back");
}
}
}
public abstract static class SemaphoreThread extends Thread {
final Cache<String, String> cache;
final Semaphore semaphore;
public ConcurrentModificationException exception;
protected SemaphoreThread(Semaphore semaphore, Cache<String, String> cache) {
this.semaphore = semaphore;
this.cache = cache;
try {
semaphore.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void run() {
try {
work();
} catch (ConcurrentModificationException cmex) {
exception = cmex;
}
semaphore.release();
}
protected abstract void work();
}
}