<Swing Dev> [9] Review Request for 8030702: Deadlock between subclass of AbstractDocument and UndoManager
Alexander Scherbatiy
alexandr.scherbatiy at oracle.com
Tue Sep 15 15:16:11 UTC 2015
On 9/11/2015 7:24 PM, Semyon Sadetsky wrote:
>
>
> On 9/11/2015 6:04 PM, Alexander Scherbatiy wrote:
>> On 9/10/2015 7:30 PM, Semyon Sadetsky wrote:
>>>
>>>
>>> On 9/10/2015 6:46 PM, Alexander Scherbatiy wrote:
>>>> On 9/10/2015 6:26 PM, Semyon Sadetsky wrote:
>>>>>
>>>>>
>>>>> On 9/10/2015 5:13 PM, Alexander Scherbatiy wrote:
>>>>>> On 9/10/2015 5:07 PM, Semyon Sadetsky wrote:
>>>>>>>
>>>>>>>
>>>>>>> On 9/10/2015 3:45 PM, Alexander Scherbatiy wrote:
>>>>>>>> On 9/10/2015 3:39 PM, Semyon Sadetsky wrote:
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On 9/10/2015 2:44 PM, Alexander Scherbatiy wrote:
>>>>>>>>>> On 9/8/2015 6:11 PM, Semyon Sadetsky wrote:
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> On 9/8/2015 2:10 PM, Alexander Scherbatiy wrote:
>>>>>>>>>>>> On 9/8/2015 2:06 PM, Semyon Sadetsky wrote:
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> On 9/8/2015 1:07 PM, Alexander Scherbatiy wrote:
>>>>>>>>>>>>>> On 9/8/2015 12:48 PM, Semyon Sadetsky wrote:
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> On 9/8/2015 12:26 PM, Alexander Scherbatiy wrote:
>>>>>>>>>>>>>>>> On 9/8/2015 11:28 AM, Semyon Sadetsky wrote:
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> On 9/7/2015 5:56 PM, Alexander Scherbatiy wrote:
>>>>>>>>>>>>>>>>>> On 9/7/2015 5:08 PM, Semyon Sadetsky wrote:
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> On 9/7/2015 2:41 PM, Alexander Scherbatiy wrote:
>>>>>>>>>>>>>>>>>>>> On 9/4/2015 9:00 PM, Semyon Sadetsky wrote:
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>> On 9/4/2015 6:11 PM, Alexander Scherbatiy wrote:
>>>>>>>>>>>>>>>>>>>>>> On 9/3/2015 10:01 PM, Semyon Sadetsky wrote:
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> On 8/5/2015 4:50 PM, Semyon Sadetsky wrote:
>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>> On 8/5/2015 2:39 PM, Alexander Scherbatiy wrote:
>>>>>>>>>>>>>>>>>>>>>>>>> On 8/5/2015 2:00 PM, Semyon Sadetsky wrote:
>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>> On 8/5/2015 1:04 PM, Alexander Scherbatiy wrote:
>>>>>>>>>>>>>>>>>>>>>>>>>>> On 8/4/2015 8:13 PM, Semyon Sadetsky wrote:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>> On 8/4/2015 6:17 PM, Alexander Scherbatiy
>>>>>>>>>>>>>>>>>>>>>>>>>>>> wrote:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On 8/4/2015 3:13 PM, Semyon Sadetsky wrote:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On 8/4/2015 2:03 PM, Alexander Scherbatiy
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> wrote:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On 8/4/2015 12:32 PM, Semyon Sadetsky
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> wrote:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On 8/4/2015 11:47 AM, Alexander
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Scherbatiy wrote:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On 8/3/2015 4:19 PM, Semyon Sadetsky
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> wrote:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On 8/3/2015 3:12 PM, Alexander
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Scherbatiy wrote:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On 7/31/2015 9:44 AM, Semyon
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Sadetsky wrote:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Good question. But I did not add a
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> concrete class.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> The problem is that UndoManager
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> provided by JDK wants to be
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> serialized but undoable objects
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> knows nothing about that. The
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> contract between UndoManager and
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> undoable is UndoableEditListener
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> which only notifies UndoManager to
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> add a new edit. AbstractDocument
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> does not care about the specific
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> UndoManager implementation and it
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> can contain plenty different
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> UndoableEditListener. That is the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> current API approach.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> If our specific UndoManager wants
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> to be serialized it should also
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> take into account that the undoable
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> it controls may require
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> serialization. For that it needs
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> undoable's synchronization monitor
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> and AbstractDocument can provide it
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> using writeLock()/writeUnlock()
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> methods. I assumed that in the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> first turn UndoManger should work
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> well with JDK undoables than to
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> serve as a general implementation.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Also I tried to preserve the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> current API.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> And your suggestion is to change
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> the existing UndoableEditListener
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> API by introducing synchronization
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> methods in it. Am I correctly
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> understand you?
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> What I said is that UndoManager
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> can be used not only by
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> AbstractDocument but also in other
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> classes which can have the same
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> synchronization problems.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> There should be a way to solve
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> these problems without storing links
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> of external classes inside the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> UndoManager.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> As well as AbstractDocument can use
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> another undo managers. It can be
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> addressed to both parties. They need
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> each others locks to serialize
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> changes without deadlock.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> AbstarctDocument is related to
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> UndoableEditListener as one to many
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> that means a lock should be taken for
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> each undo manager before the document
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> change.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Undo manager does not have any
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> methods to get its lock because it is
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> an UndoableEditListener
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> implementation. AbstarctDocument has
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> API to receive its lock.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Do you still propose to fix the issue
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> on AbstractDocument side?
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Yes.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Could you clarify how do you see such
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> fix?
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Put an
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> UndoableEdit/UndoableEditEvent/necessary
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> information to a queue instead of
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> firing the undoable edit event under
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> the write lock. Do not read the queue
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> under the write lock. The queue allows
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> to preserve the order of
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> UndoableEdit's adding to an UndoManager.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Is not it the same as the previous
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> attempt to fix this issue (see 8030118 )?
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 8030118 fix does a strange thing
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> like firing InsertUpdate document event
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> out of the lock. Do not do that.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Document change event need to be fired
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> under write lock because the change to
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> the document should be atomic. Queue of
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> changes is undo manager's
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> responsibility not the document.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> And such queue in the AbstractDocument
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> would require complex coordination with
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> all its undo managers queues. What if
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> undo called on undo manager during the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> doc's queue processing? The right
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> undo/redo requests and edit events
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> order need to be preserved in this case
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> and it would be too complex or we would
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> have to change the concept and make
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> AbstractDocument to maintain its
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> undo/redo history internally instead of
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> external undo managers.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> It only needs to pass undoable edits
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> in the right order from abstract
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> document to the UndoManager.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Consider the scenario: UndoManager
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> executes undo/redo before it receives the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> undoable edits. As result it will undo
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> not the last edit but intermediate and it
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> will crash because the document state is
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> changed and intermediate the undoable
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> edit cannot be applied to the final
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> document state.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> This is a good point. But this does
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> not work neither with the current behavior
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> nor with your proposed fix.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Consider the following scenario:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -----------------------
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> document.insertString("AAA") // "AAA"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> UndoableEdit is added to the UndoManager
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> document.insertString("BBB")
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> writeLock();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> handleInsertString();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> // a user press undo, the "AAA"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> UndoableEdit is selected in UndoManager
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> but not executed, because of the write lock
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> fireUndoableEditUpdate("BBB") //
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> UndoManager is waiting for the "AAA"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> UndoableEdit execution
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> writeUnlock() // "AAA" UndoableEdit is
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> executed instead of "BBB"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> // "BBB" UndoableEdit is added to the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> UndoManager
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -----------------------
>>>>>>>>>>>>>>>>>>>>>>>>>>>> It will work after the fix. When undo()
>>>>>>>>>>>>>>>>>>>>>>>>>>>> method is called it will be blocked on the
>>>>>>>>>>>>>>>>>>>>>>>>>>>> document lock until the edit is done in
>>>>>>>>>>>>>>>>>>>>>>>>>>>> another thread. Then undo() will acquire
>>>>>>>>>>>>>>>>>>>>>>>>>>>> the document lock and call editToBeUndone()
>>>>>>>>>>>>>>>>>>>>>>>>>>>> method which will return the actual last
>>>>>>>>>>>>>>>>>>>>>>>>>>>> edit added with addEdit() during the
>>>>>>>>>>>>>>>>>>>>>>>>>>>> undoable callback execution.
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>> Is it possible to use the same undo
>>>>>>>>>>>>>>>>>>>>>>>>>>> manager with several abstract documents? If
>>>>>>>>>>>>>>>>>>>>>>>>>>> so, how are you going to map a document lock
>>>>>>>>>>>>>>>>>>>>>>>>>>> with the document undoable edit without
>>>>>>>>>>>>>>>>>>>>>>>>>>> querying it?
>>>>>>>>>>>>>>>>>>>>>>>>>> That scenario is possible. As well as several
>>>>>>>>>>>>>>>>>>>>>>>>>> undo managers can be assigned to the same
>>>>>>>>>>>>>>>>>>>>>>>>>> document. I think I can improve the fix in
>>>>>>>>>>>>>>>>>>>>>>>>>> that direction when you agree with the
>>>>>>>>>>>>>>>>>>>>>>>>>> general approach.
>>>>>>>>>>>>>>>>>>>>>>>>> It is interesting how it is possible to
>>>>>>>>>>>>>>>>>>>>>>>>> do that without querying an undoable edit.
>>>>>>>>>>>>>>>>>>>>>>>>> Your fix is relaying that an abstract document
>>>>>>>>>>>>>>>>>>>>>>>>> lock should precede the undo manager lock but
>>>>>>>>>>>>>>>>>>>>>>>>> to get the right abstract manager lock you
>>>>>>>>>>>>>>>>>>>>>>>>> need to take an undoable edit under the undo
>>>>>>>>>>>>>>>>>>>>>>>>> manager lock first.
>>>>>>>>>>>>>>>>>>>>>>>> We always have only two possible directions
>>>>>>>>>>>>>>>>>>>>>>>> forward and backward so it will require only 2
>>>>>>>>>>>>>>>>>>>>>>>> references.
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> Hi Alexander,
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> Please, take a look on the updated version which
>>>>>>>>>>>>>>>>>>>>>>> works for any number documents shared one undo
>>>>>>>>>>>>>>>>>>>>>>> manager.
>>>>>>>>>>>>>>>>>>>>>>> Also I removed the reference you did not like.
>>>>>>>>>>>>>>>>>>>>>>> This has some disadvantages but I think they are
>>>>>>>>>>>>>>>>>>>>>>> negligible.
>>>>>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ssadetsky/8030702/webrev.01/
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>> You code looks like:
>>>>>>>>>>>>>>>>>>>>>> ----------------------
>>>>>>>>>>>>>>>>>>>>>> public void undo() throws CannotUndoException {
>>>>>>>>>>>>>>>>>>>>>> synchronized (this) {
>>>>>>>>>>>>>>>>>>>>>> lockedDoc = getLockedDocument(edit);
>>>>>>>>>>>>>>>>>>>>>> }
>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>> // TP: 1
>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>> while (!done) {
>>>>>>>>>>>>>>>>>>>>>> lockedDoc.writeLock();
>>>>>>>>>>>>>>>>>>>>>> // ...
>>>>>>>>>>>>>>>>>>>>>> lockedDoc.writeUnlock();
>>>>>>>>>>>>>>>>>>>>>> }
>>>>>>>>>>>>>>>>>>>>>> }
>>>>>>>>>>>>>>>>>>>>>> ----------------------
>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>> Is it possible that on the line "TP: 1" a new
>>>>>>>>>>>>>>>>>>>>>> UndoableEdit will be added to the UndoManager so
>>>>>>>>>>>>>>>>>>>>>> the the lockedDoc will not point to the latest
>>>>>>>>>>>>>>>>>>>>>> UndoableEdit which is taken on the line 438.
>>>>>>>>>>>>>>>>>>>>> No. It is not possible because of
>>>>>>>>>>>>>>>>>>>>> 438 UndoableEdit edit = editToBeUndone();
>>>>>>>>>>>>>>>>>>>>> It always return the last significant edit so we
>>>>>>>>>>>>>>>>>>>>> preserve the consistency.
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> I see.
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> There is one more question about the
>>>>>>>>>>>>>>>>>>>> undoOrRedo() method there the synchronization is
>>>>>>>>>>>>>>>>>>>> removed.
>>>>>>>>>>>>>>>>>>>> Lets look at the sequences of calls to an
>>>>>>>>>>>>>>>>>>>> UndoManager:
>>>>>>>>>>>>>>>>>>>> addEdit(anEdit1), addEdit(anEdit2),
>>>>>>>>>>>>>>>>>>>> undoOrRedo(), undoOrRedo().
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> The result for two undoOrRedo() calls should
>>>>>>>>>>>>>>>>>>>> neutralize each other (it is just undo and redo
>>>>>>>>>>>>>>>>>>>> calls).
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> Is it possible that after the fix the the first
>>>>>>>>>>>>>>>>>>>> undoOrRedo() from one thread fails to do the redo
>>>>>>>>>>>>>>>>>>>> and before starting to do the undo
>>>>>>>>>>>>>>>>>>>> the second undoOrRedo() call from another thread
>>>>>>>>>>>>>>>>>>>> also fails to do a redo action?
>>>>>>>>>>>>>>>>>>>> In this cases two undo actions could be called
>>>>>>>>>>>>>>>>>>>> instead of undo and redo.
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> It does not make any sense to make atomic the
>>>>>>>>>>>>>>>>>>> convenience method undoOrRedo() because undo() and
>>>>>>>>>>>>>>>>>>> redo() are not atomic.
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> All UndoManager.undo()/redo()/undoOrRedo() have
>>>>>>>>>>>>>>>>>> synchronization.
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> For the sample described above two undoOrRedo()
>>>>>>>>>>>>>>>>>> calls always invoke undo() at first and redo() at the
>>>>>>>>>>>>>>>>>> second step.
>>>>>>>>>>>>>>>>>> After the fix it is possible that two undo()
>>>>>>>>>>>>>>>>>> methods can be called. It means that there will be a
>>>>>>>>>>>>>>>>>> regression in the undoOrRedo() method behavior after
>>>>>>>>>>>>>>>>>> the fix.
>>>>>>>>>>>>>>>>> The spec of the method to not promise any
>>>>>>>>>>>>>>>>> deterministic behavior for two consequent calls.
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> javadoc for UndoManager.undoOrRedo() method [1]:
>>>>>>>>>>>>>>>> "Convenience method that invokes one of undo or redo.
>>>>>>>>>>>>>>>> If any edits have been undone (the index of the next
>>>>>>>>>>>>>>>> edit is less than the length of the edits list) this
>>>>>>>>>>>>>>>> invokes redo, otherwise it invokes undo."
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> For the sequence of calls addEdit(anEdit1),
>>>>>>>>>>>>>>>> addEdit(anEdit2), undoOrRedo(), undoOrRedo():
>>>>>>>>>>>>>>>> Step 1: call undoOrRedo() - there are no undone edits,
>>>>>>>>>>>>>>>> the undo should be invoked.
>>>>>>>>>>>>>>>> Step 2: call undoOrRedo() - there is one undone edit,
>>>>>>>>>>>>>>>> the redo should be invoked.
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> [1]
>>>>>>>>>>>>>>>> http://docs.oracle.com/javase/8/docs/api/javax/swing/undo/UndoManager.html#undoOrRedo--
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> I think it is obvious that this never worked if
>>>>>>>>>>>>>>> addEdit() and undoOrRedo() are called from different
>>>>>>>>>>>>>>> threads without the external synchronization.
>>>>>>>>>>>>>>> The fix changes nothing here. It works fine in a single
>>>>>>>>>>>>>>> thread approach.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> The javadoc does not mention that it is not thread
>>>>>>>>>>>>>> safe to use the undoOrRedo() method from different treads.
>>>>>>>>>>>>>> You can get all permutations of the
>>>>>>>>>>>>>> "addEdit(anEdit1), addEdit(anEdit2), undoOrRedo(),
>>>>>>>>>>>>>> undoOrRedo()" calls and check the the fix does not break
>>>>>>>>>>>>>> cases which worked before the fix.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> A sequence of calls can be permuted in a single thread? How?
>>>>>>>>>>>>
>>>>>>>>>>>> Why are you asking about a single thread? The UndoManager
>>>>>>>>>>>> class is designed to work with multiple threads.
>>>>>>>>>>>>
>>>>>>>>>>>> You need to look at the all possible cases which can be
>>>>>>>>>>>> called by an application from different threads like:
>>>>>>>>>>>> - addEdit(anEdit1), addEdit(anEdit2), undoOrRedo(),
>>>>>>>>>>>> undoOrRedo()
>>>>>>>>>>>> - addEdit(anEdit1), undoOrRedo(), addEdit(anEdit2),
>>>>>>>>>>>> undoOrRedo()
>>>>>>>>>>>> - ...
>>>>>>>>>>>>
>>>>>>>>>>>> and check that there are no regressions in the behavior
>>>>>>>>>>>> after the fix.
>>>>>>>>>>> Are you kidding? This UndoManager sample has never worked in
>>>>>>>>>>> multithreading because of deadlock issue we are fixing.
>>>>>>>>>>> What the regression are you talking about?
>>>>>>>>>>
>>>>>>>>>> I am sorry. I do not understand your sense of humor.
>>>>>>>>>>
>>>>>>>>>> Do you mean that the deadlock happens every time when an
>>>>>>>>>> UndoEdiale is added to a UndoManager and undo() is called and
>>>>>>>>>> because of this the the UndoManager is totally unusable?
>>>>>>>>> In you suggestion you want to run addEdit(anEdit1),
>>>>>>>>> addEdit(anEdit2), undoOrRedo(), undoOrRedo() not in single
>>>>>>>>> thread but from different threads two times: before the fix
>>>>>>>>> and after it then to compare the results. But it is just
>>>>>>>>> impossible to get any valuable results from the run without
>>>>>>>>> the fix because it will crash with the deadlock. The deadlock
>>>>>>>>> we are trying to fix.
>>>>>>>>> Do you see why it is not possible or you need extra explanation?
>>>>>>>>
>>>>>>>> Even though something does not work before the fix the
>>>>>>>> UndoManager has been designed to work in the multi-tread
>>>>>>>> environment and the undoOrRedo() method should work in the
>>>>>>>> predicted way.
>>>>>>> The sample is related to singlethreaded usage of cause.
>>>>>>>>
>>>>>>>> If you think that it can't be fixed with this fix you can
>>>>>>>> file a new issue that it is a problem which we aware of.
>>>>>>> We discussed that already. The order is not deterministic
>>>>>>> without the external fair lock. And I think it is not needed for
>>>>>>> 99.(9)% of usages. Nobody cares if an undo button pressed 1 ms
>>>>>>> early or 1 ms later. It shouldn't be critical otherwise it is
>>>>>>> anti-pattern. If the background editing is allowed concurrently
>>>>>>> along the user interaction one need to use an external
>>>>>>> synchronization or simply disable undo/redo until the editing is
>>>>>>> done.
>>>>>>> For me it absolutely clear that it is a degenerated scenario
>>>>>>> when a UI document is modified concurrently from two different
>>>>>>> threads, but we should not allow deadlocks anyway and have to
>>>>>>> fix it.
>>>>>>>>
>>>>>>>> Thanks,
>>>>>>>> Alexandr.
>>>>>>>>
>>>>>>>>
>>>>>>>>>> Do you think that it is a good idea to remove a
>>>>>>>>>> synchronization from the undoOrRedo method because there is
>>>>>>>>>> the deadlock?
>>>>>>>>>> If so, may be you can just remove the synchronization
>>>>>>>>>> keyword form the undo() and redo() methods as well and the
>>>>>>>>>> deadlock just goes away?
>>>>>>>>>> No new interfaces, no locks from an abstract document. That
>>>>>>>>>> would be the simplest solution of the issue.
>>>>>>
>>>>>> Could you answer on the question why do you suggest so
>>>>>> complicated fix? Just remove the synchronization from the undo()
>>>>>> and redo() methods and you really fix the deadlock.
>>>>>> It seems that you believe that it is possible because: "If the
>>>>>> background editing is allowed concurrently along the user
>>>>>> interaction one need to use an external synchronization or simply
>>>>>> disable undo/redo until the editing is done."
>>>>> Strange suggestion. We cannot remove synchronization it is
>>>>> required to guarantee consistency.
>>>>
>>>> The same is for the undoOrRedo() method. You need to provide a
>>>> synchronization for it or create an new issue on it.
>>> undoOrRedo() just calls undo() or redo() which contain all necessary
>>> synchronization.
>>
>> UndoManager is designed as a general purpose class which can be
>> used from multi-thread environment even for applications which do not
>> use abstract documents.
>> Consider such application which creates its UndoableEdit events
>> where it does not use locks in undo() and redo() methods. This
>> application can use UndoManager.undo()/redo()/undoOrRedo() methods
>> from different threads without deadlock.
>> This application relies on the UndoManager.undoOrRedo()
>> description that the right action always will be called.
>> After the fix it may happen that two UndoManager.undoOrRedo()
>> calls can leads to two undo() calls instead of undo() and redo().
>> This is the regression from the previous behavior.
> I showed you already that the previous behavior was a deadlock for
> this scenario. No regression here.
The deadlock that you described exists only because AbstractDocument
uses locks in the UndoableEdit.undo()/redo() methods.
Applications that use UndoManager and do not use lock in the
UndoableEdit.undo()/redo() methods do not have deadlock. They worked
fine before the fix and can lost data consistency after the fix. This is
definitely the regression.
Thanks,
Alexandr.
>> Thanks,
>> Alexandr.
>>
>>>>
>>>> Thanks,
>>>> Alexandr.
>>>>> Also synchronization is needed to provide coherency with the state
>>>>> of the document. If those two are not provided the document can be
>>>>> corrupted. This is enough most usages.
>>>>>>
>>>>>> Thanks,
>>>>>> Alexandr.
>>>>>>
>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Thanks,
>>>>>>>>>> Alexandr.
>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> Thanks,
>>>>>>>>>>>> Alexandr.
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>>> Thanks,
>>>>>>>>>>>>>> Alexandr.
>>>>>>>>>>>>> It is
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>> I still think that updating the UndoableManager
>>>>>>>>>>>>>>>>>>>>>> for one particular AbstarctManager class can be
>>>>>>>>>>>>>>>>>>>>>> made only after investigation of other
>>>>>>>>>>>>>>>>>>>>>> possibilities.
>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>> You could start with choosing behavior which
>>>>>>>>>>>>>>>>>>>>>> you want to achieve or to keep, like:
>>>>>>>>>>>>>>>>>>>>>> - fix the deadlock
>>>>>>>>>>>>>>>>>>>>>> - atomic undo() method
>>>>>>>>>>>>>>>>>>>>>> - serialization
>>>>>>>>>>>>>>>>>>>>>> - immediate roll back action
>>>>>>>>>>>>>>>>>>>>>> - abstract document consistency after undo()
>>>>>>>>>>>>>>>>>>>>>> action
>>>>>>>>>>>>>>>>>>>>>> - ...
>>>>>>>>>>>>>>>>>>>>> We need to pay attention to the deadlock at first
>>>>>>>>>>>>>>>>>>>>> of cause.
>>>>>>>>>>>>>>>>>>>>> Serialization and consistency are achieved. Any
>>>>>>>>>>>>>>>>>>>>> concrete doubts?
>>>>>>>>>>>>>>>>>>>>> immediate roll back action -- ?what is that?
>>>>>>>>>>>>>>>>>>>> "if user starts a long edit operation and
>>>>>>>>>>>>>>>>>>>> press undo after that he expects when the long edit
>>>>>>>>>>>>>>>>>>>> is finished it will be rolled back immediately." -
>>>>>>>>>>>>>>>>>>>> what ever does it mean.
>>>>>>>>>>>>>>>>>>> Got it. It will work within the fairness. We have
>>>>>>>>>>>>>>>>>>> discussed this allready.
>>>>>>>>>>>>>>>>>>>>> I sacrificed undo/redo call atomicity because you
>>>>>>>>>>>>>>>>>>>>> did not like doc references in undo manager. I
>>>>>>>>>>>>>>>>>>>>> think it is not important for the most
>>>>>>>>>>>>>>>>>>>>> multithreaded undo/redo scenarios.
>>>>>>>>>>>>>>>>>>>> Could you give more details about it. Which doc
>>>>>>>>>>>>>>>>>>>> references do you mean?
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> Your statement a dozen iterations ago was: "There
>>>>>>>>>>>>>>>>>>> should be a way to solve these problems without
>>>>>>>>>>>>>>>>>>> storing links of external classes inside the
>>>>>>>>>>>>>>>>>>> UndoManager."
>>>>>>>>>>>>>>>>>>> I guess you used "link" term for references. I would
>>>>>>>>>>>>>>>>>>> recommend to use standard terminology: reference to
>>>>>>>>>>>>>>>>>>> the object, dependency on the class, etc... to avoid
>>>>>>>>>>>>>>>>>>> misunderstanding.
>>>>>>>>>>>>>>>>>>> Usually "link" is in a browser document or a tool
>>>>>>>>>>>>>>>>>>> that produces executables after compilation.
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>> and look which of the following approaches can
>>>>>>>>>>>>>>>>>>>>>> better solve them (where the fist is more
>>>>>>>>>>>>>>>>>>>>>> preferred and the last is less preferred case):
>>>>>>>>>>>>>>>>>>>>>> - using UndoManager as is without adding links
>>>>>>>>>>>>>>>>>>>>>> from some specific classes to it
>>>>>>>>>>>>>>>>>>>>>> - provide an API for UndoManager to work with
>>>>>>>>>>>>>>>>>>>>>> UndoableEdit-s which have synchronization for
>>>>>>>>>>>>>>>>>>>>>> undo/redo methods
>>>>>>>>>>>>>>>>>>>>>> - adding links of external classes directly to
>>>>>>>>>>>>>>>>>>>>>> UndoManager
>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>> What do you mean under link term? A reference or
>>>>>>>>>>>>>>>>>>>>> dependency?
>>>>>>>>>>>>>>>>>>>> There are two options. If UndoManager is a
>>>>>>>>>>>>>>>>>>>> class designed to be only used with the
>>>>>>>>>>>>>>>>>>>> AbstractDocument and placed in the javax.swing.text
>>>>>>>>>>>>>>>>>>>> package it definitly can have special code to
>>>>>>>>>>>>>>>>>>>> handle an abstract document instance in a special way.
>>>>>>>>>>>>>>>>>>>> If UndoManager is a general purpose class, it
>>>>>>>>>>>>>>>>>>>> looks strange that it handles some special classes
>>>>>>>>>>>>>>>>>>>> in different way as all others. It usually mean
>>>>>>>>>>>>>>>>>>>> that there are some design problems in this class.
>>>>>>>>>>>>>>>>>>>> That is why I just asked to look at other ways at
>>>>>>>>>>>>>>>>>>>> first. Only if other solutions are not suitable it
>>>>>>>>>>>>>>>>>>>> has sense to look at the way that you are provided.
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> Correct. I introduced extra dependency. It is
>>>>>>>>>>>>>>>>>>> optional, but anyway. Of cause there is a design
>>>>>>>>>>>>>>>>>>> problem in undo javax.swing.undo package. But I
>>>>>>>>>>>>>>>>>>> cannot rewrite the API because we will get a
>>>>>>>>>>>>>>>>>>> compatibility problem then. I mentioned this several
>>>>>>>>>>>>>>>>>>> times in this thread.
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>> We are constrained by compatibility requirements.
>>>>>>>>>>>>>>>>>>>>> UndoManager is a broadly used class we cannot
>>>>>>>>>>>>>>>>>>>>> change the API so drastically.
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> I think that you can generalize your solution
>>>>>>>>>>>>>>>>>>>> just adding an internal interface like
>>>>>>>>>>>>>>>>>>>> sun.swing.UndoableEditLock.
>>>>>>>>>>>>>>>>>>>> Every UndoableEdit which implements this
>>>>>>>>>>>>>>>>>>>> interface can provide a lock for its synchronization.
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> If this will work it can be made public in some
>>>>>>>>>>>>>>>>>>>> days so other application can also have proper
>>>>>>>>>>>>>>>>>>>> synchronization for their undo/redo actions.
>>>>>>>>>>>>>>>>>>> OK. I added it.
>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ssadetsky/8030702/webrev.02/
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> - We can return a public class that implements an
>>>>>>>>>>>>>>>>>> internal interface, but we can't expose an internal
>>>>>>>>>>>>>>>>>> API in the public class definition.
>>>>>>>>>>>>>>>>>> May be it is possible to wrap an UndoableEdit to
>>>>>>>>>>>>>>>>>> the UndoableEditLockSupport in the UndoableEditEvent
>>>>>>>>>>>>>>>>>> or in some other place.
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> - The similar code is used both in the
>>>>>>>>>>>>>>>>>> UndoManager.undo() and redo() methods. Is it possible
>>>>>>>>>>>>>>>>>> to move this code to one method that does undo or
>>>>>>>>>>>>>>>>>> redo depending on the given argument?
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> OK. accepted.
>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ssadetsky/8030702/webrev.03/
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> - UndoManager.undo/redo methods
>>>>>>>>>>>>>>>> In your previous fix inProgress variable and the
>>>>>>>>>>>>>>>> super call were used under the lock. It may leads to
>>>>>>>>>>>>>>>> some synchronization issues if you decide to omit it.
>>>>>>>>>>>>>>>> - UndoManager.tryUndoOrRedo()
>>>>>>>>>>>>>>>> It is possible to get rid of 'done' variable just
>>>>>>>>>>>>>>>> using an infinity loop and return the exact result
>>>>>>>>>>>>>>>> where the loop is terminated.
>>>>>>>>>>>>>>>> -
>>>>>>>>>>>>>>>> AbstractDocument.DefaultDocumentEventUndoableWrapper
>>>>>>>>>>>>>>>> implements both UndoableEdit and
>>>>>>>>>>>>>>>> UndoableEditLockSupport interfaces but
>>>>>>>>>>>>>>>> UndoableEditLockSupport already extends UndoableEdit.
>>>>>>>>>>>>>>>> - "@since 1.9" javadoc for
>>>>>>>>>>>>>>>> DefaultDocumentEventUndoableWrapper.lockEdit()/unlockEdit()
>>>>>>>>>>>>>>>> methods really belongs to the UndoableEditLockSupport
>>>>>>>>>>>>>>>> methods.
>>>>>>>>>>>>>>>> In this case there is no need for {@inheritDoc} tag.
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> Thanks,
>>>>>>>>>>>>>>>> Alexandr.
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> Thanks,
>>>>>>>>>>>>>>>>>> Alexandr.
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> Thanks,
>>>>>>>>>>>>>>>>>>>> Alexandr.
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>> "adding links of external classes directly to
>>>>>>>>>>>>>>>>>>>>> UndoManager" - Sorry, did not catch what are you
>>>>>>>>>>>>>>>>>>>>> about? Could you clarify?
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>> --Semyon
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>> Thanks,
>>>>>>>>>>>>>>>>>>>>>> Alexandr.
>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> --Semyon
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>> There is a mistake in your scenario steps:
>>>>>>>>>>>>>>>>>>>>>>>>>>>> fireUndoableEditUpdate() is called before
>>>>>>>>>>>>>>>>>>>>>>>>>>>> the freeing the lock (see
>>>>>>>>>>>>>>>>>>>>>>>>>>>> AbstractDocument.handleInsertString() method).
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Yet another argument do not do this
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> from the user experience: if user
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> starts a long edit operation and press
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> undo after that he expects when the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> long edit is finished it will be rolled
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> back immediately.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> It is not true. The first process
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> adds his undo edit to the UndoManager.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> While a user trying to press undo the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> second long process can be started.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> That is what led to this issue because
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> when undo is in progress document writing
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> should be allowed.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Sorry but I didn't see why is "It not
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> true"? Then what is your expectation when
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> you press undo button while edit is not
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> finished yet and there is no way to abort
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> it?
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> It would be good if it works as you
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> described. But it does not work in this
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> way with or without your fix.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> undo() action has writeLock in
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> AbstractDocument and because of it is
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> always executed after insert string action.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> If a user sees that undo is available,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> he can call it but the second long
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> insertString process can start earlier and
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> acquire the writeLock.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>> That is what we are going to fix. And this
>>>>>>>>>>>>>>>>>>>>>>>>>>>> does work after this fix. Undo call will be
>>>>>>>>>>>>>>>>>>>>>>>>>>>> blocked by the long edit until the last is
>>>>>>>>>>>>>>>>>>>>>>>>>>>> done without any deadlocks. And when edit
>>>>>>>>>>>>>>>>>>>>>>>>>>>> is done undo() will acquire the lock and
>>>>>>>>>>>>>>>>>>>>>>>>>>>> prevent any new edits until undo() is done.
>>>>>>>>>>>>>>>>>>>>>>>>>>>> Please provide a scenario when in your
>>>>>>>>>>>>>>>>>>>>>>>>>>>> opinion it does not wok.
>>>>>>>>>>>>>>>>>>>>>>>>>>> The first process starts for 5 minutes.
>>>>>>>>>>>>>>>>>>>>>>>>>>> When it is finished a user sees that he can
>>>>>>>>>>>>>>>>>>>>>>>>>>> press undo. While he is pressing undo
>>>>>>>>>>>>>>>>>>>>>>>>>>> button, the second long process starts for
>>>>>>>>>>>>>>>>>>>>>>>>>>> 10 minutes and acquire the write lock. The
>>>>>>>>>>>>>>>>>>>>>>>>>>> user presses undo but he needs to wait 10
>>>>>>>>>>>>>>>>>>>>>>>>>>> more minutes until the second process is
>>>>>>>>>>>>>>>>>>>>>>>>>>> finished.
>>>>>>>>>>>>>>>>>>>>>>>>>> Actually, if two or more threads are waiting
>>>>>>>>>>>>>>>>>>>>>>>>>> for a monitor it is not determined which one
>>>>>>>>>>>>>>>>>>>>>>>>>> will get the control after the signal. To
>>>>>>>>>>>>>>>>>>>>>>>>>> order that the ReentrantLock API could be
>>>>>>>>>>>>>>>>>>>>>>>>>> used but AbstractDocument uses wait/notify
>>>>>>>>>>>>>>>>>>>>>>>>>> for locking. I think it is not worth to dig
>>>>>>>>>>>>>>>>>>>>>>>>>> so deep. It does not cause any issues
>>>>>>>>>>>>>>>>>>>>>>>>> The issue that is considered is "if user
>>>>>>>>>>>>>>>>>>>>>>>>> starts a long edit operation and press undo
>>>>>>>>>>>>>>>>>>>>>>>>> after that he expects when the long edit is
>>>>>>>>>>>>>>>>>>>>>>>>> finished it will be rolled back immediately."
>>>>>>>>>>>>>>>>>>>>>>>>> If you are agree that it is not always
>>>>>>>>>>>>>>>>>>>>>>>>> possible to do the roll back "immediately"
>>>>>>>>>>>>>>>>>>>>>>>>> there is no point to discussion.
>>>>>>>>>>>>>>>>>>>>>>>> I agree. On that level it is not possible to
>>>>>>>>>>>>>>>>>>>>>>>> predict the order exactly in such scenario. But
>>>>>>>>>>>>>>>>>>>>>>>> the state of the document will be consistent.
>>>>>>>>>>>>>>>>>>>>>>>> And it is possible to have it predictable using
>>>>>>>>>>>>>>>>>>>>>>>> lock fairness.
>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>> because undo() always get the last edit
>>>>>>>>>>>>>>>>>>>>>>>>>> anyway. If it will be important for somebody
>>>>>>>>>>>>>>>>>>>>>>>>>> to preserve the execution order on that level
>>>>>>>>>>>>>>>>>>>>>>>>>> of details we will fix it.
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> So undo should be executed after the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> edit is fully performed because the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> corresponding UndoableEdit which undos
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> this edit can be produced only after
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> the edit is done.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> I think at first we need to look on the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> situation externally rather than
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> concentrate on implementation questions
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> like in which class do references go.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Yes, please look on this situation
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> from a user point of view which wants to
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> implement simple Java Painter.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> But could you describe this scenario?
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Just steps when this simple Painter fails
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> under the proposed fix?I
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Note, if this Painter's content is not an
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> AbstarctDocument it will work as before
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> the fix.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Any application that uses UndoManager
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> and wants to have the same synchronization
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> (have the same lock both for UndoableEdit
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> adding and undo() method execution) will
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> have the same deadlock problems.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> As I have already written:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ---------------
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Consider someone writes Java Painter
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> application where it is possible to draw
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> lines and images and uses UndoManager for
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> undo/redo actions.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> He might want that it was possible to
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> work with copied images. He can get lock
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> on ctrl+v action, process an image,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> prepare UndoableEdit and notify the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> UndoManager.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> He also can use lock/unlock in the undo
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> action to have a consistent state with the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> processed image. If someone calls undo
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> action during the image processing and
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> gets a deadlock does it mean that link
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> from Java Painter need to be added to the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> UndoManager?
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ---------------
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>> Still do not understand the steps for your
>>>>>>>>>>>>>>>>>>>>>>>>>>>> Painter scenario. A link (reference?) can
>>>>>>>>>>>>>>>>>>>>>>>>>>>> be added if it is required to implement
>>>>>>>>>>>>>>>>>>>>>>>>>>>> functionality. If the content is not an
>>>>>>>>>>>>>>>>>>>>>>>>>>>> AbstarctDocument it may be required to
>>>>>>>>>>>>>>>>>>>>>>>>>>>> implement custom UndoManager to support the
>>>>>>>>>>>>>>>>>>>>>>>>>>>> same behavior.
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>> What is the difference between the
>>>>>>>>>>>>>>>>>>>>>>>>>>> AbstractDocument and other classes (in Swing
>>>>>>>>>>>>>>>>>>>>>>>>>>> or user defined)? Do you mean that the
>>>>>>>>>>>>>>>>>>>>>>>>>>> UndoManager is intended only to be used with
>>>>>>>>>>>>>>>>>>>>>>>>>>> AbstractDocument and it shouldn't be used in
>>>>>>>>>>>>>>>>>>>>>>>>>>> other cases where undo/redo actions are
>>>>>>>>>>>>>>>>>>>>>>>>>>> required for non text data?
>>>>>>>>>>>>>>>>>>>>>>>>>> No, undo manager can be used with any
>>>>>>>>>>>>>>>>>>>>>>>>>> classes. But since we have it assigned to
>>>>>>>>>>>>>>>>>>>>>>>>>> AbstarctDocument so often we need to do our
>>>>>>>>>>>>>>>>>>>>>>>>>> best to make undo manager working with it
>>>>>>>>>>>>>>>>>>>>>>>>>> correctly because users do not like deadlocks
>>>>>>>>>>>>>>>>>>>>>>>>>> usualy. For other classes we cannot provide
>>>>>>>>>>>>>>>>>>>>>>>>>> synchronization by default because there is
>>>>>>>>>>>>>>>>>>>>>>>>>> no API to get the lock. So it remains up to
>>>>>>>>>>>>>>>>>>>>>>>>>> user how to provide the undo manager
>>>>>>>>>>>>>>>>>>>>>>>>>> synchronization with the object it controls
>>>>>>>>>>>>>>>>>>>>>>>>>> for other classes
>>>>>>>>>>>>>>>>>>>>>>>>> What we should do just to understand that
>>>>>>>>>>>>>>>>>>>>>>>>> the same deadlock can happen in an user
>>>>>>>>>>>>>>>>>>>>>>>>> applications because he wants to use the same
>>>>>>>>>>>>>>>>>>>>>>>>> synchronization both for the data processing
>>>>>>>>>>>>>>>>>>>>>>>>> and for the undo action. If so, there should
>>>>>>>>>>>>>>>>>>>>>>>>> be two investigations:
>>>>>>>>>>>>>>>>>>>>>>>>> 1. Is it possible to achieve the requested
>>>>>>>>>>>>>>>>>>>>>>>>> goals without changing UndoManager? In other
>>>>>>>>>>>>>>>>>>>>>>>>> words The UndoManager should be used in proper
>>>>>>>>>>>>>>>>>>>>>>>>> way as it is required by its design.
>>>>>>>>>>>>>>>>>>>>>>>>> 2. Is it possible to update the UndoManager
>>>>>>>>>>>>>>>>>>>>>>>>> API to provide functionality that meets new
>>>>>>>>>>>>>>>>>>>>>>>>> requests?
>>>>>>>>>>>>>>>>>>>>>>>> With API change it is reachable. But I would
>>>>>>>>>>>>>>>>>>>>>>>> preserve the current API as less constrained.
>>>>>>>>>>>>>>>>>>>>>>>> If we add some methods for locking we will
>>>>>>>>>>>>>>>>>>>>>>>> determine the way how a user should synchronize
>>>>>>>>>>>>>>>>>>>>>>>> his undoable content. And user may not need any
>>>>>>>>>>>>>>>>>>>>>>>> synchronization at all. We should keep in mind
>>>>>>>>>>>>>>>>>>>>>>>> this opportunity as well.
>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>> Only after this discussion there can be a
>>>>>>>>>>>>>>>>>>>>>>>>> reason to look to other ways.
>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>> Thanks,
>>>>>>>>>>>>>>>>>>>>>>>>> Alexandr.
>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>> I think our undo manager implementation do
>>>>>>>>>>>>>>>>>>>>>>>>>> not pretend to be used as the global undo
>>>>>>>>>>>>>>>>>>>>>>>>>> manager for big complex applications and it
>>>>>>>>>>>>>>>>>>>>>>>>>> cannot cover all possible undo approaches.
>>>>>>>>>>>>>>>>>>>>>>>>>> But some basic functionality can be provided
>>>>>>>>>>>>>>>>>>>>>>>>>> and it should be usable. Without edits
>>>>>>>>>>>>>>>>>>>>>>>>>> serialization approach it is not usable for
>>>>>>>>>>>>>>>>>>>>>>>>>> multithreaded use. So either we do not
>>>>>>>>>>>>>>>>>>>>>>>>>> pretend to provide a multithreaded undo
>>>>>>>>>>>>>>>>>>>>>>>>>> manager and remove all synchronize keywords
>>>>>>>>>>>>>>>>>>>>>>>>>> from UndoManager class, either we need to
>>>>>>>>>>>>>>>>>>>>>>>>>> support serialization approach which does not
>>>>>>>>>>>>>>>>>>>>>>>>>> cause deadlocks.
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks,
>>>>>>>>>>>>>>>>>>>>>>>>>>> Alexandr.
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>> I don't see a contradiction here, could you
>>>>>>>>>>>>>>>>>>>>>>>>>>>> point on it more precisely?
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Alexandr.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Alexandr.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Alexandr.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> --Semyon
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Alexandr.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> --Semyon
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On 7/30/2015 5:27 PM, Alexander
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Scherbatiy wrote:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Consider someone writes Java
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Painter application where it is
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> possible to draw lines and images
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> and uses UndoManager for undo/redo
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> actions.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> He might want that it was
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> possible to work with copied
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> images. He can get lock on ctrl+v
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> action, process an image, prepare
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> UndoableEdit and notify the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> UndoManager.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> He also can use lock/unlock in
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> the undo action to have a
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> consistent state with the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> processed image. If someone calls
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> undo action during the image
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> processing and gets a deadlock
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> does it mean that link from Java
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Painter need to be added to the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> UndoManager?
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Alexandr.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> It looks like AbstractDocument
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> violates UndoManager
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> synchronization contract when it
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> both use lock to work with
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> UndoManager and in the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> implemented undo() method.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Alexandr.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> --Semyon
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>>
>
More information about the swing-dev
mailing list