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.lang.Action;
032import org.tquadrat.foundation.lang.AutoLock;
033import org.tquadrat.foundation.lang.Constraint;
034import org.tquadrat.foundation.lang.Operation;
035
036/**
037 *  The implementation of
038 *  {@link AutoLock}.
039 *
040 *  @extauthor Thomas Thrien - thomas.thrien@tquadrat.org
041 *  @version $Id: AutoLockImpl.java 1135 2024-05-28 21:32:48Z tquadrat $
042 *  @since 0.1.0
043 *
044 *  @see java.util.concurrent.locks.Lock
045 *
046 *  @UMLGraph.link
047 */
048@ClassVersion( sourceVersion = "$Id: AutoLockImpl.java 1135 2024-05-28 21:32:48Z tquadrat $" )
049@API( status = INTERNAL, since = "0.1.0" )
050public final class AutoLockImpl implements AutoLock
051{
052        /*------------*\
053    ====** Attributes **=======================================================
054        \*------------*/
055    /**
056     *  The wrapped lock.
057     */
058    private final Lock m_Lock;
059
060        /*--------------*\
061    ====** Constructors **=====================================================
062        \*--------------*/
063    /**
064     *  Creates a new {@code AutoLockImpl} instance.
065     *
066     *  @param  lock    The wrapped lock.
067     */
068    public AutoLockImpl( final Lock lock )
069    {
070        super();
071        m_Lock = requireNonNullArgument( lock, "lock" );
072    }   //  AutoLockImpl()
073
074    /**
075     *  Creates a new {@code AutoLockImpl} instance with an internal lock
076     *  object.
077     */
078    public AutoLockImpl() { this( new ReentrantLock() ); }
079
080        /*---------*\
081    ====** Methods **==========================================================
082        \*---------*/
083    /**
084     *  {@inheritDoc}
085     */
086    @SuppressWarnings( "ProhibitedExceptionCaught" )
087    @Override
088    public final void close()
089    {
090        try
091        {
092            m_Lock.unlock();
093        }
094        catch( final IllegalMonitorStateException ignored ) { /* Deliberately ignored */ }
095    }   //  close()
096
097    /**
098     *  {@inheritDoc}
099     */
100    @SuppressWarnings( "OverlyBroadCatchBlock" )
101    @Override
102    public final boolean evaluate( final Constraint constraint ) throws ExecutionFailedException
103    {
104        requireNonNullArgument( constraint, "condition" );
105        final boolean retValue;
106        try( final var ignore = lock() )
107        {
108            retValue = constraint.evaluate();
109        }
110        catch( final Throwable t )
111        {
112            throw new ExecutionFailedException( t );
113        }
114
115        //---* Done *----------------------------------------------------------
116        return retValue;
117    }   //  evaluate()
118
119    /**
120     * {@inheritDoc}
121     */
122    @SuppressWarnings( "OverlyBroadCatchBlock" )
123    @Override
124    public void execute( final Action action ) throws ExecutionFailedException
125    {
126        requireNonNullArgument( action, "action" );
127        try( final var ignore = lock() )
128        {
129            action.run();
130        }
131        catch( final Throwable t )
132        {
133            throw new ExecutionFailedException( t );
134        }
135    }   //  execute()
136
137    /**
138     * {@inheritDoc}
139     */
140    @SuppressWarnings( "OverlyBroadCatchBlock" )
141    @Override
142    public <R> Optional<R> execute( final Operation<? extends R> verification ) throws ExecutionFailedException
143    {
144        requireNonNullArgument( verification, "operation" );
145        final Optional<R> retValue;
146        try( final var ignore = lock() )
147        {
148            retValue = Optional.ofNullable( verification.get() );
149        }
150        catch( final Throwable t )
151        {
152            throw new ExecutionFailedException( t );
153        }
154
155        //---* Done *----------------------------------------------------------
156        return retValue;
157    }   //  execute()
158
159    /**
160     *  {@inheritDoc}
161     */
162    @Override
163    public final Lock getWrappedLockInstance() { return m_Lock; }
164
165    /**
166     *  {@inheritDoc}
167     */
168    @SuppressWarnings( "LockAcquiredButNotSafelyReleased" )
169    @Override
170    public final AutoLock lock()
171    {
172        m_Lock.lock();
173
174        //---* Done *----------------------------------------------------------
175        return this;
176    }   //  lock()
177
178    /**
179     *  {@inheritDoc}
180     */
181    @SuppressWarnings( "LockAcquiredButNotSafelyReleased" )
182    @Override
183    public final AutoLock lockInterruptibly() throws InterruptedException
184    {
185        m_Lock.lockInterruptibly();
186
187        //---* Done *----------------------------------------------------------
188        return this;
189    }   //  lockInterruptibly()
190
191    /**
192     *  {@inheritDoc}
193     */
194    @Override
195    public final Condition newCondition() { return m_Lock.newCondition(); }
196}
197//  class AutoLock
198
199/*
200 *  End of File
201 */