@@ -111,12 +111,12 @@ public class LogView extends ViewPart implements LogListener {
111111
112112 private ServiceTracker <LogReaderService , LogReaderService > logReaderServiceTracker ;
113113
114- private List <AbstractEntry > elements ;
114+ private final List <AbstractEntry > elements ;
115115 private Map <Object , Group > groups ;
116116 private LogSession currentSession ;
117117
118- private List <LogEntry > batchedEntries ;
119- private boolean batchEntries ;
118+ private final List <LogEntry > batchedEntries ;
119+ private volatile boolean batchEntries ;
120120
121121 private Clipboard fClipboard ;
122122
@@ -244,10 +244,11 @@ public void perspectiveChanged(IWorkbenchPage page, IPerspectiveDescriptor persp
244244
245245 if (part .equals (LogView .this )) {
246246 if (changeId .equals (IWorkbenchPage .CHANGE_VIEW_SHOW )) {
247- if (!batchedEntries .isEmpty ()) {
248- pushBatchedEntries ();
247+ synchronized (batchedEntries ) {
248+ if (!batchedEntries .isEmpty ()) {
249+ pushBatchedEntries ();
250+ }
249251 }
250-
251252 batchEntries = false ;
252253 } else if (changeId .equals (IWorkbenchPage .CHANGE_VIEW_HIDE )) {
253254 batchEntries = true ;
@@ -834,10 +835,12 @@ public AbstractEntry[] getElements() {
834835
835836 public void handleClear () {
836837 BusyIndicator .showWhile (fTree .getDisplay (), () -> {
837- elements .clear ();
838- groups .clear ();
839- if (currentSession != null ) {
840- currentSession .removeAllChildren ();
838+ synchronized (elements ) {
839+ elements .clear ();
840+ groups .clear ();
841+ if (currentSession != null ) {
842+ currentSession .removeAllChildren ();
843+ }
841844 }
842845 asyncRefresh (false );
843846 resetDialogButtons ();
@@ -888,10 +891,12 @@ private CompletableFuture<List<LogEntry>> fetchLogEntries() {
888891 }
889892
890893 private void updateLogViewer (List <LogEntry > entries ) {
891- elements .clear ();
892- groups .clear ();
893- group (entries );
894- limitEntriesCount ();
894+ synchronized (elements ) {
895+ elements .clear ();
896+ groups .clear ();
897+ group (entries );
898+ limitEntriesCount ();
899+ }
895900 setContentDescription (getTitleSummary ());
896901
897902 asyncRefresh (false );
@@ -1082,7 +1087,9 @@ public void logged(org.osgi.service.log.LogEntry input) {
10821087 if (batchEntries ) {
10831088 // create LogEntry immediately to don't loose IStatus creation date.
10841089 LogEntry entry = betterInput != null ? createLogEntry (betterInput ) : createLogEntry (input );
1085- batchedEntries .add (entry );
1090+ synchronized (batchedEntries ) {
1091+ batchedEntries .add (entry );
1092+ }
10861093 return ;
10871094 }
10881095
@@ -1093,11 +1100,16 @@ public void logged(org.osgi.service.log.LogEntry input) {
10931100 } else {
10941101 LogEntry entry = betterInput != null ? createLogEntry (betterInput ) : createLogEntry (input );
10951102
1096- if (!batchedEntries .isEmpty ()) {
1103+ boolean useBatchedEntries ;
1104+ synchronized (batchedEntries ) {
1105+ useBatchedEntries = !batchedEntries .isEmpty ();
10971106 // batch new entry as well, to have only one asyncRefresh()
1098- batchedEntries .add (entry );
1099- pushBatchedEntries ();
1100- } else {
1107+ if (useBatchedEntries ) {
1108+ batchedEntries .add (entry );
1109+ pushBatchedEntries ();
1110+ }
1111+ }
1112+ if (!useBatchedEntries ) {
11011113 pushEntry (entry );
11021114 asyncRefresh (true );
11031115 }
@@ -1111,11 +1123,14 @@ private void pushBatchedEntries() {
11111123 Job job = new Job (Messages .LogView_AddingBatchedEvents ) {
11121124 @ Override
11131125 protected IStatus run (IProgressMonitor monitor ) {
1114- for (int i = 0 ; i < batchedEntries .size (); i ++) {
1115- if (!monitor .isCanceled ()) {
1116- LogEntry entry = batchedEntries .get (i );
1117- pushEntry (entry );
1118- batchedEntries .remove (i );
1126+ synchronized (batchedEntries ) {
1127+ Iterator <LogEntry > iterator = batchedEntries .iterator ();
1128+ while (iterator .hasNext ()) {
1129+ if (!monitor .isCanceled ()) {
1130+ LogEntry entry = iterator .next ();
1131+ pushEntry (entry );
1132+ iterator .remove ();
1133+ }
11191134 }
11201135 }
11211136 asyncRefresh (true );
@@ -1159,10 +1174,12 @@ private LogEntry createLogEntry(FrameworkLogEntry input) {
11591174 return logEntry ;
11601175 }
11611176
1162- private synchronized void pushEntry (LogEntry entry ) {
1163- if (LogReader .isLogged (entry , fMemento )) {
1164- group (Collections .singletonList (entry ));
1165- limitEntriesCount ();
1177+ private void pushEntry (LogEntry entry ) {
1178+ synchronized (elements ) {
1179+ if (LogReader .isLogged (entry , fMemento )) {
1180+ group (Collections .singletonList (entry ));
1181+ limitEntriesCount ();
1182+ }
11661183 }
11671184 asyncRefresh (true );
11681185 }
@@ -1558,6 +1575,7 @@ private void setComparator(byte sortType) {
15581575 date2 = ((LogSession ) e2 ).getDate () == null ? 0 : ((LogSession ) e2 ).getDate ().getTime ();
15591576 }
15601577 if (date1 == date2 ) {
1578+ // XXX: this breaks stable sort, as elements is mutable
15611579 int result = elements .indexOf (e2 ) - elements .indexOf (e1 );
15621580 if (DATE_ORDER == DESCENDING )
15631581 result *= DESCENDING ;
@@ -1653,6 +1671,8 @@ public int compare(Viewer viewer, Object e1, Object e2) {
16531671 // i.e. latest log message first, therefore index(e2)-index(e1)
16541672 result = indexOf (children , e2 ) - indexOf (children , e1 );
16551673 } else {
1674+ // XXX: this breaks stable sort, as elements is
1675+ // mutable
16561676 result = elements .indexOf (e1 ) - elements .indexOf (e2 );
16571677 }
16581678 if (DATE_ORDER == DESCENDING )
0 commit comments