001: /* ====================================================================
002: The Jicarilla Software License
003:
004: Copyright (c) 2003 Leo Simons.
005: All rights reserved.
006:
007: Permission is hereby granted, free of charge, to any person obtaining
008: a copy of this software and associated documentation files (the
009: "Software"), to deal in the Software without restriction, including
010: without limitation the rights to use, copy, modify, merge, publish,
011: distribute, sublicense, and/or sell copies of the Software, and to
012: permit persons to whom the Software is furnished to do so, subject to
013: the following conditions:
014:
015: The above copyright notice and this permission notice shall be
016: included in all copies or substantial portions of the Software.
017:
018: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
019: EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
020: MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
021: IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
022: CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
023: TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
024: SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
025: ==================================================================== */
026: package org.jicarilla.container;
027:
028: import org.jicarilla.lang.Assert;
029: import org.jicarilla.lang.Selector;
030:
031: /**
032: * <p>Utility methods that create thread safe wrappers around the core
033: * abstractions of this package. Uses synchronization on mutexes around method
034: * calls; the arguments provided to the various methods are not modified
035: * themselves. You should take care to ensure that no references to the
036: * unwrapped objects are kept because method calls on those objects might
037: * produce concurrency problems. For example, the followin should <em>not</em>
038: * be used:</p>
039: *
040: * <pre>
041: * Adapter adapter = new DefaultAdapter();
042: * Adapter synchronizedAdapter =
043: * SynchronizationUtil.synchronizedAdapter(adapter);
044: * doThings(adapter);
045: * doThingsInANewThread(synchronizedAdapter);
046: * </pre>
047: *
048: * <p>Rather, use a coding pattern like the following:</p>
049: *
050: * <pre>
051: * Adapter adapter =
052: * SynchronizationUtil.synchronizedAdapter( new DefaultAdapter() );
053: * </pre>
054: *
055: * @author <a href="lsimons at jicarilla dot org">Leo Simons</a>
056: * @version $Id: SynchronizationUtil.java,v 1.7 2004/03/23 13:37:51 lsimons Exp $
057: */
058: public class SynchronizationUtil {
059: /**
060: * Create a thread safe version of an {@link Adapter} by wrapping the
061: * provided instance.
062: *
063: * @param adapter the adapter to wrap.
064: * @return an adapter that is safe for concurrent use.
065: */
066: public static Adapter synchronizedAdapter(final Adapter adapter) {
067: return synchronizedAdapter(adapter, new Object());
068: }
069:
070: /**
071: * Create a thread safe version of an {@link Adapter} by wrapping the
072: * provided instance, and synchronizing on the provided mutex.
073: *
074: * @param adapter the adapter to wrap.
075: * @param mutex the object to synchronize on.
076: * @return an adapter that is safe for concurrent use.
077: */
078: protected static Adapter synchronizedAdapter(final Adapter adapter,
079: final Object mutex) {
080: return new SynchronizedComponentAdapter(adapter, mutex);
081: }
082:
083: /**
084: * Create a thread safe version of a {@link Container} by wrapping the
085: * provided instance.
086: *
087: * @param delegate the container to wrap.
088: * @return a container that is safe for concurrent use.
089: */
090: public static Container synchronizedContainer(
091: final Container delegate) {
092: return new SynchronizedContainer(delegate);
093: }
094:
095: /**
096: * Synchronizing wrapper around an <code>Adapter</code>.
097: */
098: protected static class SynchronizedComponentAdapter implements
099: Adapter {
100: protected final Adapter m_delegate;
101: protected final Object m_mutex;
102:
103: protected SynchronizedComponentAdapter(final Adapter delegate,
104: final Object mutex) {
105: Assert.assertNotNull("delegate argument may not be null",
106: delegate);
107: Assert.assertNotNull("mutex argument may not be null",
108: mutex);
109: m_delegate = delegate;
110: m_mutex = mutex;
111: }
112:
113: public synchronized Object getInstance() {
114: synchronized (m_mutex) {
115: return m_delegate.getInstance();
116: }
117: }
118:
119: public synchronized void releaseInstance(final Object component)
120: throws Exception {
121: synchronized (m_mutex) {
122: m_delegate.releaseInstance(component);
123: }
124: }
125: }
126:
127: /**
128: * Synchronizing wrapper around a <code>Container<code>. Performs "deep
129: * synchronization" by also synchronizing contained adapters and
130: * resolvers on a common mutex.
131: */
132: protected static class SynchronizedContainer implements Container {
133: protected final Container m_delegate;
134: protected final Resolver m_resolver;
135: protected final Object m_mutex = new Object();
136:
137: public SynchronizedContainer(final Container delegate) {
138: Assert.assertNotNull("delegate argument may not be null",
139: delegate);
140: m_delegate = delegate;
141: m_resolver = new SynchronizedResolver(m_delegate
142: .getResolver(), m_mutex);
143: }
144:
145: public Container registerAdapter(final Selector selector,
146: final Adapter adapter) {
147: synchronized (m_mutex) {
148: return m_delegate.registerAdapter(selector,
149: SynchronizationUtil.synchronizedAdapter(
150: adapter, m_mutex));
151: }
152: }
153:
154: public Container registerAdapter(final Object key,
155: final Adapter adapter) {
156: synchronized (m_mutex) {
157: return m_delegate.registerAdapter(key,
158: SynchronizationUtil.synchronizedAdapter(
159: adapter, m_mutex));
160: }
161: }
162:
163: public Resolver getResolver() {
164: return m_resolver;
165: }
166: }
167:
168: /**
169: * Synchronizing wrapper around a <code>Resolver</code>.
170: */
171: protected static class SynchronizedResolver implements Resolver {
172: protected final Resolver m_delegate;
173: protected final Object m_mutex;
174:
175: public SynchronizedResolver(final Resolver delegate,
176: final Object mutex) {
177: m_delegate = delegate;
178: m_mutex = mutex;
179: }
180:
181: public Object get(final Object key) {
182: synchronized (m_mutex) {
183: return m_delegate.get(key);
184: }
185: }
186:
187: public Object[] getAll(final Object key) {
188: synchronized (m_mutex) {
189: return m_delegate.getAll(key);
190: }
191: }
192:
193: public boolean contains(final Object key) {
194: synchronized (m_mutex) {
195: return m_delegate.contains(key);
196: }
197: }
198:
199: public void releaseInstance(final Object component)
200: throws Exception {
201: synchronized (m_mutex) {
202: m_delegate.releaseInstance(component);
203: }
204: }
205:
206: }
207: }
|