Skip to content

Commit ccb87f6

Browse files
committed
Fix concurrent modification exception
1 parent 885c8ce commit ccb87f6

File tree

2 files changed

+34
-29
lines changed

2 files changed

+34
-29
lines changed

lib/src/main/java/ua/naiksoftware/stomp/OkHttpConnectionProvider.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import android.util.Log;
44

55
import java.util.ArrayList;
6+
import java.util.Collections;
67
import java.util.HashMap;
78
import java.util.Iterator;
89
import java.util.List;
@@ -33,13 +34,11 @@
3334

3435
private WebSocket openedSocked;
3536

36-
private final Object mLifecycleLock = new Object();
37-
3837

3938
/* package */ OkHttpConnectionProvider(String uri, Map<String, String> connectHttpHeaders, OkHttpClient okHttpClient) {
4039
mUri = uri;
4140
mConnectHttpHeaders = connectHttpHeaders != null ? connectHttpHeaders : new HashMap<>();
42-
mLifecycleEmitters = new ArrayList<>();
41+
mLifecycleEmitters = Collections.synchronizedList(new ArrayList<>());
4342
mMessagesEmitters = new ArrayList<>();
4443
mOkHttpClient = okHttpClient;
4544
}
@@ -133,7 +132,7 @@ public Flowable<Void> send(String stompMessage) {
133132
public Flowable<LifecycleEvent> getLifecycleReceiver() {
134133
return Flowable.<LifecycleEvent>create(mLifecycleEmitters::add, BackpressureStrategy.BUFFER)
135134
.doOnCancel(() -> {
136-
synchronized (mLifecycleLock) {
135+
synchronized (mLifecycleEmitters) {
137136
Iterator<FlowableEmitter<? super LifecycleEvent>> iterator = mLifecycleEmitters.iterator();
138137
while (iterator.hasNext()) {
139138
if (iterator.next().isCancelled()) iterator.remove();
@@ -158,7 +157,7 @@ private void addConnectionHeadersToBuilder(Request.Builder requestBuilder, Map<S
158157
}
159158

160159
private void emitLifecycleEvent(LifecycleEvent lifecycleEvent) {
161-
synchronized (mLifecycleLock) {
160+
synchronized (mLifecycleEmitters) {
162161
Log.d(TAG, "Emit lifecycle event: " + lifecycleEvent.getType().name());
163162
for (FlowableEmitter<? super LifecycleEvent> subscriber : mLifecycleEmitters) {
164163
subscriber.onNext(lifecycleEvent);

lib/src/main/java/ua/naiksoftware/stomp/client/StompClient.java

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public class StompClient {
3535

3636
private Disposable mMessagesDisposable;
3737
private Disposable mLifecycleDisposable;
38-
private Map<String, Set<FlowableEmitter<? super StompMessage>>> mEmitters = new ConcurrentHashMap<>();
38+
private Map<String, Set<FlowableEmitter<? super StompMessage>>> mEmitters = Collections.synchronizedMap(new HashMap<>());
3939
private List<ConnectableFlowable<Void>> mWaitConnectionFlowables;
4040
private final ConnectionProvider mConnectionProvider;
4141
private HashMap<String, String> mTopics;
@@ -141,12 +141,14 @@ public Flowable<Void> send(StompMessage stompMessage) {
141141

142142
private void callSubscribers(StompMessage stompMessage) {
143143
String messageDestination = stompMessage.findHeader(StompHeader.DESTINATION);
144-
for (String dest : mEmitters.keySet()) {
145-
if (dest.equals(messageDestination)) {
146-
for (FlowableEmitter<? super StompMessage> subscriber : mEmitters.get(dest)) {
147-
subscriber.onNext(stompMessage);
144+
synchronized (mEmitters) {
145+
for (String dest : mEmitters.keySet()) {
146+
if (dest.equals(messageDestination)) {
147+
for (FlowableEmitter<? super StompMessage> subscriber : mEmitters.get(dest)) {
148+
subscriber.onNext(stompMessage);
149+
}
150+
return;
148151
}
149-
return;
150152
}
151153
}
152154
}
@@ -167,27 +169,31 @@ public Flowable<StompMessage> topic(String destinationPath) {
167169

168170
public Flowable<StompMessage> topic(String destinationPath, List<StompHeader> headerList) {
169171
return Flowable.<StompMessage>create(emitter -> {
170-
Set<FlowableEmitter<? super StompMessage>> emittersSet = mEmitters.get(destinationPath);
171-
if (emittersSet == null) {
172-
emittersSet = new HashSet<>();
173-
mEmitters.put(destinationPath, emittersSet);
174-
subscribePath(destinationPath, headerList).subscribe();
172+
synchronized (mEmitters) {
173+
Set<FlowableEmitter<? super StompMessage>> emittersSet = mEmitters.get(destinationPath);
174+
if (emittersSet == null) {
175+
emittersSet = new HashSet<>();
176+
mEmitters.put(destinationPath, emittersSet);
177+
subscribePath(destinationPath, headerList).subscribe();
178+
}
179+
emittersSet.add(emitter);
175180
}
176-
emittersSet.add(emitter);
177181
}, BackpressureStrategy.BUFFER)
178182
.doOnCancel(() -> {
179-
Iterator<String> mapIterator = mEmitters.keySet().iterator();
180-
while (mapIterator.hasNext()) {
181-
String destinationUrl = mapIterator.next();
182-
Set<FlowableEmitter<? super StompMessage>> set = mEmitters.get(destinationUrl);
183-
Iterator<FlowableEmitter<? super StompMessage>> setIterator = set.iterator();
184-
while (setIterator.hasNext()) {
185-
FlowableEmitter<? super StompMessage> subscriber = setIterator.next();
186-
if (subscriber.isCancelled()) {
187-
setIterator.remove();
188-
if (set.size() < 1) {
189-
mapIterator.remove();
190-
unsubscribePath(destinationUrl).subscribe();
183+
synchronized (mEmitters) {
184+
Iterator<String> mapIterator = mEmitters.keySet().iterator();
185+
while (mapIterator.hasNext()) {
186+
String destinationUrl = mapIterator.next();
187+
Set<FlowableEmitter<? super StompMessage>> set = mEmitters.get(destinationUrl);
188+
Iterator<FlowableEmitter<? super StompMessage>> setIterator = set.iterator();
189+
while (setIterator.hasNext()) {
190+
FlowableEmitter<? super StompMessage> subscriber = setIterator.next();
191+
if (subscriber.isCancelled()) {
192+
setIterator.remove();
193+
if (set.size() < 1) {
194+
mapIterator.remove();
195+
unsubscribePath(destinationUrl).subscribe();
196+
}
191197
}
192198
}
193199
}

0 commit comments

Comments
 (0)