blob: 2b4e2495b41c74fd59a58f4dc3524853d9a89e85 [file] [log] [blame]
Felix Meschbergerefb2d082008-08-19 13:18:47 +00001/*
Richard S. Hall59aef192009-04-25 14:50:37 +00002 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
Felix Meschbergerefb2d082008-08-19 13:18:47 +000017package org.apache.felix.shell.remote;
18
Felix Meschbergerefb2d082008-08-19 13:18:47 +000019/**
20 * Implements a reentrant lock.
21 * <p/>
22 * Public domain code.
Felix Meschbergerefb2d082008-08-19 13:18:47 +000023 */
24class ReentrantLock
25{
Richard S. Hall59aef192009-04-25 14:50:37 +000026 protected Thread m_owner = null;
27 protected long m_holds = 0;
Felix Meschbergerefb2d082008-08-19 13:18:47 +000028
29 public void acquire() throws InterruptedException
30 {
31 //log.debug("acquire()::" + Thread.currentThread().toString());
Richard S. Hall59aef192009-04-25 14:50:37 +000032 if (Thread.interrupted())
Felix Meschbergerefb2d082008-08-19 13:18:47 +000033 {
Richard S. Hall59aef192009-04-25 14:50:37 +000034 throw new InterruptedException();
35 }
36 Thread caller = Thread.currentThread();
37 synchronized (this)
38 {
39 if (caller == m_owner)
40 {
41 ++m_holds;
42 }
Felix Meschbergerefb2d082008-08-19 13:18:47 +000043 else
44 {
45 try
46 {
Richard S. Hall59aef192009-04-25 14:50:37 +000047 while (m_owner != null)
48 {
Felix Meschbergerefb2d082008-08-19 13:18:47 +000049 wait();
Richard S. Hall59aef192009-04-25 14:50:37 +000050 }
51 m_owner = caller;
52 m_holds = 1;
Felix Meschbergerefb2d082008-08-19 13:18:47 +000053 }
Richard S. Hall59aef192009-04-25 14:50:37 +000054 catch (InterruptedException ex)
Felix Meschbergerefb2d082008-08-19 13:18:47 +000055 {
56 notify();
57 throw ex;
58 }
59 }
60 }
61 }//acquire
62
Richard S. Hall59aef192009-04-25 14:50:37 +000063 public boolean attempt(long msecs) throws InterruptedException
Felix Meschbergerefb2d082008-08-19 13:18:47 +000064 {
65 //log.debug("attempt()::" + Thread.currentThread().toString());
Richard S. Hall59aef192009-04-25 14:50:37 +000066 if (Thread.interrupted())
Felix Meschbergerefb2d082008-08-19 13:18:47 +000067 {
Richard S. Hall59aef192009-04-25 14:50:37 +000068 throw new InterruptedException();
69 }
70 Thread caller = Thread.currentThread();
71 synchronized (this)
72 {
73 if (caller == m_owner)
Felix Meschbergerefb2d082008-08-19 13:18:47 +000074 {
Richard S. Hall59aef192009-04-25 14:50:37 +000075 ++m_holds;
Felix Meschbergerefb2d082008-08-19 13:18:47 +000076 return true;
77 }
Richard S. Hall59aef192009-04-25 14:50:37 +000078 else if (m_owner == null)
Felix Meschbergerefb2d082008-08-19 13:18:47 +000079 {
Richard S. Hall59aef192009-04-25 14:50:37 +000080 m_owner = caller;
81 m_holds = 1;
Felix Meschbergerefb2d082008-08-19 13:18:47 +000082 return true;
83 }
Richard S. Hall59aef192009-04-25 14:50:37 +000084 else if (msecs <= 0)
85 {
Felix Meschbergerefb2d082008-08-19 13:18:47 +000086 return false;
Richard S. Hall59aef192009-04-25 14:50:37 +000087 }
Felix Meschbergerefb2d082008-08-19 13:18:47 +000088 else
89 {
90 long waitTime = msecs;
91 long start = System.currentTimeMillis();
92 try
93 {
Richard S. Hall59aef192009-04-25 14:50:37 +000094 for (;;)
Felix Meschbergerefb2d082008-08-19 13:18:47 +000095 {
Richard S. Hall59aef192009-04-25 14:50:37 +000096 wait(waitTime);
97 if (caller == m_owner)
Felix Meschbergerefb2d082008-08-19 13:18:47 +000098 {
Richard S. Hall59aef192009-04-25 14:50:37 +000099 ++m_holds;
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000100 return true;
101 }
Richard S. Hall59aef192009-04-25 14:50:37 +0000102 else if (m_owner == null)
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000103 {
Richard S. Hall59aef192009-04-25 14:50:37 +0000104 m_owner = caller;
105 m_holds = 1;
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000106 return true;
107 }
108 else
109 {
Richard S. Hall59aef192009-04-25 14:50:37 +0000110 waitTime = msecs - (System.currentTimeMillis() - start);
111 if (waitTime <= 0)
112 {
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000113 return false;
Richard S. Hall59aef192009-04-25 14:50:37 +0000114 }
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000115 }
116 }
117 }
Richard S. Hall59aef192009-04-25 14:50:37 +0000118 catch (InterruptedException ex)
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000119 {
120 notify();
121 throw ex;
122 }
123 }
124 }
125 }//attempt
126
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000127 /**
128 * Release the lock.
129 *
130 * @throws Error thrown if not current owner of lock
131 */
132 public synchronized void release()
133 {
134 //log.debug("release()::" + Thread.currentThread().toString());
Richard S. Hall59aef192009-04-25 14:50:37 +0000135 if (Thread.currentThread() != m_owner)
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000136 {
Richard S. Hall59aef192009-04-25 14:50:37 +0000137 throw new Error("Illegal Lock usage");
138 }
139
140 if (--m_holds == 0)
141 {
142 m_owner = null;
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000143 notify();
144 }
145 }//release
146
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000147 /**
148 * Release the lock N times. <code>release(n)</code> is
149 * equivalent in effect to:
150 * <pre>
151 * for (int i = 0; i < n; ++i) release();
152 * </pre>
153 * <p/>
154 *
155 * @param n times the lock should be released.
156 * @throws Error thrown if not current owner of lock
157 * or has fewer than N holds on the lock
158 */
Richard S. Hall59aef192009-04-25 14:50:37 +0000159 public synchronized void release(long n)
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000160 {
Richard S. Hall59aef192009-04-25 14:50:37 +0000161 if (Thread.currentThread() != m_owner || n > m_holds)
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000162 {
Richard S. Hall59aef192009-04-25 14:50:37 +0000163 throw new Error("Illegal Lock usage");
164 }
165
166 m_holds -= n;
167 if (m_holds == 0)
168 {
169 m_owner = null;
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000170 notify();
171 }
172 }//release
173
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000174 /**
175 * Return the number of unreleased acquires performed
176 * by the current thread.
177 * Returns zero if current thread does not hold lock.
178 *
179 * @return the number of unreleased acquires performed by the owner thread.
180 */
181 public synchronized long holds()
182 {
Richard S. Hall59aef192009-04-25 14:50:37 +0000183 if (Thread.currentThread() != m_owner)
184 {
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000185 return 0;
Richard S. Hall59aef192009-04-25 14:50:37 +0000186 }
187 return m_holds;
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000188 }//holds
Richard S. Hall59aef192009-04-25 14:50:37 +0000189}//class ReentrantLock