Convert common.futures.SimpleSettableFuture (#45677)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/45677

Changelog:
[Internal] [Changed] - Convert com.facebook.react.common.futures.SimpleSettableFuture to Kotlin

Reviewed By: rshest

Differential Revision: D60237075

fbshipit-source-id: e8a94fa3bb5d09da85b13d86b55a020d42a770cd
This commit is contained in:
Thomas Nardone
2024-07-31 11:28:07 -07:00
committed by Facebook GitHub Bot
parent fbfb430b3b
commit 5812ee1969
3 changed files with 116 additions and 126 deletions
@@ -1923,17 +1923,17 @@ public class com/facebook/react/common/build/ReactBuildConfig {
public fun <init> ()V
}
public class com/facebook/react/common/futures/SimpleSettableFuture : java/util/concurrent/Future {
public final class com/facebook/react/common/futures/SimpleSettableFuture : java/util/concurrent/Future {
public fun <init> ()V
public fun cancel (Z)Z
public fun get ()Ljava/lang/Object;
public fun get (JLjava/util/concurrent/TimeUnit;)Ljava/lang/Object;
public fun getOrThrow ()Ljava/lang/Object;
public fun getOrThrow (JLjava/util/concurrent/TimeUnit;)Ljava/lang/Object;
public final fun getOrThrow ()Ljava/lang/Object;
public final fun getOrThrow (JLjava/util/concurrent/TimeUnit;)Ljava/lang/Object;
public fun isCancelled ()Z
public fun isDone ()Z
public fun set (Ljava/lang/Object;)V
public fun setException (Ljava/lang/Exception;)V
public final fun set (Ljava/lang/Object;)V
public final fun setException (Ljava/lang/Exception;)V
}
public abstract interface class com/facebook/react/common/mapbuffer/MapBuffer : java/lang/Iterable, kotlin/jvm/internal/markers/KMappedMarker {
@@ -1,121 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react.common.futures;
import androidx.annotation.Nullable;
import com.facebook.infer.annotation.Nullsafe;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* A super simple Future-like class that can safely notify another Thread when a value is ready.
* Does not support canceling.
*/
@Nullsafe(Nullsafe.Mode.LOCAL)
public class SimpleSettableFuture<T> implements Future<T> {
private final CountDownLatch mReadyLatch = new CountDownLatch(1);
private @Nullable T mResult;
private @Nullable Exception mException;
/**
* Sets the result. If another thread has called {@link #get}, they will immediately receive the
* value. set or setException must only be called once.
*/
public void set(@Nullable T result) {
checkNotSet();
mResult = result;
mReadyLatch.countDown();
}
/**
* Sets the exception. If another thread has called {@link #get}, they will immediately receive
* the exception. set or setException must only be called once.
*/
public void setException(Exception exception) {
checkNotSet();
mException = exception;
mReadyLatch.countDown();
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
throw new UnsupportedOperationException();
}
@Override
public boolean isCancelled() {
return false;
}
@Override
public boolean isDone() {
return mReadyLatch.getCount() == 0;
}
@Override
public @Nullable T get() throws InterruptedException, ExecutionException {
mReadyLatch.await();
if (mException != null) {
throw new ExecutionException(mException);
}
return mResult;
}
/**
* Wait up to the timeout time for another Thread to set a value on this future. If a value has
* already been set, this method will return immediately.
*
* <p>NB: For simplicity, we catch and wrap InterruptedException. Do NOT use this class if you are
* in the 1% of cases where you actually want to handle that.
*/
@Override
public @Nullable T get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
if (!mReadyLatch.await(timeout, unit)) {
throw new TimeoutException("Timed out waiting for result");
}
if (mException != null) {
throw new ExecutionException(mException);
}
return mResult;
}
/**
* Convenience wrapper for {@link #get()} that re-throws get()'s Exceptions as RuntimeExceptions.
*/
public @Nullable T getOrThrow() {
try {
return get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
/**
* Convenience wrapper for {@link #get(long, TimeUnit)} that re-throws get()'s Exceptions as
* RuntimeExceptions.
*/
public @Nullable T getOrThrow(long timeout, TimeUnit unit) {
try {
return get(timeout, unit);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
throw new RuntimeException(e);
}
}
private void checkNotSet() {
if (mReadyLatch.getCount() == 0) {
throw new RuntimeException("Result has already been set!");
}
}
}
@@ -0,0 +1,111 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react.common.futures
import java.util.concurrent.CountDownLatch
import java.util.concurrent.ExecutionException
import java.util.concurrent.Future
import java.util.concurrent.TimeUnit
import java.util.concurrent.TimeoutException
/**
* A super simple Future-like class that can safely notify another Thread when a value is ready.
* Does not support canceling.
*/
public class SimpleSettableFuture<T> : Future<T?> {
private val readyLatch = CountDownLatch(1)
private var result: T? = null
private var exception: Exception? = null
/**
* Sets the result. If another thread has called [get], they will immediately receive the value.
* set or setException must only be called once.
*/
public fun set(result: T?): Unit {
checkNotSet()
this.result = result
readyLatch.countDown()
}
/**
* Sets the exception. If another thread has called [get], they will immediately receive the
* exception. set or setException must only be called once.
*/
public fun setException(exception: Exception): Unit {
checkNotSet()
this.exception = exception
readyLatch.countDown()
}
override fun cancel(mayInterruptIfRunning: Boolean): Boolean {
throw UnsupportedOperationException()
}
override fun isCancelled(): Boolean = false
override fun isDone(): Boolean = readyLatch.count == 0L
@Throws(InterruptedException::class, ExecutionException::class)
override fun get(): T? {
readyLatch.await()
if (exception != null) {
throw ExecutionException(exception)
}
return result
}
/**
* Wait up to the timeout time for another Thread to set a value on this future. If a value has
* already been set, this method will return immediately.
*
* NB: For simplicity, we catch and wrap InterruptedException. Do NOT use this class if you are in
* the 1% of cases where you actually want to handle that.
*/
@Throws(InterruptedException::class, ExecutionException::class, TimeoutException::class)
override fun get(timeout: Long, unit: TimeUnit): T? {
if (!readyLatch.await(timeout, unit)) {
throw TimeoutException("Timed out waiting for result")
}
if (exception != null) {
throw ExecutionException(exception)
}
return result
}
/** Convenience wrapper for [get()] that re-throws get()'s Exceptions as RuntimeExceptions. */
public fun getOrThrow(): T? =
try {
get()
} catch (e: InterruptedException) {
throw RuntimeException(e)
} catch (e: ExecutionException) {
throw RuntimeException(e)
}
/**
* Convenience wrapper for [get(long, TimeUnit)] that re-throws get()'s Exceptions as
* RuntimeExceptions.
*/
public fun getOrThrow(timeout: Long, unit: TimeUnit): T? =
try {
get(timeout, unit)
} catch (e: InterruptedException) {
throw RuntimeException(e)
} catch (e: ExecutionException) {
throw RuntimeException(e)
} catch (e: TimeoutException) {
throw RuntimeException(e)
}
private fun checkNotSet() {
if (readyLatch.count == 0L) {
throw RuntimeException("Result has already been set!")
}
}
}