Beispiel #1
0
 /**
  * Collects all dependent nodes of root node and locks them.
  *
  * @param rootNode root node to lookup dependencies from
  * @return a list of dependent caches and a super lock for this list. Note: returned super lock is
  *     <b>already locked</b> unless there was an exception thrown.
  */
 public static RecursiveLock lockRecursive(DependencyNode rootNode) {
   TIdentityHashSet<CleaningNode> elements =
       DependencyTracker.getAllDependentNodes(Collections.singleton(rootNode));
   Iterable<DependencyNode> nodes = nodeMapping(elements);
   while (true) {
     SuperLock superLock = getSuperLock(elements);
     superLock.lock();
     try {
       TIdentityHashSet<CleaningNode> newElements =
           DependencyTracker.getAllDependentNodes(nodes, elements);
       if (!newElements.containsAll(elements)) {
         // we have to unlock all locks and lock them again among with new ones as advanced locking
         // algorithm
         // locks guarantees the absence of deadlocks only if all locks are locked at once.
         superLock.unlock();
         elements.addAll(newElements);
         continue;
       }
       return new RecursiveLock(elements, superLock);
     } catch (Error e) {
       // we have to unlock it on exception
       superLock.unlock();
       throw e;
     } catch (RuntimeException e) {
       // we have to unlock it on exception
       superLock.unlock();
       throw e;
     }
   }
 }
Beispiel #2
0
 public static void lockAndClear(Collection<? extends CleaningNode> elements) {
   Iterable<DependencyNode> nodes = nodeMapping(elements);
   TIdentityHashSet<CleaningNode> elementsAndDependent =
       DependencyTracker.getAllDependentNodes(nodes, elements);
   while (true) {
     SuperLock superLock = getSuperLock(elementsAndDependent);
     superLock.lock();
     try {
       TIdentityHashSet<CleaningNode> newElements =
           DependencyTracker.getAllDependentNodes(nodes, elements);
       if (newElements.equals(elementsAndDependent)) {
         for (CleaningNode element : elementsAndDependent) {
           element.clear();
         }
         return;
       }
       // the set of dependent caches has been altered, lock everything again
       elementsAndDependent = newElements;
     } finally {
       superLock.unlock();
     }
   }
 }
Beispiel #3
0
  public static void clear(@Nonnull CleanableInstanceList list) {
    List<WeakList<?>> lists = new ArrayList<WeakList<?>>();
    List<CleaningNode> elements = new ArrayList<CleaningNode>();

    Iterable<DependencyNode> nodes = nodeMapping(elements);

    outer:
    while (true) {
      int subtreeVersion = list.deepLock();
      try {
        lists.clear();
        list.getLists(lists);
      } finally {
        list.deepUnlock();
      }

      int listsVersion = lockLists(lists);
      try {
        elements.clear();
        list.getCaches(elements);
      } finally {
        unlockLists(lists);
      }
      TIdentityHashSet<CleaningNode> elementsAndDependent =
          DependencyTracker.getAllDependentNodes(nodes, elements);
      // dependency modification check loop
      while (true) {
        SuperLock superLock = getSuperLock(elementsAndDependent);
        superLock.lock();
        try {
          TIdentityHashSet<CleaningNode> newElements =
              DependencyTracker.getAllDependentNodes(nodes, elements);
          if (!newElements.equals(elementsAndDependent)) {
            // the set of dependent caches has been altered, lock everything again
            elementsAndDependent = newElements;
            continue;
          }
          int newSubtreeVersion = list.deepLock();
          try {
            if (newSubtreeVersion != subtreeVersion) {
              continue outer;
            }
            int newListsVersion = lockLists(lists);
            try {
              if (newListsVersion != listsVersion) {
                continue outer;
              }
              clear(elementsAndDependent);
              return;
            } finally {
              unlockLists(lists);
            }
          } finally {
            list.deepUnlock();
          }
        } finally {
          superLock.unlock();
        }
      }
    }
  }