use CoW data structure for read markers. fixes #3904

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/entities/Message.java      |  6 
src/main/java/eu/siacs/conversations/entities/ReadByMarker.java | 24 +-
2 files changed, 15 insertions(+), 15 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/entities/Message.java 🔗

@@ -15,10 +15,10 @@ import java.lang.ref.WeakReference;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.ArrayList;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
 
 import eu.siacs.conversations.Config;
 import eu.siacs.conversations.crypto.axolotl.FingerprintStatus;
@@ -113,7 +113,7 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable
 	private Message mPreviousMessage = null;
 	private String axolotlFingerprint = null;
 	private String errorMessage = null;
-	private Set<ReadByMarker> readByMarkers = new HashSet<>();
+	private Set<ReadByMarker> readByMarkers = new CopyOnWriteArraySet<>();
 
 	private Boolean isGeoUri = null;
 	private Boolean isEmojisOnly = null;
@@ -206,7 +206,7 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable
 		this.edits = Edit.fromJson(edited);
 		this.oob = oob;
 		this.errorMessage = errorMessage;
-		this.readByMarkers = readByMarkers == null ? new HashSet<>() : readByMarkers;
+		this.readByMarkers = readByMarkers == null ? new CopyOnWriteArraySet<>() : readByMarkers;
 		this.markable = markable;
 		this.deleted = deleted;
 		this.bodyLanguage = bodyLanguage;

src/main/java/eu/siacs/conversations/entities/ReadByMarker.java 🔗

@@ -5,8 +5,8 @@ import org.json.JSONException;
 import org.json.JSONObject;
 
 import java.util.Collection;
-import java.util.HashSet;
 import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
 
 import eu.siacs.conversations.xmpp.Jid;
 
@@ -66,8 +66,8 @@ public class ReadByMarker {
 		return jsonObject;
 	}
 
-	public static Set<ReadByMarker> fromJson(JSONArray jsonArray) {
-		HashSet<ReadByMarker> readByMarkers = new HashSet<>();
+	public static Set<ReadByMarker> fromJson(final JSONArray jsonArray) {
+		final Set<ReadByMarker> readByMarkers = new CopyOnWriteArraySet<>();
 		for(int i = 0; i < jsonArray.length(); ++i) {
 			try {
 				readByMarkers.add(fromJson(jsonArray.getJSONObject(i)));
@@ -100,7 +100,7 @@ public class ReadByMarker {
 	}
 
 	public static Set<ReadByMarker> from(Collection<MucOptions.User> users) {
-		final HashSet<ReadByMarker> markers = new HashSet<>();
+		final Set<ReadByMarker> markers = new CopyOnWriteArraySet<>();
 		for(MucOptions.User user : users) {
 			markers.add(from(user));
 		}
@@ -125,21 +125,21 @@ public class ReadByMarker {
 	public static Set<ReadByMarker> fromJsonString(String json) {
 		try {
 			return fromJson(new JSONArray(json));
-		} catch (JSONException | NullPointerException e) {
-			return new HashSet<>();
+		} catch (final JSONException | NullPointerException e) {
+			return new CopyOnWriteArraySet<>();
 		}
 	}
 
-	public static JSONArray toJson(Set<ReadByMarker> readByMarkers) {
-		JSONArray jsonArray = new JSONArray();
-		for(ReadByMarker marker : readByMarkers) {
+	public static JSONArray toJson(final Set<ReadByMarker> readByMarkers) {
+		final JSONArray jsonArray = new JSONArray();
+		for(final ReadByMarker marker : readByMarkers) {
 			jsonArray.put(marker.toJson());
 		}
 		return jsonArray;
 	}
 
-	public static boolean contains(ReadByMarker needle, Set<ReadByMarker> readByMarkers) {
-		for(ReadByMarker marker : readByMarkers) {
+	public static boolean contains(ReadByMarker needle, final Set<ReadByMarker> readByMarkers) {
+		for(final ReadByMarker marker : readByMarkers) {
 			if (marker.realJid != null && needle.realJid != null) {
 				if (marker.realJid.asBareJid().equals(needle.realJid.asBareJid())) {
 					return true;
@@ -163,7 +163,7 @@ public class ReadByMarker {
 	}
 
 	public static boolean allUsersRepresented(Collection<MucOptions.User> users, Set<ReadByMarker> markers, ReadByMarker marker) {
-		HashSet<ReadByMarker> markersCopy = new HashSet<>(markers);
+		final Set<ReadByMarker> markersCopy = new CopyOnWriteArraySet<>(markers);
 		markersCopy.add(marker);
 		return allUsersRepresented(users, markersCopy);
 	}