@Override
 public synchronized ICPPTemplateInstance[] getAllInstances() {
   if (instances != null) {
     ICPPTemplateInstance[] result = new ICPPTemplateInstance[instances.size()];
     for (int i = 0; i < instances.size(); i++) {
       result[i] = (ICPPTemplateInstance) instances.getAt(i);
     }
     return result;
   }
   return ICPPTemplateInstance.EMPTY_TEMPLATE_INSTANCE_ARRAY;
 }
 @Override
 public final synchronized void addInstance(
     ICPPTemplateArgument[] arguments, ICPPTemplateInstance instance) {
   if (instances == null) instances = new ObjectMap(2);
   String key = ASTTypeUtil.getArgumentListString(arguments, true);
   instances.put(key, instance);
 }
  @Override
  public IBinding specializeMember(IBinding original, IASTNode point) {
    if (specializationMap == null) {
      final Long key = record + PDOMCPPLinkage.CACHE_INSTANCE_SCOPE;
      Object cached = getPDOM().getCachedResult(key);
      if (cached != null) {
        specializationMap = (ObjectMap) cached;
      } else {
        final ObjectMap newMap = new ObjectMap(2);
        try {
          PDOMClassUtil.NestedClassCollector visitor = new PDOMClassUtil.NestedClassCollector();
          PDOMCPPClassScope.acceptViaCache(this, visitor, false);
          final ICPPClassType[] nested = visitor.getNestedClasses();
          for (ICPPClassType classType : nested) {
            if (classType instanceof ICPPSpecialization) {
              newMap.put(((ICPPSpecialization) classType).getSpecializedBinding(), classType);
            }
          }
        } catch (CoreException e) {
          CCorePlugin.log(e);
        }
        specializationMap = (ObjectMap) getPDOM().putCachedResult(key, newMap, false);
      }
    }
    Set<IBinding> set;
    synchronized (specializationMap) {
      IBinding result = (IBinding) specializationMap.get(original);
      if (result != null) return result;
      set = fInProgress.get();
      if (set == null) {
        set = new HashSet<IBinding>();
        fInProgress.set(set);
      }
      if (!set.add(original)) return RecursionResolvingBinding.createFor(original, point);
    }
    IBinding newSpec = CPPTemplates.createSpecialization(this, original, point);
    set.remove(original);

    synchronized (specializationMap) {
      IBinding oldSpec = (IBinding) specializationMap.put(original, newSpec);
      if (oldSpec != null) {
        specializationMap.put(original, oldSpec);
        return oldSpec;
      }
    }
    return newSpec;
  }
 @Override
 public final synchronized ICPPTemplateInstance getInstance(ICPPTemplateArgument[] arguments) {
   if (instances != null) {
     String key = ASTTypeUtil.getArgumentListString(arguments, true);
     return (ICPPTemplateInstance) instances.get(key);
   }
   return null;
 }