127 |
* Manages event listeners for this <code>Document</code>. |
* Manages event listeners for this <code>Document</code>. |
128 |
*/ |
*/ |
129 |
protected EventListenerList listenerList = new EventListenerList(); |
protected EventListenerList listenerList = new EventListenerList(); |
130 |
|
|
131 |
|
/** |
132 |
|
* Stores the current writer thread. Used for locking. |
133 |
|
*/ |
134 |
|
private Thread currentWriter = null; |
135 |
|
|
136 |
|
/** |
137 |
|
* The number of readers. Used for locking. |
138 |
|
*/ |
139 |
|
private int numReaders = 0; |
140 |
|
|
141 |
|
/** |
142 |
|
* Tells if there are one or more writers waiting. |
143 |
|
*/ |
144 |
|
private int numWritersWaiting = 0; |
145 |
|
|
146 |
/** |
/** |
147 |
|
* A condition variable that readers and writers wait on. |
148 |
|
*/ |
149 |
|
Object documentCV = new Object(); |
150 |
|
|
151 |
|
|
152 |
|
/** |
153 |
* Creates a new <code>AbstractDocument</code> with the specified |
* Creates a new <code>AbstractDocument</code> with the specified |
154 |
* {@link Content} model. |
* {@link Content} model. |
155 |
* |
* |
368 |
*/ |
*/ |
369 |
protected Thread getCurrentWriter() |
protected Thread getCurrentWriter() |
370 |
{ |
{ |
371 |
// FIXME: Implement locking! |
return currentWriter; |
|
return null; |
|
372 |
} |
} |
373 |
|
|
374 |
/** |
/** |
540 |
new DefaultDocumentEvent(offset, text.length(), |
new DefaultDocumentEvent(offset, text.length(), |
541 |
DocumentEvent.EventType.INSERT); |
DocumentEvent.EventType.INSERT); |
542 |
|
|
543 |
|
writeLock(); |
544 |
UndoableEdit temp = content.insertString(offset, text); |
UndoableEdit temp = content.insertString(offset, text); |
545 |
|
writeUnlock(); |
546 |
|
|
547 |
GapContent.UndoInsertString changes = null; |
GapContent.UndoInsertString changes = null; |
548 |
if (content instanceof GapContent) |
if (content instanceof GapContent) |
549 |
changes = (GapContent.UndoInsertString) temp; |
changes = (GapContent.UndoInsertString) temp; |
610 |
} |
} |
611 |
|
|
612 |
/** |
/** |
613 |
* Blocks until a read lock can be obtained. |
* Blocks until a read lock can be obtained. Must block if there is |
614 |
|
* currently a writer modifying the <code>Document</code>. |
615 |
*/ |
*/ |
616 |
public void readLock() |
public void readLock() |
617 |
{ |
{ |
618 |
|
if (currentWriter != null && currentWriter.equals(Thread.currentThread())) |
619 |
|
return; |
620 |
|
synchronized (documentCV) |
621 |
|
{ |
622 |
|
while (currentWriter != null || numWritersWaiting > 0) |
623 |
|
{ |
624 |
|
try |
625 |
|
{ |
626 |
|
documentCV.wait(); |
627 |
|
} |
628 |
|
catch (InterruptedException ie) |
629 |
|
{ |
630 |
|
throw new Error("interrupted trying to get a readLock"); |
631 |
|
} |
632 |
|
} |
633 |
|
numReaders++; |
634 |
|
} |
635 |
} |
} |
636 |
|
|
637 |
/** |
/** |
640 |
*/ |
*/ |
641 |
public void readUnlock() |
public void readUnlock() |
642 |
{ |
{ |
643 |
|
// Note we could have a problem here if readUnlock was called without a |
644 |
|
// prior call to readLock but the specs simply warn users to ensure that |
645 |
|
// balance by using a finally block: |
646 |
|
// readLock() |
647 |
|
// try |
648 |
|
// { |
649 |
|
// doSomethingHere |
650 |
|
// } |
651 |
|
// finally |
652 |
|
// { |
653 |
|
// readUnlock(); |
654 |
|
// } |
655 |
|
|
656 |
|
// All that the JDK seems to check for is that you don't call unlock |
657 |
|
// more times than you've previously called lock, but it doesn't make |
658 |
|
// sure that the threads calling unlock were the same ones that called lock |
659 |
|
|
660 |
|
// FIXME: the reference implementation throws a |
661 |
|
// javax.swing.text.StateInvariantError here |
662 |
|
if (numReaders == 0) |
663 |
|
throw new IllegalStateException("document lock failure"); |
664 |
|
|
665 |
|
synchronized (documentCV) |
666 |
|
{ |
667 |
|
// If currentWriter is not null, the application code probably had a |
668 |
|
// writeLock and then tried to obtain a readLock, in which case |
669 |
|
// numReaders wasn't incremented |
670 |
|
if (currentWriter == null) |
671 |
|
{ |
672 |
|
numReaders --; |
673 |
|
if (numReaders == 0 && numWritersWaiting != 0) |
674 |
|
documentCV.notify(); |
675 |
|
} |
676 |
|
} |
677 |
} |
} |
678 |
|
|
679 |
/** |
/** |
708 |
added[0] = root.getElement(start); |
added[0] = root.getElement(start); |
709 |
boolean shouldFire = content.getString(offset, length).length() != 0; |
boolean shouldFire = content.getString(offset, length).length() != 0; |
710 |
|
|
711 |
|
writeLock(); |
712 |
UndoableEdit temp = content.remove(offset, length); |
UndoableEdit temp = content.remove(offset, length); |
713 |
|
writeUnlock(); |
714 |
|
|
715 |
postRemoveUpdate(event); |
postRemoveUpdate(event); |
716 |
|
|
841 |
*/ |
*/ |
842 |
public void render(Runnable runnable) |
public void render(Runnable runnable) |
843 |
{ |
{ |
844 |
// FIXME: Implement me! |
readLock(); |
845 |
|
try |
846 |
|
{ |
847 |
|
runnable.run(); |
848 |
|
} |
849 |
|
finally |
850 |
|
{ |
851 |
|
readUnlock(); |
852 |
|
} |
853 |
} |
} |
854 |
|
|
855 |
/** |
/** |
875 |
} |
} |
876 |
|
|
877 |
/** |
/** |
878 |
* Blocks until a write lock can be obtained. |
* Blocks until a write lock can be obtained. Must wait if there are |
879 |
|
* readers currently reading or another thread is currently writing. |
880 |
*/ |
*/ |
881 |
protected void writeLock() |
protected void writeLock() |
882 |
{ |
{ |
883 |
// FIXME: Implement me. |
if (currentWriter!= null && currentWriter.equals(Thread.currentThread())) |
884 |
|
return; |
885 |
|
synchronized (documentCV) |
886 |
|
{ |
887 |
|
numWritersWaiting++; |
888 |
|
while (numReaders > 0) |
889 |
|
{ |
890 |
|
try |
891 |
|
{ |
892 |
|
documentCV.wait(); |
893 |
|
} |
894 |
|
catch (InterruptedException ie) |
895 |
|
{ |
896 |
|
throw new Error("interruped while trying to obtain write lock"); |
897 |
|
} |
898 |
|
} |
899 |
|
numWritersWaiting --; |
900 |
|
currentWriter = Thread.currentThread(); |
901 |
|
} |
902 |
} |
} |
903 |
|
|
904 |
/** |
/** |
907 |
*/ |
*/ |
908 |
protected void writeUnlock() |
protected void writeUnlock() |
909 |
{ |
{ |
910 |
// FIXME: Implement me. |
synchronized (documentCV) |
911 |
|
{ |
912 |
|
if (currentWriter.equals(Thread.currentThread())) |
913 |
|
{ |
914 |
|
currentWriter = null; |
915 |
|
documentCV.notifyAll(); |
916 |
|
} |
917 |
|
} |
918 |
} |
} |
919 |
|
|
920 |
/** |
/** |