Пример #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;
     }
   }
 }
Пример #2
0
 @Override
 @SuppressWarnings({"unchecked"})
 public long getOrCreate(float o) {
   if (DependencyTracker.isBypassCaches()) {
     return calculatable.calculate(owner, o);
   } else {
     preCheckDirty();
     lock(o);
     try {
       Object v = load(o);
       ExceptionHelper.throwIfExceptionRecordNotExpired(v);
       if (v != UNDEFINED) {
         DependencyTracker.mark(getDependencyNode());
         hit();
         return (Long) v;
       }
       DependencyNode callerNode = DependencyTracker.track(getDependencyNode());
       try {
         while (true) {
           try {
             return create(o);
           } catch (ResourceOccupied e) {
             if (callerNode != null) {
               throw e;
             } else {
               unlock(o);
               try {
                 e.getResource().waitForEndOfModification();
               } finally {
                 lock(o);
               }
               v = load(o);
               ExceptionHelper.throwIfExceptionRecordNotExpired(v);
               if (v != UNDEFINED) {
                 hit();
                 return (Long) v;
               }
             }
           }
         }
       } finally {
         DependencyTracker.exit(callerNode);
       }
     } finally {
       unlock(o);
       postCheckDirty();
     }
   }
 }
Пример #3
0
 @Override
 @SuppressWarnings({"unchecked"})
 public F getOrCreate(E o) {
   if (DependencyTracker.isBypassCaches()) {
     return calculatable.calculate(owner, o);
   } else {
     lock(o);
     try {
       Object v = load(o);
       if (v != UNDEFINED) {
         DependencyTracker.mark(getDependencyNode());
         hit();
         return (F) v;
       }
       DependencyNode callerNode = DependencyTracker.track(getDependencyNode());
       try {
         while (true) {
           try {
             return create(o);
           } catch (ResourceOccupied e) {
             if (callerNode != null) {
               throw e;
             } else {
               unlock(o);
               try {
                 e.getResource().waitForEndOfModification();
               } finally {
                 lock(o);
               }
               v = load(o);
               if (v != UNDEFINED) {
                 hit();
                 return (F) v;
               }
             }
           }
         }
       } finally {
         DependencyTracker.exit(callerNode);
       }
     } finally {
       unlock(o);
     }
   }
 }
  @Override
  public char getOrCreate(boolean o) {
    if (DependencyTracker.isBypassCaches()) {
      return calculatable.calculate(owner, o);
    } else {
      lock(o);
      try {
        if (isCalculated(o)) {
          DependencyTracker.mark(getDependencyNode());
          hit();
          return load(o);
        }

        DependencyNode callerNode = DependencyTracker.track(getDependencyNode());
        try {
          while (true) {
            try {
              return create(o);
            } catch (ResourceOccupied e) {
              if (callerNode != null) {
                throw e;
              } else {
                unlock(o);
                try {
                  e.getResource().waitForEndOfModification();
                } finally {
                  lock(o);
                }
                if (isCalculated(o)) {
                  hit();
                  return load(o);
                }
              }
            }
          }
        } finally {
          DependencyTracker.exit(callerNode);
        }
      } finally {
        unlock(o);
      }
    }
  }
Пример #5
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();
     }
   }
 }
Пример #6
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();
        }
      }
    }
  }