From c5f9dfc3cfe0acc0b6b622110381db6e83149b51 Mon Sep 17 00:00:00 2001 From: Luc Boudreau Date: Fri, 28 Sep 2012 10:38:24 +0000 Subject: [PATCH] Makes DeferredNamedList thread safe to prevent concurrent modifications exceptions. git-svn-id: https://olap4j.svn.sourceforge.net/svnroot/olap4j/trunk@549 c6a108a4-781c-0410-a6c6-c2d559e19af0 --- .../driver/xmla/DeferredNamedListImpl.java | 44 ++++++++++++------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/src/org/olap4j/driver/xmla/DeferredNamedListImpl.java b/src/org/olap4j/driver/xmla/DeferredNamedListImpl.java index 41b135e..b664156 100644 --- a/src/org/olap4j/driver/xmla/DeferredNamedListImpl.java +++ b/src/org/olap4j/driver/xmla/DeferredNamedListImpl.java @@ -26,6 +26,7 @@ import java.util.AbstractList; import java.util.Map; +import java.util.concurrent.Semaphore; /** * Named list which instantiates itself on first use. @@ -57,6 +58,7 @@ class DeferredNamedListImpl protected final XmlaOlap4jConnection.Context context; protected final XmlaOlap4jConnection.Handler handler; protected final Object[] restrictions; + protected final Semaphore semaphore = new Semaphore(1); DeferredNamedListImpl( XmlaOlap4jConnection.MetadataRequest metadataRequest, @@ -80,24 +82,32 @@ void reset() { } private NamedList getList() { - switch (state) { - case POPULATING: - throw new RuntimeException("recursive population"); - case NEW: - try { - state = State.POPULATING; - populateList(list); - state = State.POPULATED; - } catch (OlapException e) { - state = State.NEW; - // TODO: fetch metadata on getCollection() method, so we - // can't get an exception while traversing the list - throw new RuntimeException(e); + try { + semaphore.acquire(); + switch (state) { + case POPULATING: + throw new RuntimeException("recursive population"); + case NEW: + try { + state = State.POPULATING; + populateList(list); + state = State.POPULATED; + } catch (OlapException e) { + state = State.NEW; + // TODO: fetch metadata on getCollection() method, so we + // can't get an exception while traversing the list + throw new RuntimeException(e); + } + // fall through + case POPULATED: + default: + return list; } - // fall through - case POPULATED: - default: - return list; + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException(e); + } finally { + semaphore.release(); } }