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 */