View Javadoc

1   /***
2    *  Copyright 2003-2010 Terracotta, Inc.
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   */
16  
17  package net.sf.ehcache.constructs.nonstop.concurrency;
18  
19  import java.util.LinkedList;
20  
21  /***
22   * A class that maintains a thread local to keep track of any explicit locks acquired by the app thread
23   *
24   * @author Abhishek Sanoujam
25   *
26   */
27  public final class ExplicitLockingContextThreadLocal {
28  
29      private final ThreadLocal<ExplicitLockingContext> contextThreadLocal = new ThreadLocal<ExplicitLockingContext>() {
30          @Override
31          protected ExplicitLockingContextImpl initialValue() {
32              return new ExplicitLockingContextImpl();
33          }
34      };
35  
36      /***
37       * Public constructor
38       */
39      public ExplicitLockingContextThreadLocal() {
40          // private constructor
41      }
42  
43      /***
44       * Returns true if the thread has acquired any locks previously and not released yet
45       *
46       * @return true if the thread has acquired any locks previously and not released yet
47       */
48      public boolean areAnyExplicitLocksAcquired() {
49          return contextThreadLocal.get().areAnyExplicitLocksAcquired();
50      }
51  
52      /***
53       * Returns the thread local for the current thread
54       *
55       * @return the thread local for the current thread
56       */
57      public ExplicitLockingContext getCurrentThreadLockContext() {
58          return contextThreadLocal.get();
59      }
60  
61      /***
62       *
63       * This class doesn't need to be thread safe as there's 1-1 mapping between app thread and nonstop threads. And only one of the threads
64       * is using this class at a time.
65       *
66       */
67      private static class ExplicitLockingContextImpl implements ExplicitLockingContext {
68  
69          // volatile for visibility
70          private volatile boolean locksAcquired;
71          private final LinkedList<Long> lockAcquisitionStack = new LinkedList<Long>();
72  
73          /***
74           * {@inheritDoc}
75           */
76          public boolean areAnyExplicitLocksAcquired() {
77              return locksAcquired;
78          }
79  
80          /***
81           * {@inheritDoc}
82           */
83          public void lockAcquired(final long currentNonstopThreadUniqueId) {
84              locksAcquired = true;
85              lockAcquisitionStack.addFirst(Long.valueOf(currentNonstopThreadUniqueId));
86          }
87  
88          /***
89           * {@inheritDoc}
90           */
91          public void lockReleased() {
92              if (lockAcquisitionStack.peek() != null) {
93                  lockAcquisitionStack.removeFirst();
94              }
95              // a litte perf than doing size() > 0
96              if (lockAcquisitionStack.peek() == null) {
97                  locksAcquired = false;
98              }
99          }
100 
101         /***
102          * {@inheritDoc}
103          */
104         public boolean areLocksAcquiredByOtherThreads(long currentNonstopThreadUniqueId) {
105             for (Long nonstopThreadUniqueId : lockAcquisitionStack) {
106                 if (nonstopThreadUniqueId.longValue() != currentNonstopThreadUniqueId) {
107                     return true;
108                 }
109             }
110             return false;
111         }
112     }
113 }