]> git.argeo.org Git - lgpl/argeo-commons.git/blobdiff - org.argeo.api.uuid/src/org/argeo/api/uuid/AbstractAsyncUuidFactory.java
Integrate UUID API
[lgpl/argeo-commons.git] / org.argeo.api.uuid / src / org / argeo / api / uuid / AbstractAsyncUuidFactory.java
diff --git a/org.argeo.api.uuid/src/org/argeo/api/uuid/AbstractAsyncUuidFactory.java b/org.argeo.api.uuid/src/org/argeo/api/uuid/AbstractAsyncUuidFactory.java
new file mode 100644 (file)
index 0000000..2cdb59f
--- /dev/null
@@ -0,0 +1,130 @@
+package org.argeo.api.uuid;
+
+import java.security.SecureRandom;
+import java.util.UUID;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.ForkJoinPool;
+import java.util.concurrent.ForkJoinTask;
+import java.util.concurrent.ThreadLocalRandom;
+
+/**
+ * Execute {@link UUID} creations in {@link ForkJoinPool#commonPool()}. The goal
+ * is to provide good performance while staying within the parallelism defined
+ * for the system, so as to overwhelm it if many UUIDs are requested.
+ * Additionally, with regard to time based UUIDs, since we use
+ * {@link ConcurrentTimeUuidState}, which maintains one "clock sequence" per
+ * thread, we want to limit the number of threads accessing the actual
+ * generation method.
+ */
+public abstract class AbstractAsyncUuidFactory extends AbstractUuidFactory implements AsyncUuidFactory {
+       private SecureRandom secureRandom;
+       protected TimeUuidState timeUuidState;
+
+       public AbstractAsyncUuidFactory() {
+               secureRandom = newSecureRandom();
+               timeUuidState = new ConcurrentTimeUuidState(secureRandom, null);
+       }
+       /*
+        * ABSTRACT METHODS
+        */
+
+       protected abstract UUID newTimeUUID();
+
+       protected abstract UUID newTimeUUIDwithMacAddress();
+
+       protected abstract SecureRandom newSecureRandom();
+
+       /*
+        * SYNC OPERATIONS
+        */
+       protected UUID newRandomUUIDStrong() {
+               return newRandomUUID(secureRandom);
+       }
+
+       public UUID randomUUIDWeak() {
+               return newRandomUUID(ThreadLocalRandom.current());
+       }
+
+       /*
+        * ASYNC OPERATIONS (heavy)
+        */
+       protected CompletionStage<UUID> request(ForkJoinTask<UUID> newUuid) {
+               return CompletableFuture.supplyAsync(newUuid::invoke).minimalCompletionStage();
+       }
+
+       @Override
+       public CompletionStage<UUID> requestNameUUIDv5(UUID namespace, byte[] data) {
+               return request(futureNameUUIDv5(namespace, data));
+       }
+
+       @Override
+       public CompletionStage<UUID> requestNameUUIDv3(UUID namespace, byte[] data) {
+               return request(futureNameUUIDv3(namespace, data));
+       }
+
+       @Override
+       public CompletionStage<UUID> requestRandomUUIDStrong() {
+               return request(futureRandomUUIDStrong());
+       }
+
+       @Override
+       public CompletionStage<UUID> requestTimeUUID() {
+               return request(futureTimeUUID());
+       }
+
+       @Override
+       public CompletionStage<UUID> requestTimeUUIDwithMacAddress() {
+               return request(futureTimeUUIDwithMacAddress());
+       }
+
+       /*
+        * ASYNC OPERATIONS (light)
+        */
+       protected ForkJoinTask<UUID> submit(Callable<UUID> newUuid) {
+               return ForkJoinTask.adapt(newUuid);
+       }
+
+       @Override
+       public ForkJoinTask<UUID> futureNameUUIDv5(UUID namespace, byte[] data) {
+               return submit(() -> newNameUUIDv5(namespace, data));
+       }
+
+       @Override
+       public ForkJoinTask<UUID> futureNameUUIDv3(UUID namespace, byte[] data) {
+               return submit(() -> newNameUUIDv3(namespace, data));
+       }
+
+       @Override
+       public ForkJoinTask<UUID> futureRandomUUIDStrong() {
+               return submit(this::newRandomUUIDStrong);
+       }
+
+       @Override
+       public ForkJoinTask<UUID> futureTimeUUID() {
+               return submit(this::newTimeUUID);
+       }
+
+       @Override
+       public ForkJoinTask<UUID> futureTimeUUIDwithMacAddress() {
+               return submit(this::newTimeUUIDwithMacAddress);
+       }
+
+//     @Override
+//     public UUID timeUUID() {
+//             if (ConcurrentTimeUuidState.isTimeUuidThread.get())
+//                     return newTimeUUID();
+//             else
+//                     return futureTimeUUID().join();
+//     }
+//
+//     @Override
+//     public UUID timeUUIDwithMacAddress() {
+//             if (ConcurrentTimeUuidState.isTimeUuidThread.get())
+//                     return newTimeUUIDwithMacAddress();
+//             else
+//                     return futureTimeUUIDwithMacAddress().join();
+//     }
+
+}