Added RetryingFunction for simplified retry support.
Moved retry logic out of primitives (AtomicCounter) to the caller site.

Change-Id: I319d61f153f98d421baf32a1b5cd69d20dc63427
diff --git a/utils/misc/src/main/java/org/onlab/util/Tools.java b/utils/misc/src/main/java/org/onlab/util/Tools.java
index 301f411..b12d15c 100644
--- a/utils/misc/src/main/java/org/onlab/util/Tools.java
+++ b/utils/misc/src/main/java/org/onlab/util/Tools.java
@@ -46,6 +46,8 @@
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
+import java.util.function.Function;
+import java.util.function.Supplier;
 import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
 
@@ -227,6 +229,41 @@
     }
 
     /**
+     * Returns a function that retries execution on failure.
+     * @param base base function
+     * @param exceptionClass type of exception for which to retry
+     * @param maxRetries max number of retries before giving up
+     * @param maxDelayBetweenRetries max delay between successive retries. The actual delay is randomly picked from
+     * the interval (0, maxDelayBetweenRetries]
+     * @return function
+     */
+    public static <U, V> Function<U, V> retryable(Function<U, V> base,
+            Class<? extends Throwable> exceptionClass,
+            int maxRetries,
+            int maxDelayBetweenRetries) {
+        return new RetryingFunction<>(base, exceptionClass, maxRetries, maxDelayBetweenRetries);
+    }
+
+    /**
+     * Returns a Supplier that retries execution on failure.
+     * @param base base supplier
+     * @param exceptionClass type of exception for which to retry
+     * @param maxRetries max number of retries before giving up
+     * @param maxDelayBetweenRetries max delay between successive retries. The actual delay is randomly picked from
+     * the interval (0, maxDelayBetweenRetries]
+     * @return supplier
+     */
+    public static <V> Supplier<V> retryable(Supplier<V> base,
+            Class<? extends Throwable> exceptionClass,
+            int maxRetries,
+            int maxDelayBetweenRetries) {
+        return () -> new RetryingFunction<>(v -> base.get(),
+                exceptionClass,
+                maxRetries,
+                maxDelayBetweenRetries).apply(null);
+    }
+
+    /**
      * Suspends the current thread for a random number of millis between 0 and
      * the indicated limit.
      *