Improved encapsulation of thread synchronisation as follows

- replaced use of Object instance mutex with a private final Lock object
- replaced Object signaling with specific condition signalling
This commit is contained in:
Abraham Kiggundu
2014-12-23 23:55:56 +03:00
parent 276dcb1038
commit b074978472
19 changed files with 1001 additions and 478 deletions

View File

@@ -4,6 +4,10 @@ import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Logger;
class PollingRemovableDriveMonitor implements RemovableDriveMonitor, Runnable {
@@ -14,11 +18,14 @@ class PollingRemovableDriveMonitor implements RemovableDriveMonitor, Runnable {
private final Executor ioExecutor;
private final RemovableDriveFinder finder;
private final long pollingInterval;
private final Object pollingLock = new Object();
private volatile boolean running = false;
private volatile Callback callback = null;
private final Lock synchLock = new ReentrantLock();
private final Condition stopPolling = synchLock.newCondition();
public PollingRemovableDriveMonitor(Executor ioExecutor,
RemovableDriveFinder finder, long pollingInterval) {
this.ioExecutor = ioExecutor;
@@ -34,8 +41,12 @@ class PollingRemovableDriveMonitor implements RemovableDriveMonitor, Runnable {
public void stop() throws IOException {
running = false;
synchronized(pollingLock) {
pollingLock.notifyAll();
synchLock.lock();
try {
stopPolling.signalAll();
}
finally {
synchLock.unlock();
}
}
@@ -43,8 +54,12 @@ class PollingRemovableDriveMonitor implements RemovableDriveMonitor, Runnable {
try {
Collection<File> drives = finder.findRemovableDrives();
while(running) {
synchronized(pollingLock) {
pollingLock.wait(pollingInterval);
synchLock.lock();
try {
stopPolling.await(pollingInterval, TimeUnit.MILLISECONDS);
}
finally{
synchLock.unlock();
}
if(!running) return;
Collection<File> newDrives = finder.findRemovableDrives();

View File

@@ -4,6 +4,9 @@ import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import net.contentobjects.jnotify.JNotify;
import net.contentobjects.jnotify.JNotifyListener;
@@ -21,7 +24,11 @@ JNotifyListener {
private Callback callback = null; // Locking: this
protected abstract String[] getPathsToWatch();
//TODO: rationalise this in a further refactor
private final Lock synchLock = new ReentrantLock();
private static final Lock staticSynchLock = new ReentrantLock();
private static Throwable tryLoad() {
try {
Class.forName("net.contentobjects.jnotify.JNotify");
@@ -33,12 +40,18 @@ JNotifyListener {
}
}
public static synchronized void checkEnabled() throws IOException {
if(!triedLoad) {
loadError = tryLoad();
triedLoad = true;
public static void checkEnabled() throws IOException {
staticSynchLock.lock();
try {
if(!triedLoad) {
loadError = tryLoad();
triedLoad = true;
}
if(loadError != null) throw new IOException(loadError.toString());
}
finally{
staticSynchLock.unlock();
}
if(loadError != null) throw new IOException(loadError.toString());
}
public void start(Callback callback) throws IOException {
@@ -49,34 +62,46 @@ JNotifyListener {
if(new File(path).exists())
watches.add(JNotify.addWatch(path, mask, false, this));
}
synchronized(this) {
assert !started;
assert this.callback == null;
started = true;
this.callback = callback;
this.watches.addAll(watches);
}
synchLock.lock();
try {
assert !started;
assert this.callback == null;
started = true;
this.callback = callback;
this.watches.addAll(watches);
}
finally{
synchLock.unlock();
}
}
public void stop() throws IOException {
checkEnabled();
List<Integer> watches;
synchronized(this) {
assert started;
assert callback != null;
started = false;
callback = null;
watches = new ArrayList<Integer>(this.watches);
this.watches.clear();
}
synchLock.lock();
try {
assert started;
assert callback != null;
started = false;
callback = null;
watches = new ArrayList<Integer>(this.watches);
this.watches.clear();
}
finally{
synchLock.unlock();
}
for(Integer w : watches) JNotify.removeWatch(w);
}
public void fileCreated(int wd, String rootPath, String name) {
Callback callback;
synchronized(this) {
callback = this.callback;
}
synchLock.lock();
try {
callback = this.callback;
}
finally{
synchLock.unlock();
}
if(callback != null)
callback.driveInserted(new File(rootPath + "/" + name));
}