[JGIT PATCH 01/13] Fix invalid "double checked locking" in InflaterCache

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



We move the Inflater allocation out of the synchronized block as
it requires JNI code to build the libz structure.  This permits
other threads to get into the Inflater allocation faster.

We also fix the release implementation to validate the array size
only after we enter the lock, rather than before.  This prevents
us from releasing an inflater due to a stale copy of the open
count being in our processor cache.

Signed-off-by: Shawn O. Pearce <spearce@xxxxxxxxxxx>
---
 .../src/org/spearce/jgit/lib/InflaterCache.java    |   31 ++++++++++---------
 1 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/InflaterCache.java b/org.spearce.jgit/src/org/spearce/jgit/lib/InflaterCache.java
index f0f9139..578911c 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/InflaterCache.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/InflaterCache.java
@@ -59,13 +59,18 @@
 	 * 
 	 * @return an available inflater. Never null.
 	 */
-	public synchronized static Inflater get() {
+	public static Inflater get() {
+		final Inflater r = getImpl();
+		return r != null ? r : new Inflater(false);
+	}
+
+	private synchronized static Inflater getImpl() {
 		if (openInflaterCount > 0) {
 			final Inflater r = inflaterCache[--openInflaterCount];
 			inflaterCache[openInflaterCount] = null;
 			return r;
 		}
-		return new Inflater(false);
+		return null;
 	}
 
 	/**
@@ -76,23 +81,19 @@ public synchronized static Inflater get() {
 	 *            does nothing.
 	 */
 	public static void release(final Inflater i) {
-		if (i == null)
-			return;
-
-		if (openInflaterCount == SZ) {
-			i.end();
-			return;
+		if (i != null) {
+			i.reset();
+			if (releaseImpl(i))
+				i.end();
 		}
-
-		i.reset();
-		releaseImpl(i);
 	}
 
-	private static synchronized void releaseImpl(final Inflater i) {
-		if (openInflaterCount == SZ)
-			i.end();
-		else
+	private static synchronized boolean releaseImpl(final Inflater i) {
+		if (openInflaterCount < SZ) {
 			inflaterCache[openInflaterCount++] = i;
+			return false;
+		}
+		return true;
 	}
 
 	private InflaterCache() {
-- 
1.6.1.rc4.301.g5497a

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux