View Javadoc

1   /***
2    * 
3    * Copyright 2005 LogicBlaze, Inc. http://www.logicblaze.com
4    * 
5    * Licensed under the Apache License, Version 2.0 (the "License"); 
6    * you may not use this file except in compliance with the License. 
7    * 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   * 
17   **/
18  package org.logicblaze.lingo.util.locks;
19  
20  import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
21  import edu.emory.mathcs.backport.java.util.concurrent.locks.Lock;
22  import edu.emory.mathcs.backport.java.util.concurrent.locks.ReentrantLock;
23  
24  import java.util.LinkedList;
25  
26  /***
27   * A server side version of a {@link Condition} which is used by a
28   * {@link ConditionServer} to implement distributed conditions.
29   * 
30   * @version $Revision$
31   */
32  public class ConditionController {
33  
34      private String id;
35      private Lock lock;
36      private LinkedList listeners = new LinkedList();
37      private int signalCount;
38      private int signalAllCount;
39  
40      public ConditionController(String id, Lock lock) {
41          this.id = id;
42          this.lock = lock;
43      }
44  
45      /***
46       * Returns whether or not this condition is active so that it can be cleaned
47       * up in a pool.
48       * 
49       * @return true if this condition is active otherwise false indicating it
50       *         can be deleted.
51       */
52      public boolean isActive() {
53          if (signalCount == 0 && signalAllCount == 0) {
54              lock.lock();
55              try {
56                  return !listeners.isEmpty();
57              }
58              finally {
59                  lock.unlock();
60              }
61          }
62          return true;
63      }
64  
65      public void await(ConditionListener listener, long timeoutMillis) {
66          // TODO need to timeout stuff...
67          lock.lock();
68          try {
69              if (!pendingSignals(listener)) {
70                  listeners.add(listener);
71              }
72          }
73          finally {
74              lock.unlock();
75          }
76      }
77  
78      public void signal() {
79          lock.lock();
80          try {
81              if (listeners.isEmpty()) {
82                  // lets buffer up any missed notifies
83                  // in case we're failing over to a new server
84                  // instance and the signal() and await()
85                  // calls come in out of order
86                  signalCount++;
87              }
88              else {
89                  ConditionListener listener = (ConditionListener) listeners.remove();
90                  listener.onSignal(id);
91              }
92          }
93          finally {
94              lock.unlock();
95          }
96      }
97  
98      public void signalAll() {
99          lock.lock();
100         try {
101             if (listeners.isEmpty()) {
102                 // lets buffer up any missed notifies
103                 // in case we're failing over to a new server
104                 // instance and the signal() and await()
105                 // calls come in out of order
106                 signalAllCount++;
107             }
108             else {
109                 while (!listeners.isEmpty()) {
110                     ConditionListener listener = (ConditionListener) listeners.remove();
111                     listener.onSignalAll(id);
112                 }
113             }
114         }
115         finally {
116             lock.unlock();
117         }
118     }
119 
120     /***
121      * Purges any inactive listeners from the Map
122      */
123     public void purge() {
124         // TODO
125     }
126 
127     /***
128      * Returns true if there were pending signals
129      */
130     protected boolean pendingSignals(ConditionListener listener) {
131         boolean answer = true;
132         if (signalAllCount > 0) {
133             signalAllCount--;
134             listener.onSignalAll(id);
135         }
136         else if (signalCount > 0) {
137             signalCount--;
138             listener.onSignal(id);
139         }
140         else {
141             answer = false;
142         }
143         return answer;
144     }
145 }