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 1151 2025-10-01 21:32:15Z 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 1151 2025-10-01 21:32:15Z 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 ignore = lock() )
109        {
110            retValue = constraint.evaluate();
111        }
112        catch( final Throwable t )
113        {
114            throw new ExecutionFailedException( t );
115        }
116
117        //---* Done *----------------------------------------------------------
118        return retValue;
119    }   //  evaluate()
120
121    /**
122     * {@inheritDoc}
123     */
124    @SuppressWarnings( "OverlyBroadCatchBlock" )
125    @Override
126    public void execute( final Action action ) throws ExecutionFailedException
127    {
128        requireNonNullArgument( action, "action" );
129        try( final var ignore = lock() )
130        {
131            action.run();
132        }
133        catch( final Throwable t )
134        {
135            throw new ExecutionFailedException( t );
136        }
137    }   //  execute()
138
139    /**
140     * {@inheritDoc}
141     */
142    @SuppressWarnings( "OverlyBroadCatchBlock" )
143    @Override
144    public <R> Optional<R> execute( final Operation<? extends R> verification ) throws ExecutionFailedException
145    {
146        requireNonNullArgument( verification, "operation" );
147        final Optional<R> retValue;
148        try( final var ignore = lock() )
149        {
150            retValue = Optional.ofNullable( verification.get() );
151        }
152        catch( final Throwable t )
153        {
154            throw new ExecutionFailedException( t );
155        }
156
157        //---* Done *----------------------------------------------------------
158        return retValue;
159    }   //  execute()
160
161    /**
162     *  {@inheritDoc}
163     */
164    @Override
165    public final Lock getWrappedLockInstance() { return m_Lock; }
166
167    /**
168     *  {@inheritDoc}
169     */
170    @SuppressWarnings( "LockAcquiredButNotSafelyReleased" )
171    @Override
172    public final AutoLock lock()
173    {
174        m_Lock.lock();
175
176        //---* Done *----------------------------------------------------------
177        return this;
178    }   //  lock()
179
180    /**
181     *  {@inheritDoc}
182     */
183    @SuppressWarnings( "LockAcquiredButNotSafelyReleased" )
184    @Override
185    public final AutoLock lockInterruptibly() throws InterruptedException
186    {
187        m_Lock.lockInterruptibly();
188
189        //---* Done *----------------------------------------------------------
190        return this;
191    }   //  lockInterruptibly()
192
193    /**
194     *  {@inheritDoc}
195     */
196    @Override
197    public final Condition newCondition() { return m_Lock.newCondition(); }
198}
199//  class AutoLock
200
201/*
202 *  End of File
203 */