/*
* Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com
* The software in this package is published under the terms of the CPAL v1.0
* license, a copy of which has been included with this distribution in the
* LICENSE.txt file.
*/
package org.mule.runtime.core.util.func;
import static org.mule.runtime.core.util.ConcurrencyUtils.withLock;
import java.util.concurrent.locks.ReentrantLock;
/**
* Executes a given {@link CheckedRunnable} only once.
* <p>
* Once the {@link #runOnce()} method has been successfully executed, subsequent invokations to
* such method will have no effect. Notice that the key word here is {@code successfully}. If the method fails,
* each invokation to {@link #runOnce()} WILL run the delegate until it completes successfully.
* <p>
* Instances are thread safe, which means that if two threads are competing for the first successful invokation, only
* one will prevail and the other one will get a no-op execution.
*
* @since 4.0
*/
public class Once {
private final ReentrantLock lock = new ReentrantLock();
private CheckedRunnable runner;
private boolean done = false;
/**
* Creates a new instance
*
* @param runnable the delegate to be executed only once
* @return a new instance
*/
public static Once of(CheckedRunnable runnable) {
return new Once(runnable);
}
private Once(CheckedRunnable delegate) {
runner = () -> withLock(lock, () -> {
if (!done) {
delegate.run();
done = true;
runner = () -> {
};
}
});
}
/**
* Runs (or not) the delegate according to the behaviour described on the class javadoc
*/
public void runOnce() {
runner.run();
}
}