public synchronized long getAllocatedSize() {
   long sum = 0;
   for (PowerOfTwoAllocator a : sliceAllocators) {
     sum += a.occupied();
   }
   return sum;
 }
 public long getAllocatedSizeUnSync() {
   long sum = 0;
   for (PowerOfTwoAllocator a : sliceAllocators) {
     sum += a.occupied();
   }
   return sum;
 }
  private Page allocateAsThief(final int size, boolean victim, OffHeapStorageArea owner) {
    Page free = allocateFromFree(size, victim, owner);

    if (free != null) {
      return free;
    }

    // do thieving here...
    PowerOfTwoAllocator victimAllocator = null;
    PowerOfTwoAllocator sliceAllocator = null;
    List<Page> targets = Collections.emptyList();
    Collection<AllocatedRegion> tempHolds = new ArrayList<AllocatedRegion>();
    Map<OffHeapStorageArea, Collection<Page>> releases =
        new IdentityHashMap<OffHeapStorageArea, Collection<Page>>();

    synchronized (this) {
      for (int i = 0; i < victimAllocators.size(); i++) {
        int address = victimAllocators.get(i).find(size, victim ? CEILING : FLOOR);
        if (address >= 0) {
          victimAllocator = victimAllocators.get(i);
          sliceAllocator = sliceAllocators.get(i);
          targets = findVictimPages(i, address, size);

          // need to claim everything that falls within the range of our allocation
          int claimAddress = address;
          for (Page p : targets) {
            victimAllocator.claim(p.address(), p.size());
            int claimSize = p.address() - claimAddress;
            if (claimSize > 0) {
              tempHolds.add(new AllocatedRegion(claimAddress, claimSize));
              sliceAllocator.claim(claimAddress, claimSize);
              victimAllocator.claim(claimAddress, claimSize);
            }
            claimAddress = p.address() + p.size();
          }
          int claimSize = (address + size) - claimAddress;
          if (claimSize > 0) {
            tempHolds.add(new AllocatedRegion(claimAddress, claimSize));
            sliceAllocator.claim(claimAddress, claimSize);
            victimAllocator.claim(claimAddress, claimSize);
          }
          break;
        }
      }

      for (Page p : targets) {
        OffHeapStorageArea a = p.binding();
        Collection<Page> c = releases.get(a);
        if (c == null) {
          c = new LinkedList<Page>();
          c.add(p);
          releases.put(a, c);
        } else {
          c.add(p);
        }
      }
    }

    /*
     * Drop the page source synchronization here to prevent deadlock against
     * map/cache threads.
     */
    Collection<Page> results = new LinkedList<Page>();
    for (Entry<OffHeapStorageArea, Collection<Page>> e : releases.entrySet()) {
      OffHeapStorageArea a = e.getKey();
      Collection<Page> p = e.getValue();
      results.addAll(a.release(p));
    }

    List<Page> failedReleases = new ArrayList<Page>();
    synchronized (this) {
      for (AllocatedRegion r : tempHolds) {
        sliceAllocator.free(r.address, r.size);
        victimAllocator.free(r.address, r.size);
      }

      if (results.size() == targets.size()) {
        for (Page p : targets) {
          victimAllocator.free(p.address(), p.size());
          free(p);
        }
        return allocateFromFree(size, victim, owner);
      } else {
        for (Page p : targets) {
          if (results.contains(p)) {
            victimAllocator.free(p.address(), p.size());
            free(p);
          } else {
            failedReleases.add(p);
          }
        }
      }
    }

    try {
      return allocateAsThief(size, victim, owner);
    } finally {
      synchronized (this) {
        for (Page p : failedReleases) {
          // this is just an ugly way of doing an identity equals based contains
          if (victims.get(p.index()).floor(p) == p) {
            victimAllocator.free(p.address(), p.size());
          }
        }
      }
    }
  }