package net.acomputerdog.webchat;

import net.acomputerdog.webchat.util.BoundedSet;

import java.util.function.Consumer;

public class ChatList {
    private final BoundedSet<String> lines;
    private final Object lock;

    //increments after every new chat message, can safely overflow to negative
    private int version;

    public ChatList(PluginWebChat plugin) {
        lines = new BoundedSet<>(plugin.maxLines);
        lock = new Object();
        version = 0;
    }

    public void forEach(Consumer<String> consumer) {
        synchronized (lock) {
            for (String str : lines) {
                consumer.accept(str);
            }
        }
    }

    public void addLine(String line) {
        if (line != null) {
            line = filter(line);
            synchronized (lock) {
                lines.add(line);
                version++;
            }
        }
    }

    public int getVersion() {
        synchronized (lock) {
            return version;
        }
    }

    private String filter(String line) {
        StringBuilder builder = new StringBuilder(line.length());
        for (char chr : line.toCharArray()) {
            switch (chr) {
                case '<':
                case '>':
                case '{':
                case '}':
                    break; //ignore those characters
                default:
                    builder.append(chr);//otherwise add
            }
        }
        return builder.toString();
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        forEach(line -> {
            builder.append(line);
            builder.append("\n");
        });
        return builder.toString();
    }
}

@@ -74,24 +74,63 @@
 oundedSet;%0A%0A
+import java.util.concurrent.Semaphore;%0A
 import java.
@@ -153,16 +153,16 @@
 nsumer;%0A
-
 %0Apublic 
@@ -240,22 +240,25 @@
 e final 
-Object
+Semaphore
  lock;%0A%0A
@@ -480,15 +480,25 @@
 new 
-Object(
+Semaphore(1, true
 );%0A 
@@ -585,35 +585,58 @@
         
-synchronized (lock)
+lock.acquireUninterruptibly();%0A        try
  %7B%0A     
@@ -713,32 +713,80 @@
 ;%0A            %7D%0A
+        %7D finally %7B%0A            lock.release();%0A
         %7D%0A    %7D%0A
@@ -878,32 +878,33 @@
 = filter(line);%0A
+%0A
             sync
@@ -899,35 +899,62 @@
         
-synchronized (lock)
+lock.acquireUninterruptibly();%0A            try
  %7B%0A     
@@ -1008,16 +1008,72 @@
 sion++;%0A
+            %7D finally %7B%0A                lock.release();%0A
         
@@ -1137,56 +1137,127 @@
     
-synchronized (lock) %7B%0A            return version
+lock.acquireUninterruptibly();%0A        try %7B%0A            return version;%0A        %7D finally %7B%0A            lock.release()
 ;%0A  

Rewrite concurrency in ChatList