Source Code Cross Referenced for ConcurrentBarrier.java in  » Library » Tapestry » org » apache » tapestry » ioc » internal » util » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Library » Tapestry » org.apache.tapestry.ioc.internal.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        // Copyright 2006, 2007 The Apache Software Foundation
002:        //
003:        // Licensed under the Apache License, Version 2.0 (the "License");
004:        // you may not use this file except in compliance with the License.
005:        // You may obtain a copy of the License at
006:        //
007:        //     http://www.apache.org/licenses/LICENSE-2.0
008:        //
009:        // Unless required by applicable law or agreed to in writing, software
010:        // distributed under the License is distributed on an "AS IS" BASIS,
011:        // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012:        // See the License for the specific language governing permissions and
013:        // limitations under the License.
014:
015:        package org.apache.tapestry.ioc.internal.util;
016:
017:        import java.util.concurrent.locks.ReadWriteLock;
018:        import java.util.concurrent.locks.ReentrantReadWriteLock;
019:        import java.util.concurrent.TimeUnit;
020:
021:        /**
022:         * A barrier used to execute code in a context where it is guarded by read/write locks. In addition,
023:         * handles upgrading read locks to write locks (and vice versa). Execution of code within a lock is
024:         * in terms of a {@link Runnable} object (that returns no value), or a {@link Invokable} object
025:         * (which does return a value).
026:         */
027:        public class ConcurrentBarrier {
028:            private final ReadWriteLock _lock = new ReentrantReadWriteLock();
029:
030:            /**
031:             * This is, of course, a bit of a problem. We don't have an avenue for ensuring that this
032:             * ThreadLocal is destroyed at the end of the request, and that means a thread can hold a
033:             * reference to the class and the class loader which loaded it. This may cause redeployment
034:             * problems (leaked classes and class loaders). Apparently JDK 1.6 provides the APIs to check to
035:             * see if the current thread has a read lock. So, we tend to remove the TL, rather than set its
036:             * value to false.
037:             */
038:            public static class ThreadBoolean extends ThreadLocal<Boolean> {
039:                @Override
040:                protected Boolean initialValue() {
041:                    return false;
042:                }
043:            }
044:
045:            private final ThreadBoolean _threadHasReadLock = new ThreadBoolean();
046:
047:            /**
048:             * Invokes the object after acquiring the read lock (if necessary). If invoked when the read
049:             * lock has not yet been acquired, then the lock is acquired for the duration of the call. If
050:             * the lock has already been acquired, then the status of the lock is not changed.
051:             * <p>
052:             * TODO: Check to see if the write lock is acquired and <em>not</em> acquire the read lock in
053:             * that situation. Currently this code is not re-entrant. If a write lock is already acquired
054:             * and the thread attempts to get the read lock, then the thread will hang. For the moment, all
055:             * the uses of ConcurrentBarrier are coded in such a way that reentrant locks are not a problem.
056:             * 
057:             * @param <T>
058:             * @param invokable
059:             * @return the result of invoking the invokable
060:             */
061:            public <T> T withRead(Invokable<T> invokable) {
062:                boolean readLockedAtEntry = _threadHasReadLock.get();
063:
064:                if (!readLockedAtEntry) {
065:                    _lock.readLock().lock();
066:
067:                    _threadHasReadLock.set(true);
068:                }
069:
070:                try {
071:                    return invokable.invoke();
072:                } finally {
073:                    if (!readLockedAtEntry) {
074:                        _lock.readLock().unlock();
075:
076:                        _threadHasReadLock.remove();
077:                    }
078:                }
079:            }
080:
081:            /**
082:             * As with {@link #withRead(Invokable)}, creating an {@link Invokable} wrapper around the
083:             * runnable object.
084:             */
085:            public void withRead(final Runnable runnable) {
086:                Invokable<Void> invokable = new Invokable<Void>() {
087:                    public Void invoke() {
088:                        runnable.run();
089:
090:                        return null;
091:                    }
092:                };
093:
094:                withRead(invokable);
095:            }
096:
097:            /**
098:             * Acquires the exclusive write lock before invoking the Invokable. The code will be executed
099:             * exclusively, no other reader or writer threads will exist (they will be blocked waiting for
100:             * the lock). If the current thread has a read lock, it is released before attempting to acquire
101:             * the write lock, and re-acquired after the write lock is released. Note that in that short
102:             * window, between releasing the read lock and acquiring the write lock, it is entirely possible
103:             * that some other thread will sneak in and do some work, so the {@link Invokable} object should
104:             * be prepared for cases where the state has changed slightly, despite holding the read lock.
105:             * This usually manifests as race conditions where either a) some parallel unrelated bit of work
106:             * has occured or b) duplicate work has occured. The latter is only problematic if the operation
107:             * is very expensive.
108:             * 
109:             * @param <T>
110:             * @param invokable
111:             */
112:            public <T> T withWrite(Invokable<T> invokable) {
113:                boolean readLockedAtEntry = releaseReadLock();
114:
115:                _lock.writeLock().lock();
116:
117:                try {
118:                    return invokable.invoke();
119:                } finally {
120:                    _lock.writeLock().unlock();
121:                    restoreReadLock(readLockedAtEntry);
122:                }
123:            }
124:
125:            private boolean releaseReadLock() {
126:                boolean readLockedAtEntry = _threadHasReadLock.get();
127:
128:                if (readLockedAtEntry) {
129:                    _lock.readLock().unlock();
130:
131:                    _threadHasReadLock.set(false);
132:                }
133:                return readLockedAtEntry;
134:            }
135:
136:            private void restoreReadLock(boolean readLockedAtEntry) {
137:                if (readLockedAtEntry) {
138:                    _lock.readLock().lock();
139:
140:                    _threadHasReadLock.set(true);
141:                } else {
142:                    _threadHasReadLock.remove();
143:                }
144:            }
145:
146:            /**
147:             * As with {@link #withWrite(Invokable)}, creating an {@link Invokable} wrapper around the
148:             * runnable object.
149:             */
150:            public void withWrite(final Runnable runnable) {
151:                Invokable<Void> invokable = new Invokable<Void>() {
152:                    public Void invoke() {
153:                        runnable.run();
154:
155:                        return null;
156:                    }
157:                };
158:
159:                withWrite(invokable);
160:            }
161:
162:            /**
163:             * Try to aquire the exclusive write lock and invoke the Runnable. If the write lock is obtained
164:             * within the specfied timeout, then this method behaves as {@link #withWrite(Runnable)} and
165:             * will return true. If the write lock is not obtained within the timeout then the runnable is
166:             * never invoked and the method will return false.
167:             * 
168:             * @param runnable
169:             *            Runnable object to execute inside the write lock.
170:             * @param timeout
171:             *            Time to wait for write lock.
172:             * @param timeoutUnit
173:             *            Units of timeout.
174:             * @return true if lock was obtained & runnabled executed. False otherwise.
175:             */
176:            public boolean tryWithWrite(final Runnable runnable, long timeout,
177:                    TimeUnit timeoutUnit) {
178:                boolean readLockedAtEntry = releaseReadLock();
179:
180:                boolean obtainedLock = false;
181:
182:                try {
183:                    try {
184:                        obtainedLock = _lock.writeLock().tryLock(timeout,
185:                                timeoutUnit);
186:
187:                        if (obtainedLock)
188:                            runnable.run();
189:
190:                    } catch (InterruptedException e) {
191:                        obtainedLock = false;
192:                    } finally {
193:                        if (obtainedLock)
194:                            _lock.writeLock().unlock();
195:                    }
196:                } finally {
197:                    restoreReadLock(readLockedAtEntry);
198:                }
199:
200:                return obtainedLock;
201:            }
202:
203:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.