You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@river.apache.org by pe...@apache.org on 2013/11/10 12:29:17 UTC

svn commit: r1540464 - in /river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini: reggie/RegistrarImpl.java thread/ReadersPriorityWriter.java

Author: peter_firmstone
Date: Sun Nov 10 11:29:17 2013
New Revision: 1540464

URL: http://svn.apache.org/r1540464
Log:
Reggie is having some concurrency issues on Windows Server 2008 and Java 7 (see qa refactoring tests on this platform), this new subclass of ReadersWriter, more accurately implements the original intent of the class by using multiple Conditions with an explicit lock.  While I'm not expecting this to fix the concurrency issues, it rules out the case where a writer is unable to obtain a lock in order to wait for readers to finish.

Added:
    river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/thread/ReadersPriorityWriter.java
Modified:
    river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/reggie/RegistrarImpl.java

Modified: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/reggie/RegistrarImpl.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/reggie/RegistrarImpl.java?rev=1540464&r1=1540463&r2=1540464&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/reggie/RegistrarImpl.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/reggie/RegistrarImpl.java Sun Nov 10 11:29:17 2013
@@ -34,11 +34,11 @@ import com.sun.jini.proxy.MarshalledWrap
 import com.sun.jini.reliableLog.LogHandler;
 import com.sun.jini.reliableLog.ReliableLog;
 import com.sun.jini.start.LifeCycle;
-import org.apache.river.api.util.Commission;
 import com.sun.jini.thread.InterruptedStatusThread;
+import com.sun.jini.thread.ReadersPriorityWriter;
 import com.sun.jini.thread.ReadersWriter;
-import com.sun.jini.thread.ReadyState;
 import com.sun.jini.thread.ReadersWriter.ConcurrentLockException;
+import com.sun.jini.thread.ReadyState;
 import com.sun.jini.thread.TaskManager;
 import java.io.DataInputStream;
 import java.io.IOException;
@@ -69,27 +69,24 @@ import java.rmi.activation.ActivationID;
 import java.rmi.activation.ActivationSystem;
 import java.security.AccessControlContext;
 import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.Random;
+import java.util.SortedMap;
 import java.util.TreeMap;
 import java.util.logging.Level;
 import java.util.logging.Logger;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.SortedMap;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentLinkedQueue;
-import java.util.concurrent.ConcurrentSkipListMap;
 import javax.net.ServerSocketFactory;
 import javax.net.SocketFactory;
 import javax.security.auth.Subject;
@@ -137,6 +134,7 @@ import net.jini.security.BasicProxyPrepa
 import net.jini.security.ProxyPreparer;
 import net.jini.security.TrustVerifier;
 import net.jini.security.proxytrust.ServerProxyTrust;
+import org.apache.river.api.util.Commission;
 
 /**
  * Base server-side implementation of a lookup service, subclassed by
@@ -314,7 +312,7 @@ class RegistrarImpl implements Registrar
     private final Thread snapshotter;
 
     /** Concurrent object to control read and write access */
-    private final ReadersWriter concurrentObj = new ReadersWriter();
+    private final ReadersWriter concurrentObj = new ReadersPriorityWriter();
     /** Object for synchronizing with the service expire thread */
     private final Object serviceNotifier = new Object();
     /** Object for synchronizing with the event expire thread */

Added: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/thread/ReadersPriorityWriter.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/thread/ReadersPriorityWriter.java?rev=1540464&view=auto
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/thread/ReadersPriorityWriter.java (added)
+++ river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/thread/ReadersPriorityWriter.java Sun Nov 10 11:29:17 2013
@@ -0,0 +1,154 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.sun.jini.thread;
+
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * ReadersPriorityWriter gives priority to waiting priority writers, then 
+ * writers, then readers.  While writers or priority writers are waiting to
+ * obtain a lock, new readers will wait until the priority writers and
+ * writers have released all locks.
+ * 
+ * Unlike its parent class, ReadersPriorityWriter ensures waiting writers
+ * are notified before readers, avoiding unnecessary awakening of multiple
+ * readers, instead of a waiting writer.
+ * 
+ * @author Peter Firmstone.
+ */
+public class ReadersPriorityWriter extends ReadersWriter {
+    private boolean activeWriter;
+    private int waitingWriters;
+    private int activeReaders;
+    private int waitingPriorityWriters;
+    private final Lock lock;
+    private final Condition waitingPriorityWriter;
+    private final Condition waitingWriter;
+    private final Condition waitingReader;
+    
+    public ReadersPriorityWriter() {
+        super();
+        lock = new ReentrantLock();
+        waitingPriorityWriter = lock.newCondition();
+        waitingWriter = lock.newCondition();
+        waitingReader = lock.newCondition();
+        activeWriter = false;
+        waitingWriters = 0;
+        activeReaders = 0;
+        waitingPriorityWriters = 0;
+    }
+    
+    /** Obtain a read lock.  Multiple concurrent readers allowed. */
+    public void readLock() {
+        lock.lock();
+        try {
+            while (activeWriter || waitingWriters != 0) {
+                try {
+                    waitingReader.await();
+                } catch (InterruptedException e) {
+                    throw new ConcurrentLockException(
+                                           "read lock interrupted in thread");
+                }
+            }
+            activeReaders++;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /** Release a read lock. */
+    public void readUnlock() {
+        lock.lock();
+        try {
+            activeReaders--;
+            if (activeReaders == 0){
+                if ( waitingPriorityWriters > 0 ) waitingPriorityWriter.signal();
+                else if ( waitingWriters > 0 ) waitingWriter.signal();
+            }
+        } finally {
+            lock.unlock();
+        } 
+    }
+
+    /** Obtain a regular write lock.  Only a single writer allowed at once. */
+    public void writeLock() {
+        lock.lock();
+        try {
+            while (activeWriter ||
+                   activeReaders != 0 ||
+                   waitingPriorityWriters != 0)
+            {
+                try {
+                    waitingWriters++;
+                    try {
+                        waitingWriter.await();
+                    } finally {
+                        waitingWriters--;
+                    }
+                } catch (InterruptedException e) {
+                    throw new ConcurrentLockException(
+                                          "write lock interrupted in thread");
+                }
+            }
+            activeWriter = true;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /** Obtain a priority write lock.  Only a single writer allowed at once. */
+    public void priorityWriteLock() {
+        lock.lock();
+        try {
+            while (activeWriter || activeReaders != 0) {
+                try {
+                    waitingWriters++;
+                    waitingPriorityWriters++;
+                    try {
+                        waitingPriorityWriter.await();
+                    } finally {
+                        waitingWriters--;
+                        waitingPriorityWriters--;
+                    }
+                } catch (InterruptedException e) {
+                    throw new ConcurrentLockException(
+                                          "write lock interrupted in thread");
+                }
+            }
+            activeWriter = true;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /** Release a (regular or priority) write lock. */
+    public void writeUnlock() {
+        lock.lock();
+        try {
+            activeWriter = false;
+            if (waitingWriters > 0) {
+                if (waitingPriorityWriters > 0) waitingPriorityWriter.signal();
+                else waitingWriter.signal();
+            } else waitingReader.signalAll();
+        } finally {
+            lock.unlock();
+        }
+    }
+}