001/*
002 * ============================================================================
003 *  Copyright © 2002-2026 by Thomas Thrien.
004 *  All Rights Reserved.
005 * ============================================================================
006 *  Licensed to the public under the agreements of the GNU Lesser General Public
007 *  License, version 3.0 (the "License"). You may obtain a copy of the License at
008 *
009 *       http://www.gnu.org/licenses/lgpl.html
010 *
011 *  Unless required by applicable law or agreed to in writing, software
012 *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
013 *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
014 *  License for the specific language governing permissions and limitations
015 *  under the License.
016 */
017
018package org.tquadrat.foundation.lang;
019
020import static org.apiguardian.api.API.Status.STABLE;
021
022import java.util.Optional;
023import java.util.concurrent.locks.Lock;
024
025import org.apiguardian.api.API;
026import org.tquadrat.foundation.annotation.ClassVersion;
027import org.tquadrat.foundation.lang.AutoLock.ExecutionFailedException;
028import org.tquadrat.foundation.lang.internal.LockExecutorImpl;
029
030/**
031 *  <p>{@summary Allows to execute an operation with an obtained lock.}</p>
032 *  <p>Use this class like below:</p>
033 *  <div class="source-container"><pre>…
034 *  final var lock = new ReentrantLock();
035 *  final var executor = LockExecutor.of( lock );
036 *  …
037 *  executor.execute( () -> doSomething() );
038 *  …</pre></div>
039 *
040 *  @note   If your program is using {@code AutoLock}, you should use the
041 *      corresponding methods from there.
042 *
043 *  @version $Id: LockExecutor.java 1185 2026-04-06 10:26:47Z tquadrat $
044 *  @extauthor Thomas Thrien - thomas.thrien@tquadrat.org
045 *  @UMLGraph.link
046 *  @since 0.1.0
047 */
048@ClassVersion( sourceVersion = "$Id: LockExecutor.java 1185 2026-04-06 10:26:47Z tquadrat $" )
049@API( status = STABLE, since = "0.1.0" )
050public sealed interface LockExecutor
051    permits LockExecutorImpl
052{
053        /*---------*\
054    ====** Methods **==========================================================
055        \*---------*/
056    /**
057     *  Evaluates the given condition.
058     *
059     *  @param  constraint  The constraint.
060     *  @return The result of the evaluation of the condition.
061     *  @throws ExecutionFailedException    The evaluation failed for some
062     *      reason.
063     */
064    @SuppressWarnings( "BooleanMethodNameMustStartWithQuestion" )
065    public boolean evaluate( final Constraint constraint ) throws ExecutionFailedException;
066
067    /**
068     *  Executes the given action.
069     *
070     *  @param  action  The action.
071     *  @throws ExecutionFailedException    The action failed for some
072     *      reason.
073     *  @deprecated Use
074     *      {@link #perform(Action)}
075     *      instead; basically this method was renamed to avoid the unintended
076     *      use of
077     *      {@link #execute(Operation)}
078     *      when an
079     *      {@link Action}
080     *      should be used instead.
081     */
082    @Deprecated( since = "0.25.3", forRemoval = true )
083    public default void execute( final Action action ) throws ExecutionFailedException
084    {
085        perform( action );
086    }   //  execute()
087
088    /**
089     *  Executes the given operation.
090     *
091     *  @param  <R> The type of the operation's result.
092     *  @param  operation   The operation.
093     *  @return An instance of
094     *      {@link Optional}
095     *      that holds the result of the operation.
096     *  @throws ExecutionFailedException    The operation failed for some
097     *      reason.
098     */
099    public <R> Optional<R> execute( final Operation<R> operation ) throws ExecutionFailedException;
100
101    /**
102     *  Creates a new {@code LockExecutor} from the given
103     *  {@link Lock}
104     *  instance.
105     *
106     *  @param  lock    The lock.
107     *  @return The new {@code LockExecutor}.
108     */
109    @API( status = STABLE, since = "0.1.0" )
110    public static LockExecutor of( final Lock lock )
111    {
112        final var retValue = LockExecutorImpl.of( lock );
113
114        //---* Done *----------------------------------------------------------
115        return retValue;
116    }   //  of()
117
118    /**
119     *  Creates a new {@code LockExecutor} from the given
120     *  {@link AutoLock}
121     *  instance.
122     *
123     *  @param  lock    The lock.
124     *  @return The new {@code LockExecutor}.
125     */
126    @API( status = STABLE, since = "0.1.0" )
127    public static LockExecutor of( final AutoLock lock )
128    {
129        final var retValue = LockExecutorImpl.of( lock );
130
131        //---* Done *----------------------------------------------------------
132        return retValue;
133    }   //  of()
134
135    /**
136     *  <p>{@summary Performs the given action after obtaining the lock.}</p>
137     *  <p>This differs from
138     *  {@link #execute(Operation)}
139     *  as
140     *  {@link Action}
141     *  does not return something, and a warning regarding &quot;Result of
142     *  assignment expression used&quot; can be avoided in case the
143     *  {@code action} is used to set an attribute.</p>
144     *
145     *  @param  action  The action.
146     *  @throws ExecutionFailedException    The action failed for some reason.
147     */
148    public void perform( final Action action ) throws ExecutionFailedException;
149}
150//  interface LockExecutor
151
152/*
153 *  End of File
154 */