diff options
author | Thomas Watson | 2014-11-07 22:13:28 +0000 |
---|---|---|
committer | Thomas Watson | 2014-11-07 22:13:28 +0000 |
commit | d9b63c1587a976988f98635f4388f602f1a4f55e (patch) | |
tree | 9d9990b0712710784fc20bd832bc5dfde795457b /bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/container | |
parent | 67afa78e319b7bff12529b25790047bd754d23a0 (diff) | |
download | rt.equinox.framework-d9b63c1587a976988f98635f4388f602f1a4f55e.tar.gz rt.equinox.framework-d9b63c1587a976988f98635f4388f602f1a4f55e.tar.xz rt.equinox.framework-d9b63c1587a976988f98635f4388f602f1a4f55e.zip |
Bug 449779 - Deadlock within the OSGi framework
- Introduce and use AtomicLazyInitializer to manage construction of the loader
- Remove the monitor lock from ModuleWiring
Diffstat (limited to 'bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/container')
-rw-r--r-- | bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/container/AtomicLazyInitializer.java | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/container/AtomicLazyInitializer.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/container/AtomicLazyInitializer.java new file mode 100644 index 000000000..bb72070d5 --- /dev/null +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/container/AtomicLazyInitializer.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright (c) 2014 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.osgi.internal.container; + +import java.util.concurrent.Callable; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A helper class for doing lazy initialization + * + * @param <V> the type of object to lazy initialize + */ +public class AtomicLazyInitializer<V> { + private final AtomicReference<V> holder = new AtomicReference<V>(); + + /** + * Gets the current value. If the value has not been initialized then + * {@code null} is returned; + * @return the current value + */ + public final V get() { + return holder.get(); + } + + /** + * Atomically gets the current initialized value. If the current value is {@code null} + * then the supplied initializer is called to create the value returned. + * @param initializer the initializer to call if the current value is {@code null} + * @return the initialized value. May return {@code null} if initializer returns null. + */ + public final V getInitialized(Callable<V> initializer) { + V result = holder.get(); + if (result != null) { + return result; + } + // Must hold a lock to ensure the operation is atomic. + synchronized (holder) { + result = holder.get(); + if (result != null) { + return result; + } + try { + result = initializer.call(); + } catch (Exception e) { + unchecked(e); + } + holder.set(result); + return result; + } + } + + /** + * Gets the current value and clears the value for future calls to this lazy initializer. + * @return the current value + */ + public final V getAndClear() { + return holder.getAndSet(null); + } + + private static <T> T unchecked(Exception exception) { + return AtomicLazyInitializer.<T, RuntimeException> unchecked0(exception); + } + + @SuppressWarnings("unchecked") + private static <T, E extends Exception> T unchecked0(Exception exception) throws E { + throw (E) exception; + } +}
\ No newline at end of file |