(Object a)
| 171 | // toArray |
| 172 | // ------------------------------------------------- |
| 173 | public static List<Object> toArray(Object a) { |
| 174 | if (a == null) return null; |
| 175 | |
| 176 | // WS caches mutate from the message-executor thread. Take the snapshot |
| 177 | // under the cache's own monitor so the copy can't observe a remove(0) |
| 178 | // mid-flight (would surface as nulls / off-by-one IOOBE downstream). |
| 179 | if (a instanceof io.github.ccxt.ws.ArrayCache cache) { |
| 180 | return cache.snapshot(); |
| 181 | } |
| 182 | if (a instanceof List<?> l) { |
| 183 | return new ArrayList<>((List<Object>) l); |
| 184 | } |
| 185 | |
| 186 | // treat as map -> return values as list (preserve insertion order if possible). |
| 187 | // Take the map's intrinsic lock so this iteration can't observe a concurrent |
| 188 | // put/remove from a WS handler (paired with the synchronized block in |
| 189 | // Helpers.addElementToObject's Map branch). Symptom without this: binance |
| 190 | // watchTickers ConcurrentModificationException from HashMap$KeySpliterator. |
| 191 | Map<String, Object> b = (Map<String, Object>) a; |
| 192 | synchronized (b) { |
| 193 | List<Object> out = new ArrayList<>(b.size()); |
| 194 | for (String key : b.keySet()) { |
| 195 | out.add(b.get(key)); |
| 196 | } |
| 197 | return out; |
| 198 | } |
| 199 | } |
| 200 | |
| 201 | // ------------------------------------------------- |
| 202 | // arrayConcat |
no test coverage detected