package com.intellij.openapi.components.impl;

import com.intellij.util.concurrency.JBLock;
import com.intellij.util.concurrency.JBReentrantReadWriteLock;
import com.intellij.util.concurrency.LockFactory;
import org.picocontainer.*;
import org.picocontainer.defaults.*;

/**
 * @author mike
 */
public class CachingComponentAdapter extends DecoratingComponentAdapter implements LifecycleManager {

  private ObjectReference instanceReference;
  private boolean disposed;
  private boolean started;
  private boolean delegateHasLifecylce;
  private JBReentrantReadWriteLock rw = LockFactory.createReadWriteLock();
  private JBLock r = rw.readLock();
  private JBLock w = rw.writeLock();

  public CachingComponentAdapter(ComponentAdapter delegate) {
    this(delegate, new SimpleReference());
  }

  public CachingComponentAdapter(ComponentAdapter delegate, ObjectReference instanceReference) {
    super(delegate);
    this.instanceReference = instanceReference;
    disposed = false;
    started = false;
    delegateHasLifecylce =
      delegate instanceof LifecycleStrategy && ((LifecycleStrategy)delegate).hasLifecycle(delegate.getComponentImplementation());
  }


  public Object getComponentInstance(PicoContainer container)
    throws PicoInitializationException, PicoIntrospectionException, AssignabilityRegistrationException, NotConcreteRegistrationException {

    r.lock();
    Object instance;
    try {
      instance = instanceReference.get();
      if (instance != null) return instance;
    }
    finally {
      r.unlock();
    }

    w.lock();
    try {
      instance = instanceReference.get();
      if (instance == null) {
        instance = super.getComponentInstance(container);
        instanceReference.set(instance);
      }
      return instance;
    }
    finally {
      w.unlock();
    }
  }

  /**
   * Starts the cached component instance
   * {@inheritDoc}
   */
  public void start(PicoContainer container) {
    if (delegateHasLifecylce) {
      if (disposed) throw new IllegalStateException("Already disposed");
      if (started) throw new IllegalStateException("Already started");
      start(getComponentInstance(container));
      started = true;
    }
  }

  /**
   * Stops the cached component instance
   * {@inheritDoc}
   */
  public void stop(PicoContainer container) {
    if (delegateHasLifecylce) {
      if (disposed) throw new IllegalStateException("Already disposed");
      if (!started) throw new IllegalStateException("Not started");
      stop(getComponentInstance(container));
      started = false;
    }
  }

  /**
   * Disposes the cached component instance
   * {@inheritDoc}
   */
  public void dispose(PicoContainer container) {
    if (delegateHasLifecylce) {
      if (disposed) throw new IllegalStateException("Already disposed");
      dispose(getComponentInstance(container));
      disposed = true;
    }
  }

  public boolean hasLifecycle() {
    return delegateHasLifecylce;
  }

}

@@ -51,157 +51,321 @@
 ort 
-com.intellij.util.concurrency.JBLock;%0Aimport com.intellij.util.concurrency.JBReentrantReadWriteLock;%0Aimport com.intellij.util.concurrency.LockFactory
+org.picocontainer.ComponentAdapter;%0Aimport org.picocontainer.PicoContainer;%0Aimport org.picocontainer.PicoInitializationException;%0Aimport org.picocontainer.PicoIntrospectionException;%0Aimport org.picocontainer.defaults.AssignabilityRegistrationException;%0Aimport org.picocontainer.defaults.DecoratingComponentAdapter
 ;%0Aim
@@ -387,17 +387,42 @@
 ntainer.
-*
+defaults.LifecycleStrategy
 ;%0Aimport
@@ -449,17 +449,48 @@
 efaults.
-*
+NotConcreteRegistrationException
 ;%0A%0A/**%0A 
@@ -584,39 +584,10 @@
 ter 
-implements LifecycleManager 
 %7B%0A
-%0A
   pr
@@ -596,41 +596,30 @@
 ate 
-ObjectReference instanceReference
+volatile Object cached
 ;%0A  
@@ -725,421 +725,124 @@
 ate 
-JBReentrantReadWriteLock rw = LockFactory.createReadWriteLock();%0A  private JBLock r = rw.readLock();%0A  private JBLock w = rw.writeLock();%0A%0A  public CachingComponentAdapter(ComponentAdapter delegate) %7B%0A    this(delegate, new SimpleReference());%0A  %7D%0A%0A  public CachingComponentAdapter(ComponentAdapter delegate, ObjectReference instanceReference) %7B%0A    super(delegate);%0A    this.instanceReference = instanceReference
+final Object lock = new Object();%0A%0A  public CachingComponentAdapter(ComponentAdapter delegate) %7B%0A    super(delegate)
 ;%0A  
@@ -1044,17 +1044,16 @@
 );%0A  %7D%0A%0A
-%0A
   public
@@ -1254,293 +1254,138 @@
     
-r.lock();%0A    Object instance;%0A    try %7B%0A      instance = instanceReference.get();%0A      if (instance != null) return instance;%0A    %7D%0A    finally %7B%0A      r.unlock();%0A    %7D%0A%0A    w.lock();%0A    try %7B%0A      instance = instanceReference.get();%0A      if (instance == null) %7B%0A        instance
+Object o = cached;%0A    if (o != null) return o;%0A    synchronized (lock) %7B%0A      o = cached;%0A      if (o != null) return o;%0A      o
  = s
@@ -1432,45 +1432,20 @@
     
-  instanceReference.set(instance);%0A  
+cached = o;%0A
     
@@ -1454,70 +1454,17 @@
     
- 
- 
 return 
-instance;%0A    %7D%0A    finally %7B%0A      w.unlock();%0A    %7D
+o;
 %0A  %7D

use DCL instead of readwrite locks