ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jdk8/java/util/concurrent/locks/ReentrantLock.java
Revision: 1.2
Committed: Sat Mar 26 18:46:01 2016 UTC (8 years, 2 months ago) by jsr166
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +0 -5 lines
Log Message:
remove all references to jdk9ism @ReservedStackAccess

File Contents

# User Rev Content
1 jsr166 1.1 /*
2     * Written by Doug Lea with assistance from members of JCP JSR-166
3     * Expert Group and released to the public domain, as explained at
4     * http://creativecommons.org/publicdomain/zero/1.0/
5     */
6    
7     package java.util.concurrent.locks;
8    
9     import java.util.Collection;
10     import java.util.concurrent.TimeUnit;
11    
12     /**
13     * A reentrant mutual exclusion {@link Lock} with the same basic
14     * behavior and semantics as the implicit monitor lock accessed using
15     * {@code synchronized} methods and statements, but with extended
16     * capabilities.
17     *
18     * <p>A {@code ReentrantLock} is <em>owned</em> by the thread last
19     * successfully locking, but not yet unlocking it. A thread invoking
20     * {@code lock} will return, successfully acquiring the lock, when
21     * the lock is not owned by another thread. The method will return
22     * immediately if the current thread already owns the lock. This can
23     * be checked using methods {@link #isHeldByCurrentThread}, and {@link
24     * #getHoldCount}.
25     *
26     * <p>The constructor for this class accepts an optional
27     * <em>fairness</em> parameter. When set {@code true}, under
28     * contention, locks favor granting access to the longest-waiting
29     * thread. Otherwise this lock does not guarantee any particular
30     * access order. Programs using fair locks accessed by many threads
31     * may display lower overall throughput (i.e., are slower; often much
32     * slower) than those using the default setting, but have smaller
33     * variances in times to obtain locks and guarantee lack of
34     * starvation. Note however, that fairness of locks does not guarantee
35     * fairness of thread scheduling. Thus, one of many threads using a
36     * fair lock may obtain it multiple times in succession while other
37     * active threads are not progressing and not currently holding the
38     * lock.
39     * Also note that the untimed {@link #tryLock()} method does not
40     * honor the fairness setting. It will succeed if the lock
41     * is available even if other threads are waiting.
42     *
43     * <p>It is recommended practice to <em>always</em> immediately
44     * follow a call to {@code lock} with a {@code try} block, most
45     * typically in a before/after construction such as:
46     *
47     * <pre> {@code
48     * class X {
49     * private final ReentrantLock lock = new ReentrantLock();
50     * // ...
51     *
52     * public void m() {
53     * lock.lock(); // block until condition holds
54     * try {
55     * // ... method body
56     * } finally {
57     * lock.unlock()
58     * }
59     * }
60     * }}</pre>
61     *
62     * <p>In addition to implementing the {@link Lock} interface, this
63     * class defines a number of {@code public} and {@code protected}
64     * methods for inspecting the state of the lock. Some of these
65     * methods are only useful for instrumentation and monitoring.
66     *
67     * <p>Serialization of this class behaves in the same way as built-in
68     * locks: a deserialized lock is in the unlocked state, regardless of
69     * its state when serialized.
70     *
71     * <p>This lock supports a maximum of 2147483647 recursive locks by
72     * the same thread. Attempts to exceed this limit result in
73     * {@link Error} throws from locking methods.
74     *
75     * @since 1.5
76     * @author Doug Lea
77     */
78     public class ReentrantLock implements Lock, java.io.Serializable {
79     private static final long serialVersionUID = 7373984872572414699L;
80     /** Synchronizer providing all implementation mechanics */
81     private final Sync sync;
82    
83     /**
84     * Base of synchronization control for this lock. Subclassed
85     * into fair and nonfair versions below. Uses AQS state to
86     * represent the number of holds on the lock.
87     */
88     abstract static class Sync extends AbstractQueuedSynchronizer {
89     private static final long serialVersionUID = -5179523762034025860L;
90    
91     /**
92     * Performs {@link Lock#lock}. The main reason for subclassing
93     * is to allow fast path for nonfair version.
94     */
95     abstract void lock();
96    
97     /**
98     * Performs non-fair tryLock. tryAcquire is implemented in
99     * subclasses, but both need nonfair try for trylock method.
100     */
101     final boolean nonfairTryAcquire(int acquires) {
102     final Thread current = Thread.currentThread();
103     int c = getState();
104     if (c == 0) {
105     if (compareAndSetState(0, acquires)) {
106     setExclusiveOwnerThread(current);
107     return true;
108     }
109     }
110     else if (current == getExclusiveOwnerThread()) {
111     int nextc = c + acquires;
112     if (nextc < 0) // overflow
113     throw new Error("Maximum lock count exceeded");
114     setState(nextc);
115     return true;
116     }
117     return false;
118     }
119    
120     protected final boolean tryRelease(int releases) {
121     int c = getState() - releases;
122     if (Thread.currentThread() != getExclusiveOwnerThread())
123     throw new IllegalMonitorStateException();
124     boolean free = false;
125     if (c == 0) {
126     free = true;
127     setExclusiveOwnerThread(null);
128     }
129     setState(c);
130     return free;
131     }
132    
133     protected final boolean isHeldExclusively() {
134     // While we must in general read state before owner,
135     // we don't need to do so to check if current thread is owner
136     return getExclusiveOwnerThread() == Thread.currentThread();
137     }
138    
139     final ConditionObject newCondition() {
140     return new ConditionObject();
141     }
142    
143     // Methods relayed from outer class
144    
145     final Thread getOwner() {
146     return getState() == 0 ? null : getExclusiveOwnerThread();
147     }
148    
149     final int getHoldCount() {
150     return isHeldExclusively() ? getState() : 0;
151     }
152    
153     final boolean isLocked() {
154     return getState() != 0;
155     }
156    
157     /**
158     * Reconstitutes the instance from a stream (that is, deserializes it).
159     */
160     private void readObject(java.io.ObjectInputStream s)
161     throws java.io.IOException, ClassNotFoundException {
162     s.defaultReadObject();
163     setState(0); // reset to unlocked state
164     }
165     }
166    
167     /**
168     * Sync object for non-fair locks
169     */
170     static final class NonfairSync extends Sync {
171     private static final long serialVersionUID = 7316153563782823691L;
172    
173     /**
174     * Performs lock. Try immediate barge, backing up to normal
175     * acquire on failure.
176     */
177     final void lock() {
178     if (compareAndSetState(0, 1))
179     setExclusiveOwnerThread(Thread.currentThread());
180     else
181     acquire(1);
182     }
183    
184     protected final boolean tryAcquire(int acquires) {
185     return nonfairTryAcquire(acquires);
186     }
187     }
188    
189     /**
190     * Sync object for fair locks
191     */
192     static final class FairSync extends Sync {
193     private static final long serialVersionUID = -3000897897090466540L;
194    
195     final void lock() {
196     acquire(1);
197     }
198    
199     /**
200     * Fair version of tryAcquire. Don't grant access unless
201     * recursive call or no waiters or is first.
202     */
203     protected final boolean tryAcquire(int acquires) {
204     final Thread current = Thread.currentThread();
205     int c = getState();
206     if (c == 0) {
207     if (!hasQueuedPredecessors() &&
208     compareAndSetState(0, acquires)) {
209     setExclusiveOwnerThread(current);
210     return true;
211     }
212     }
213     else if (current == getExclusiveOwnerThread()) {
214     int nextc = c + acquires;
215     if (nextc < 0)
216     throw new Error("Maximum lock count exceeded");
217     setState(nextc);
218     return true;
219     }
220     return false;
221     }
222     }
223    
224     /**
225     * Creates an instance of {@code ReentrantLock}.
226     * This is equivalent to using {@code ReentrantLock(false)}.
227     */
228     public ReentrantLock() {
229     sync = new NonfairSync();
230     }
231    
232     /**
233     * Creates an instance of {@code ReentrantLock} with the
234     * given fairness policy.
235     *
236     * @param fair {@code true} if this lock should use a fair ordering policy
237     */
238     public ReentrantLock(boolean fair) {
239     sync = fair ? new FairSync() : new NonfairSync();
240     }
241    
242     /**
243     * Acquires the lock.
244     *
245     * <p>Acquires the lock if it is not held by another thread and returns
246     * immediately, setting the lock hold count to one.
247     *
248     * <p>If the current thread already holds the lock then the hold
249     * count is incremented by one and the method returns immediately.
250     *
251     * <p>If the lock is held by another thread then the
252     * current thread becomes disabled for thread scheduling
253     * purposes and lies dormant until the lock has been acquired,
254     * at which time the lock hold count is set to one.
255     */
256     public void lock() {
257     sync.lock();
258     }
259    
260     /**
261     * Acquires the lock unless the current thread is
262     * {@linkplain Thread#interrupt interrupted}.
263     *
264     * <p>Acquires the lock if it is not held by another thread and returns
265     * immediately, setting the lock hold count to one.
266     *
267     * <p>If the current thread already holds this lock then the hold count
268     * is incremented by one and the method returns immediately.
269     *
270     * <p>If the lock is held by another thread then the
271     * current thread becomes disabled for thread scheduling
272     * purposes and lies dormant until one of two things happens:
273     *
274     * <ul>
275     *
276     * <li>The lock is acquired by the current thread; or
277     *
278     * <li>Some other thread {@linkplain Thread#interrupt interrupts} the
279     * current thread.
280     *
281     * </ul>
282     *
283     * <p>If the lock is acquired by the current thread then the lock hold
284     * count is set to one.
285     *
286     * <p>If the current thread:
287     *
288     * <ul>
289     *
290     * <li>has its interrupted status set on entry to this method; or
291     *
292     * <li>is {@linkplain Thread#interrupt interrupted} while acquiring
293     * the lock,
294     *
295     * </ul>
296     *
297     * then {@link InterruptedException} is thrown and the current thread's
298     * interrupted status is cleared.
299     *
300     * <p>In this implementation, as this method is an explicit
301     * interruption point, preference is given to responding to the
302     * interrupt over normal or reentrant acquisition of the lock.
303     *
304     * @throws InterruptedException if the current thread is interrupted
305     */
306     public void lockInterruptibly() throws InterruptedException {
307     sync.acquireInterruptibly(1);
308     }
309    
310     /**
311     * Acquires the lock only if it is not held by another thread at the time
312     * of invocation.
313     *
314     * <p>Acquires the lock if it is not held by another thread and
315     * returns immediately with the value {@code true}, setting the
316     * lock hold count to one. Even when this lock has been set to use a
317     * fair ordering policy, a call to {@code tryLock()} <em>will</em>
318     * immediately acquire the lock if it is available, whether or not
319     * other threads are currently waiting for the lock.
320     * This &quot;barging&quot; behavior can be useful in certain
321     * circumstances, even though it breaks fairness. If you want to honor
322     * the fairness setting for this lock, then use
323     * {@link #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) }
324     * which is almost equivalent (it also detects interruption).
325     *
326     * <p>If the current thread already holds this lock then the hold
327     * count is incremented by one and the method returns {@code true}.
328     *
329     * <p>If the lock is held by another thread then this method will return
330     * immediately with the value {@code false}.
331     *
332     * @return {@code true} if the lock was free and was acquired by the
333     * current thread, or the lock was already held by the current
334     * thread; and {@code false} otherwise
335     */
336     public boolean tryLock() {
337     return sync.nonfairTryAcquire(1);
338     }
339    
340     /**
341     * Acquires the lock if it is not held by another thread within the given
342     * waiting time and the current thread has not been
343     * {@linkplain Thread#interrupt interrupted}.
344     *
345     * <p>Acquires the lock if it is not held by another thread and returns
346     * immediately with the value {@code true}, setting the lock hold count
347     * to one. If this lock has been set to use a fair ordering policy then
348     * an available lock <em>will not</em> be acquired if any other threads
349     * are waiting for the lock. This is in contrast to the {@link #tryLock()}
350     * method. If you want a timed {@code tryLock} that does permit barging on
351     * a fair lock then combine the timed and un-timed forms together:
352     *
353     * <pre> {@code
354     * if (lock.tryLock() ||
355     * lock.tryLock(timeout, unit)) {
356     * ...
357     * }}</pre>
358     *
359     * <p>If the current thread
360     * already holds this lock then the hold count is incremented by one and
361     * the method returns {@code true}.
362     *
363     * <p>If the lock is held by another thread then the
364     * current thread becomes disabled for thread scheduling
365     * purposes and lies dormant until one of three things happens:
366     *
367     * <ul>
368     *
369     * <li>The lock is acquired by the current thread; or
370     *
371     * <li>Some other thread {@linkplain Thread#interrupt interrupts}
372     * the current thread; or
373     *
374     * <li>The specified waiting time elapses
375     *
376     * </ul>
377     *
378     * <p>If the lock is acquired then the value {@code true} is returned and
379     * the lock hold count is set to one.
380     *
381     * <p>If the current thread:
382     *
383     * <ul>
384     *
385     * <li>has its interrupted status set on entry to this method; or
386     *
387     * <li>is {@linkplain Thread#interrupt interrupted} while
388     * acquiring the lock,
389     *
390     * </ul>
391     * then {@link InterruptedException} is thrown and the current thread's
392     * interrupted status is cleared.
393     *
394     * <p>If the specified waiting time elapses then the value {@code false}
395     * is returned. If the time is less than or equal to zero, the method
396     * will not wait at all.
397     *
398     * <p>In this implementation, as this method is an explicit
399     * interruption point, preference is given to responding to the
400     * interrupt over normal or reentrant acquisition of the lock, and
401     * over reporting the elapse of the waiting time.
402     *
403     * @param timeout the time to wait for the lock
404     * @param unit the time unit of the timeout argument
405     * @return {@code true} if the lock was free and was acquired by the
406     * current thread, or the lock was already held by the current
407     * thread; and {@code false} if the waiting time elapsed before
408     * the lock could be acquired
409     * @throws InterruptedException if the current thread is interrupted
410     * @throws NullPointerException if the time unit is null
411     */
412     public boolean tryLock(long timeout, TimeUnit unit)
413     throws InterruptedException {
414     return sync.tryAcquireNanos(1, unit.toNanos(timeout));
415     }
416    
417     /**
418     * Attempts to release this lock.
419     *
420     * <p>If the current thread is the holder of this lock then the hold
421     * count is decremented. If the hold count is now zero then the lock
422     * is released. If the current thread is not the holder of this
423     * lock then {@link IllegalMonitorStateException} is thrown.
424     *
425     * @throws IllegalMonitorStateException if the current thread does not
426     * hold this lock
427     */
428     public void unlock() {
429     sync.release(1);
430     }
431    
432     /**
433     * Returns a {@link Condition} instance for use with this
434     * {@link Lock} instance.
435     *
436     * <p>The returned {@link Condition} instance supports the same
437     * usages as do the {@link Object} monitor methods ({@link
438     * Object#wait() wait}, {@link Object#notify notify}, and {@link
439     * Object#notifyAll notifyAll}) when used with the built-in
440     * monitor lock.
441     *
442     * <ul>
443     *
444     * <li>If this lock is not held when any of the {@link Condition}
445     * {@linkplain Condition#await() waiting} or {@linkplain
446     * Condition#signal signalling} methods are called, then an {@link
447     * IllegalMonitorStateException} is thrown.
448     *
449     * <li>When the condition {@linkplain Condition#await() waiting}
450     * methods are called the lock is released and, before they
451     * return, the lock is reacquired and the lock hold count restored
452     * to what it was when the method was called.
453     *
454     * <li>If a thread is {@linkplain Thread#interrupt interrupted}
455     * while waiting then the wait will terminate, an {@link
456     * InterruptedException} will be thrown, and the thread's
457     * interrupted status will be cleared.
458     *
459     * <li>Waiting threads are signalled in FIFO order.
460     *
461     * <li>The ordering of lock reacquisition for threads returning
462     * from waiting methods is the same as for threads initially
463     * acquiring the lock, which is in the default case not specified,
464     * but for <em>fair</em> locks favors those threads that have been
465     * waiting the longest.
466     *
467     * </ul>
468     *
469     * @return the Condition object
470     */
471     public Condition newCondition() {
472     return sync.newCondition();
473     }
474    
475     /**
476     * Queries the number of holds on this lock by the current thread.
477     *
478     * <p>A thread has a hold on a lock for each lock action that is not
479     * matched by an unlock action.
480     *
481     * <p>The hold count information is typically only used for testing and
482     * debugging purposes. For example, if a certain section of code should
483     * not be entered with the lock already held then we can assert that
484     * fact:
485     *
486     * <pre> {@code
487     * class X {
488     * ReentrantLock lock = new ReentrantLock();
489     * // ...
490     * public void m() {
491     * assert lock.getHoldCount() == 0;
492     * lock.lock();
493     * try {
494     * // ... method body
495     * } finally {
496     * lock.unlock();
497     * }
498     * }
499     * }}</pre>
500     *
501     * @return the number of holds on this lock by the current thread,
502     * or zero if this lock is not held by the current thread
503     */
504     public int getHoldCount() {
505     return sync.getHoldCount();
506     }
507    
508     /**
509     * Queries if this lock is held by the current thread.
510     *
511     * <p>Analogous to the {@link Thread#holdsLock(Object)} method for
512     * built-in monitor locks, this method is typically used for
513     * debugging and testing. For example, a method that should only be
514     * called while a lock is held can assert that this is the case:
515     *
516     * <pre> {@code
517     * class X {
518     * ReentrantLock lock = new ReentrantLock();
519     * // ...
520     *
521     * public void m() {
522     * assert lock.isHeldByCurrentThread();
523     * // ... method body
524     * }
525     * }}</pre>
526     *
527     * <p>It can also be used to ensure that a reentrant lock is used
528     * in a non-reentrant manner, for example:
529     *
530     * <pre> {@code
531     * class X {
532     * ReentrantLock lock = new ReentrantLock();
533     * // ...
534     *
535     * public void m() {
536     * assert !lock.isHeldByCurrentThread();
537     * lock.lock();
538     * try {
539     * // ... method body
540     * } finally {
541     * lock.unlock();
542     * }
543     * }
544     * }}</pre>
545     *
546     * @return {@code true} if current thread holds this lock and
547     * {@code false} otherwise
548     */
549     public boolean isHeldByCurrentThread() {
550     return sync.isHeldExclusively();
551     }
552    
553     /**
554     * Queries if this lock is held by any thread. This method is
555     * designed for use in monitoring of the system state,
556     * not for synchronization control.
557     *
558     * @return {@code true} if any thread holds this lock and
559     * {@code false} otherwise
560     */
561     public boolean isLocked() {
562     return sync.isLocked();
563     }
564    
565     /**
566     * Returns {@code true} if this lock has fairness set true.
567     *
568     * @return {@code true} if this lock has fairness set true
569     */
570     public final boolean isFair() {
571     return sync instanceof FairSync;
572     }
573    
574     /**
575     * Returns the thread that currently owns this lock, or
576     * {@code null} if not owned. When this method is called by a
577     * thread that is not the owner, the return value reflects a
578     * best-effort approximation of current lock status. For example,
579     * the owner may be momentarily {@code null} even if there are
580     * threads trying to acquire the lock but have not yet done so.
581     * This method is designed to facilitate construction of
582     * subclasses that provide more extensive lock monitoring
583     * facilities.
584     *
585     * @return the owner, or {@code null} if not owned
586     */
587     protected Thread getOwner() {
588     return sync.getOwner();
589     }
590    
591     /**
592     * Queries whether any threads are waiting to acquire this lock. Note that
593     * because cancellations may occur at any time, a {@code true}
594     * return does not guarantee that any other thread will ever
595     * acquire this lock. This method is designed primarily for use in
596     * monitoring of the system state.
597     *
598     * @return {@code true} if there may be other threads waiting to
599     * acquire the lock
600     */
601     public final boolean hasQueuedThreads() {
602     return sync.hasQueuedThreads();
603     }
604    
605     /**
606     * Queries whether the given thread is waiting to acquire this
607     * lock. Note that because cancellations may occur at any time, a
608     * {@code true} return does not guarantee that this thread
609     * will ever acquire this lock. This method is designed primarily for use
610     * in monitoring of the system state.
611     *
612     * @param thread the thread
613     * @return {@code true} if the given thread is queued waiting for this lock
614     * @throws NullPointerException if the thread is null
615     */
616     public final boolean hasQueuedThread(Thread thread) {
617     return sync.isQueued(thread);
618     }
619    
620     /**
621     * Returns an estimate of the number of threads waiting to acquire
622     * this lock. The value is only an estimate because the number of
623     * threads may change dynamically while this method traverses
624     * internal data structures. This method is designed for use in
625     * monitoring system state, not for synchronization control.
626     *
627     * @return the estimated number of threads waiting for this lock
628     */
629     public final int getQueueLength() {
630     return sync.getQueueLength();
631     }
632    
633     /**
634     * Returns a collection containing threads that may be waiting to
635     * acquire this lock. Because the actual set of threads may change
636     * dynamically while constructing this result, the returned
637     * collection is only a best-effort estimate. The elements of the
638     * returned collection are in no particular order. This method is
639     * designed to facilitate construction of subclasses that provide
640     * more extensive monitoring facilities.
641     *
642     * @return the collection of threads
643     */
644     protected Collection<Thread> getQueuedThreads() {
645     return sync.getQueuedThreads();
646     }
647    
648     /**
649     * Queries whether any threads are waiting on the given condition
650     * associated with this lock. Note that because timeouts and
651     * interrupts may occur at any time, a {@code true} return does
652     * not guarantee that a future {@code signal} will awaken any
653     * threads. This method is designed primarily for use in
654     * monitoring of the system state.
655     *
656     * @param condition the condition
657     * @return {@code true} if there are any waiting threads
658     * @throws IllegalMonitorStateException if this lock is not held
659     * @throws IllegalArgumentException if the given condition is
660     * not associated with this lock
661     * @throws NullPointerException if the condition is null
662     */
663     public boolean hasWaiters(Condition condition) {
664     if (condition == null)
665     throw new NullPointerException();
666     if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
667     throw new IllegalArgumentException("not owner");
668     return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);
669     }
670    
671     /**
672     * Returns an estimate of the number of threads waiting on the
673     * given condition associated with this lock. Note that because
674     * timeouts and interrupts may occur at any time, the estimate
675     * serves only as an upper bound on the actual number of waiters.
676     * This method is designed for use in monitoring of the system
677     * state, not for synchronization control.
678     *
679     * @param condition the condition
680     * @return the estimated number of waiting threads
681     * @throws IllegalMonitorStateException if this lock is not held
682     * @throws IllegalArgumentException if the given condition is
683     * not associated with this lock
684     * @throws NullPointerException if the condition is null
685     */
686     public int getWaitQueueLength(Condition condition) {
687     if (condition == null)
688     throw new NullPointerException();
689     if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
690     throw new IllegalArgumentException("not owner");
691     return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);
692     }
693    
694     /**
695     * Returns a collection containing those threads that may be
696     * waiting on the given condition associated with this lock.
697     * Because the actual set of threads may change dynamically while
698     * constructing this result, the returned collection is only a
699     * best-effort estimate. The elements of the returned collection
700     * are in no particular order. This method is designed to
701     * facilitate construction of subclasses that provide more
702     * extensive condition monitoring facilities.
703     *
704     * @param condition the condition
705     * @return the collection of threads
706     * @throws IllegalMonitorStateException if this lock is not held
707     * @throws IllegalArgumentException if the given condition is
708     * not associated with this lock
709     * @throws NullPointerException if the condition is null
710     */
711     protected Collection<Thread> getWaitingThreads(Condition condition) {
712     if (condition == null)
713     throw new NullPointerException();
714     if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
715     throw new IllegalArgumentException("not owner");
716     return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
717     }
718    
719     /**
720     * Returns a string identifying this lock, as well as its lock state.
721     * The state, in brackets, includes either the String {@code "Unlocked"}
722     * or the String {@code "Locked by"} followed by the
723     * {@linkplain Thread#getName name} of the owning thread.
724     *
725     * @return a string identifying this lock, as well as its lock state
726     */
727     public String toString() {
728     Thread o = sync.getOwner();
729     return super.toString() + ((o == null) ?
730     "[Unlocked]" :
731     "[Locked by thread " + o.getName() + "]");
732     }
733     }