001/*
002 * ============================================================================
003 * Copyright © 2002-2020 by Thomas Thrien.
004 * All Rights Reserved.
005 * ============================================================================
006 *
007 * Licensed to the public under the agreements of the GNU Lesser General Public
008 * License, version 3.0 (the "License"). You may obtain a copy of the License at
009 *
010 *      http://www.gnu.org/licenses/lgpl.html
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
014 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
015 * License for the specific language governing permissions and limitations
016 * under the License.
017 */
018
019package org.tquadrat.foundation.lang.internal;
020
021import static org.apiguardian.api.API.Status.INTERNAL;
022import static org.tquadrat.foundation.lang.Objects.requireNonNullArgument;
023
024import java.util.Optional;
025import java.util.concurrent.locks.Condition;
026import java.util.concurrent.locks.Lock;
027import java.util.concurrent.locks.ReentrantLock;
028
029import org.apiguardian.api.API;
030import org.tquadrat.foundation.annotation.ClassVersion;
031import org.tquadrat.foundation.annotation.NotRecord;
032import org.tquadrat.foundation.lang.Action;
033import org.tquadrat.foundation.lang.AutoLock;
034import org.tquadrat.foundation.lang.Constraint;
035import org.tquadrat.foundation.lang.Operation;
036
037/**
038 *  The implementation of
039 *  {@link AutoLock}.
040 *
041 *  @extauthor Thomas Thrien - thomas.thrien@tquadrat.org
042 *  @version $Id: AutoLockImpl.java 1185 2026-04-06 10:26:47Z tquadrat $
043 *  @since 0.1.0
044 *
045 *  @see java.util.concurrent.locks.Lock
046 *
047 *  @UMLGraph.link
048 */
049@ClassVersion( sourceVersion = "$Id: AutoLockImpl.java 1185 2026-04-06 10:26:47Z tquadrat $" )
050@API( status = INTERNAL, since = "0.1.0" )
051@NotRecord
052public final class AutoLockImpl implements AutoLock
053{
054        /*------------*\
055    ====** Attributes **=======================================================
056        \*------------*/
057    /**
058     *  The wrapped lock.
059     */
060    private final Lock m_Lock;
061
062        /*--------------*\
063    ====** Constructors **=====================================================
064        \*--------------*/
065    /**
066     *  Creates a new {@code AutoLockImpl} instance.
067     *
068     *  @param  lock    The wrapped lock.
069     */
070    public AutoLockImpl( final Lock lock )
071    {
072        super();
073        m_Lock = requireNonNullArgument( lock, "lock" );
074    }   //  AutoLockImpl()
075
076    /**
077     *  Creates a new {@code AutoLockImpl} instance with an internal lock
078     *  object.
079     */
080    public AutoLockImpl() { this( new ReentrantLock() ); }
081
082        /*---------*\
083    ====** Methods **==========================================================
084        \*---------*/
085    /**
086     *  {@inheritDoc}
087     */
088    @SuppressWarnings( "ProhibitedExceptionCaught" )
089    @Override
090    public final void close()
091    {
092        try
093        {
094            m_Lock.unlock();
095        }
096        catch( final IllegalMonitorStateException ignored ) { /* Deliberately ignored */ }
097    }   //  close()
098
099    /**
100     *  {@inheritDoc}
101     */
102    @SuppressWarnings( "OverlyBroadCatchBlock" )
103    @Override
104    public final boolean evaluate( final Constraint constraint ) throws ExecutionFailedException
105    {
106        requireNonNullArgument( constraint, "condition" );
107        final boolean retValue;
108        try( final var _ = lock() )
109        {
110            retValue = constraint.evaluate();
111        }
112        /*
113         * Catching java.lang.Throwable is required here to wrap really all
114         * thrown exceptions into an ExecutionFailedException.
115         */
116        catch( final Throwable t )
117        {
118            throw new ExecutionFailedException( t );
119        }
120
121        //---* Done *----------------------------------------------------------
122        return retValue;
123    }   //  evaluate()
124
125    /**
126     * {@inheritDoc}
127     */
128    @SuppressWarnings( "OverlyBroadCatchBlock" )
129    @Override
130    public <R> Optional<R> execute( final Operation<? extends R> verification ) throws ExecutionFailedException
131    {
132        requireNonNullArgument( verification, "operation" );
133        final Optional<R> retValue;
134        try( final var _ = lock() )
135        {
136            retValue = Optional.ofNullable( verification.get() );
137        }
138        /*
139         * Catching java.lang.Throwable is required here to wrap really all
140         * thrown exceptions into an ExecutionFailedException.
141         */
142        catch( final Throwable t )
143        {
144            throw new ExecutionFailedException( t );
145        }
146
147        //---* Done *----------------------------------------------------------
148        return retValue;
149    }   //  execute()
150
151    /**
152     *  {@inheritDoc}
153     */
154    @Override
155    public final Lock getWrappedLockInstance() { return m_Lock; }
156
157    /**
158     *  {@inheritDoc}
159     */
160    @SuppressWarnings( "LockAcquiredButNotSafelyReleased" )
161    @Override
162    public final AutoLock lock()
163    {
164        m_Lock.lock();
165
166        //---* Done *----------------------------------------------------------
167        return this;
168    }   //  lock()
169
170    /**
171     *  {@inheritDoc}
172     */
173    @SuppressWarnings( "LockAcquiredButNotSafelyReleased" )
174    @Override
175    public final AutoLock lockInterruptibly() throws InterruptedException
176    {
177        m_Lock.lockInterruptibly();
178
179        //---* Done *----------------------------------------------------------
180        return this;
181    }   //  lockInterruptibly()
182
183    /**
184     *  {@inheritDoc}
185     */
186    @Override
187    public final Condition newCondition() { return m_Lock.newCondition(); }
188
189    /**
190     * {@inheritDoc}
191     */
192    @SuppressWarnings( "OverlyBroadCatchBlock" )
193    @Override
194    public void perform( final Action action ) throws ExecutionFailedException
195    {
196        requireNonNullArgument( action, "action" );
197        try( final var _ = lock() )
198        {
199            action.run();
200        }
201        /*
202         * Catching java.lang.Throwable is required here to wrap really all
203         * thrown exceptions into an ExecutionFailedException.
204         */
205        catch( final Throwable t )
206        {
207            throw new ExecutionFailedException( t );
208        }
209    }   //  perform()
210}
211//  class AutoLock
212
213/*
214 *  End of File
215 */