private long mutateWithDefault(Mutator t, String key, long by, long def,
      int exp) {
    long rv = mutate(t, key, by, def, exp);
    // The ascii protocol doesn't support defaults, so I added them
    // manually here.
    if (rv == -1) {
      Future<Boolean> f = asyncStore(StoreType.add, key, exp,
          String.valueOf(def));
      try {
        if (f.get(operationTimeout, TimeUnit.MILLISECONDS)) {
          rv = def;
        } else {
          rv = mutate(t, key, by, 0, exp);
          assert rv != -1 : "Failed to mutate or init value";
        }
      } catch (InterruptedException e) {
        throw new RuntimeException("Interrupted waiting for store", e);
      } catch (ExecutionException e) {
        if(e.getCause() instanceof CancellationException) {
          throw (CancellationException) e.getCause();
        } else {
          throw new RuntimeException("Failed waiting for store", e);
        }
      } catch (TimeoutException e) {
        throw new OperationTimeoutException("Timeout waiting to mutate or init"
          + " value" + buildTimeoutMessage(operationTimeout,
            TimeUnit.MILLISECONDS), e);
      }
    }
    return rv;
  }
Decrement the given counter, returning the new value.

Due to the way the memcached server operates on items, incremented and
decremented items will be returned as Strings with any operations that
return a value.

@param key the key
@param by the amount to decrement
@param def the default value (if the counter does not exist)
@param exp the expiration of this object
@return the new value, or -1 if we were unable to decrement or add
@throws OperationTimeoutException if the global operation timeout is
          exceeded
@throws IllegalStateException in the rare circumstance where queue is too
          full to accept any more requests
src/main/java/net/spy/memcached/MemcachedClient.java