001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
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,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.servicemix.common.locks.impl;
018    
019    import java.io.IOException;
020    import java.io.ObjectInputStream;
021    import java.io.Serializable;
022    import java.util.concurrent.TimeUnit;
023    import java.util.concurrent.locks.AbstractQueuedSynchronizer;
024    import java.util.concurrent.locks.Condition;
025    import java.util.concurrent.locks.Lock;
026    
027    /**
028     * @author lhein
029     */
030    public class SimpleLock implements Lock, Serializable {
031    
032        // Our internal helper class
033        private static class Sync extends AbstractQueuedSynchronizer {
034            // Report whether in locked state
035            protected boolean isHeldExclusively() {
036                return getState() == 1;
037            }
038    
039            // Acquire the lock if state is zero
040            public boolean tryAcquire(int acquires) {
041                assert acquires == 1; // Otherwise unused
042                return compareAndSetState(0, 1);
043            }
044    
045            // Release the lock by setting state to zero
046            protected boolean tryRelease(int releases) {
047                assert releases == 1; // Otherwise unused
048                if (getState() == 0) {
049                    throw new IllegalMonitorStateException();
050                }
051                setState(0);
052                return true;
053            }
054    
055            // Provide a Condition
056            Condition newCondition() {
057                return new ConditionObject();
058            }
059    
060            // Deserialize properly
061            private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
062                s.defaultReadObject();
063                setState(0); // reset to unlocked state
064            }
065        }
066    
067        // The sync object does all the hard work. We just forward to it.
068        private final Sync sync = new Sync();
069    
070        public void lock() {
071            sync.acquire(1);
072        }
073    
074        public boolean tryLock() {
075            return sync.tryAcquire(1);
076        }
077    
078        public void unlock() {
079            sync.release(1);
080        }
081    
082        public Condition newCondition() {
083            return sync.newCondition();
084        }
085    
086        public boolean isLocked() {
087            return sync.isHeldExclusively();
088        }
089    
090        public boolean hasQueuedThreads() {
091            return sync.hasQueuedThreads();
092        }
093    
094        public void lockInterruptibly() throws InterruptedException {
095            sync.acquireInterruptibly(1);
096        }
097    
098        public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
099            return sync.tryAcquireNanos(1, unit.toNanos(timeout));
100        }
101    
102    }