View Javadoc

1   /*
2    Copyright (C) 2007 Grid Systems, S.A.
3   
4    This library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8   
9    This library is distributed in the hope that it will be useful,
10   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12   Lesser General Public License for more details.
13  
14   You should have received a copy of the GNU Lesser General Public
15   License along with this library; if not, write to the Free Software
16   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
17  */
18  package com.gridsystems.nextgrid.api.pom.ref;
19  
20  import java.util.Collections;
21  import java.util.HashSet;
22  import java.util.Set;
23  import java.util.concurrent.locks.Condition;
24  import java.util.concurrent.locks.Lock;
25  import java.util.concurrent.locks.ReadWriteLock;
26  import java.util.concurrent.locks.ReentrantLock;
27  import java.util.concurrent.locks.ReentrantReadWriteLock;
28  
29  import org.apache.commons.logging.Log;
30  import org.apache.commons.logging.LogFactory;
31  
32  import nextgrid.api.pom.Process;
33  import nextgrid.api.pom.Reference;
34  
35  /**
36   * ReferenceSupport type.
37   *
38   * @param <T> The referenced type
39   * @author Rodrigo Ruiz
40   */
41  public abstract class ReferenceSupport<T> implements Reference<T> {
42  
43    /**
44     * Serial Version UID.
45     */
46    private static final long serialVersionUID = 4543296708806798851L;
47  
48    /**
49     * Enactor logger.
50     */
51    protected static  final Log LOG = LogFactory.getLog("ENACTOR");
52  
53    /**
54     * The readers collection.
55     */
56    private Set<Process> readers;
57  
58    /**
59     * The writers collection.
60     */
61    private Set<Process> writers;
62  
63    /**
64     * Used for locking.
65     */
66    private ReadWriteLock rwLock = new ReentrantReadWriteLock(true);
67  
68    /**
69     * Used for availability synchronisation.
70     */
71    private Lock availLock = new ReentrantLock(true);
72  
73    /**
74     * Used for availability synchronisation.
75     */
76    private Condition cAvailable = availLock.newCondition();
77  
78    /**
79     * Available flag.
80     */
81    boolean available;
82  
83    /**
84     * Creates a new instance with default reader and writer collections.
85     *
86     */
87    public ReferenceSupport() {
88      this(new HashSet<Process>(), new HashSet<Process>());
89    }
90  
91    /**
92     * Creates a new instance, allowing to specify the readers and writers
93     * instances to use.
94     *
95     * @param readers A set to store reader processes
96     * @param writers A set to store writer processes
97     */
98    public ReferenceSupport(Set<Process> readers,
99      Set<Process> writers) {
100 
101     this.readers = readers;
102     this.writers = writers;
103   }
104 
105   /**
106    * {@inheritDoc}
107    */
108   public final void clearLinks() {
109     this.readers.clear();
110     this.writers.clear();
111   }
112 
113   /**
114    * {@inheritDoc}
115    */
116   public final void dispose() {
117   }
118 
119   /**
120    * {@inheritDoc}
121    */
122   public final void reset() {
123     this.setValue(null);
124     this.setAvailable(false);
125   }
126 
127   /**
128    * {@inheritDoc}
129    */
130   public final void addReader(Process reader) {
131     this.readers.add(reader);
132   }
133 
134   /**
135    * {@inheritDoc}
136    */
137   public final void addWriter(Process writer) {
138     this.writers.add(writer);
139   }
140 
141   /**
142    * {@inheritDoc}
143    */
144   public final Set<Process> getReaders() {
145     return Collections.unmodifiableSet(this.readers);
146   }
147 
148   /**
149    * {@inheritDoc}
150    */
151   public final Set<Process> getWriters() {
152     return Collections.unmodifiableSet(this.writers);
153   }
154 
155   /**
156    * {@inheritDoc}
157    */
158   public final void removeReader(Process reader) {
159     this.readers.remove(reader);
160   }
161 
162   /**
163    * {@inheritDoc}
164    */
165   public final void removeWriter(Process writer) {
166     this.writers.remove(writers);
167   }
168 
169   /**
170    * {@inheritDoc}
171    */
172   public Lock readLock() {
173     return rwLock.readLock();
174   }
175 
176   /**
177    * {@inheritDoc}
178    */
179   public Lock writeLock() {
180     return rwLock.writeLock();
181   }
182 
183   /**
184    * {@inheritDoc}
185    */
186   public boolean isAvailable() {
187     availLock.lock();
188     try {
189       return this.available;
190     } finally {
191       availLock.unlock();
192     }
193   }
194 
195   /**
196    * {@inheritDoc}
197    */
198   public void setAvailable(boolean available) {
199     availLock.lock();
200     try {
201       this.available = available;
202       if (available) {
203         LOG.debug("Signaling " + this);
204         cAvailable.signalAll();
205       }
206     } finally {
207       availLock.unlock();
208     }
209   }
210 
211   /**
212    * {@inheritDoc}
213    */
214   public void waitAvailable() throws InterruptedException {
215     availLock.lock();
216     try {
217       if (!this.isAvailable()) {
218         LOG.debug("Waiting for " + this);
219         cAvailable.await();
220       }
221     } finally {
222       availLock.unlock();
223     }
224   }
225 
226   /**
227    * {@inheritDoc}
228    */
229   @SuppressWarnings("unchecked")
230   public ReferenceSupport<T> copy() {
231     try {
232       ReferenceSupport<T> copy = (ReferenceSupport<T>)clone();
233 
234       copy.rwLock = new ReentrantReadWriteLock(true);
235       copy.availLock = new ReentrantLock(true);
236       copy.cAvailable = copy.availLock.newCondition();
237 
238       copy.readers = new HashSet<Process>(this.readers);
239       copy.writers = new HashSet<Process>(this.writers);
240 
241       return copy;
242     } catch (CloneNotSupportedException e) {
243       throw new InternalError("Unexpected CloneNotSupported exception");
244     }
245   }
246 }