@@ -889,9 +889,9 @@ public String toString() {
889
889
private final State .Builder <T > builder ;
890
890
private ParseUser user ;
891
891
892
- private final Object lock = new Object ();
893
- private int isRunning = 0 ;
894
- private TaskCompletionSource < Void > cts = new TaskCompletionSource <>( );
892
+ // Just like ParseFile
893
+ private Set < TaskCompletionSource <?>> currentTasks = Collections . synchronizedSet (
894
+ new HashSet < TaskCompletionSource <?>>() );
895
895
896
896
/**
897
897
* Constructs a query for a {@link ParseObject} subclass type. A default query with no further
@@ -961,21 +961,19 @@ public ParseQuery(ParseQuery<T> query) {
961
961
}
962
962
963
963
/**
964
- * Cancels the current network request (if one is running).
964
+ * Cancels the current network request(s) (if any is running).
965
965
*/
966
966
//TODO (grantland): Deprecate and replace with CancellationTokens
967
967
public void cancel () {
968
- synchronized (lock ) {
969
- cts .trySetCancelled ();
970
- cts = new TaskCompletionSource <>();
971
- isRunning = 0 ;
968
+ Set <TaskCompletionSource <?>> tasks = new HashSet <>(currentTasks );
969
+ for (TaskCompletionSource <?> tcs : tasks ) {
970
+ tcs .trySetCancelled ();
972
971
}
972
+ currentTasks .removeAll (tasks );
973
973
}
974
974
975
975
public boolean isRunning () {
976
- synchronized (lock ) {
977
- return isRunning > 0 ;
978
- }
976
+ return currentTasks .size () > 0 ;
979
977
}
980
978
981
979
/**
@@ -1123,10 +1121,13 @@ public long getMaxCacheAge() {
1123
1121
}
1124
1122
1125
1123
1126
- private <TResult > Task <TResult > perform (Callable <Task <TResult >> runnable ) {
1127
- synchronized (lock ) {
1128
- isRunning ++;
1129
- }
1124
+ /**
1125
+ * Wraps the runnable operation and keeps it in sync with the given tcs, so we know how many
1126
+ * operations are running (currentTasks.size()) and can cancel them.
1127
+ */
1128
+ private <TResult > Task <TResult > perform (Callable <Task <TResult >> runnable , final TaskCompletionSource <?> tcs ) {
1129
+ currentTasks .add (tcs );
1130
+
1130
1131
Task <TResult > task ;
1131
1132
try {
1132
1133
task = runnable .call ();
@@ -1136,10 +1137,8 @@ private <TResult> Task<TResult> perform(Callable<Task<TResult>> runnable) {
1136
1137
return task .continueWithTask (new Continuation <TResult , Task <TResult >>() {
1137
1138
@ Override
1138
1139
public Task <TResult > then (Task <TResult > task ) throws Exception {
1139
- synchronized (lock ) {
1140
- // cancel() drops the count to 0 so we have to check
1141
- isRunning = Math .max (isRunning -1 , 0 );
1142
- }
1140
+ tcs .trySetResult (null ); // release
1141
+ currentTasks .remove (tcs );
1143
1142
return task ;
1144
1143
}
1145
1144
});
@@ -1187,18 +1186,19 @@ public Task<List<T>> call(State<T> state, ParseUser user, Task<Void> cancellatio
1187
1186
}
1188
1187
1189
1188
private Task <List <T >> findAsync (final State <T > state ) {
1189
+ final TaskCompletionSource <Void > tcs = new TaskCompletionSource <>();
1190
1190
return perform (new Callable <Task <List <T >>>() {
1191
1191
@ Override
1192
1192
public Task <List <T >> call () throws Exception {
1193
1193
return getUserAsync (state ).onSuccessTask (new Continuation <ParseUser , Task <List <T >>>() {
1194
1194
@ Override
1195
1195
public Task <List <T >> then (Task <ParseUser > task ) throws Exception {
1196
1196
final ParseUser user = task .getResult ();
1197
- return findAsync (state , user , cts .getTask ());
1197
+ return findAsync (state , user , tcs .getTask ());
1198
1198
}
1199
1199
});
1200
1200
}
1201
- });
1201
+ }, tcs );
1202
1202
}
1203
1203
1204
1204
/* package */ Task <List <T >> findAsync (State <T > state , ParseUser user , Task <Void > cancellationToken ) {
@@ -1254,18 +1254,19 @@ public Task<T> call(State<T> state, ParseUser user, Task<Void> cancellationToken
1254
1254
}
1255
1255
1256
1256
private Task <T > getFirstAsync (final State <T > state ) {
1257
+ final TaskCompletionSource <Void > tcs = new TaskCompletionSource <>();
1257
1258
return perform (new Callable <Task <T >>() {
1258
1259
@ Override
1259
1260
public Task <T > call () throws Exception {
1260
1261
return getUserAsync (state ).onSuccessTask (new Continuation <ParseUser , Task <T >>() {
1261
1262
@ Override
1262
1263
public Task <T > then (Task <ParseUser > task ) throws Exception {
1263
1264
final ParseUser user = task .getResult ();
1264
- return getFirstAsync (state , user , cts .getTask ());
1265
+ return getFirstAsync (state , user , tcs .getTask ());
1265
1266
}
1266
1267
});
1267
1268
}
1268
- });
1269
+ }, tcs );
1269
1270
}
1270
1271
1271
1272
private Task <T > getFirstAsync (State <T > state , ParseUser user , Task <Void > cancellationToken ) {
@@ -1331,18 +1332,19 @@ public Task<Integer> call(State<T> state, ParseUser user, Task<Void> cancellatio
1331
1332
}
1332
1333
1333
1334
private Task <Integer > countAsync (final State <T > state ) {
1335
+ final TaskCompletionSource <Void > tcs = new TaskCompletionSource <>();
1334
1336
return perform (new Callable <Task <Integer >>() {
1335
1337
@ Override
1336
1338
public Task <Integer > call () throws Exception {
1337
1339
return getUserAsync (state ).onSuccessTask (new Continuation <ParseUser , Task <Integer >>() {
1338
1340
@ Override
1339
1341
public Task <Integer > then (Task <ParseUser > task ) throws Exception {
1340
1342
final ParseUser user = task .getResult ();
1341
- return countAsync (state , user , cts .getTask ());
1343
+ return countAsync (state , user , tcs .getTask ());
1342
1344
}
1343
1345
});
1344
1346
}
1345
- });
1347
+ }, tcs );
1346
1348
}
1347
1349
1348
1350
private Task <Integer > countAsync (State <T > state , ParseUser user , Task <Void > cancellationToken ) {
@@ -1500,6 +1502,8 @@ private <TResult> Task<TResult> doCacheThenNetwork(
1500
1502
final ParseQuery .State <T > state ,
1501
1503
final ParseCallback2 <TResult , ParseException > callback ,
1502
1504
final CacheThenNetworkCallable <T , Task <TResult >> delegate ) {
1505
+
1506
+ final TaskCompletionSource <Void > tcs = new TaskCompletionSource <>();
1503
1507
return perform (new Callable <Task <TResult >>() {
1504
1508
@ Override
1505
1509
public Task <TResult > call () throws Exception {
@@ -1514,21 +1518,21 @@ public Task<TResult> then(Task<ParseUser> task) throws Exception {
1514
1518
.setCachePolicy (CachePolicy .NETWORK_ONLY )
1515
1519
.build ();
1516
1520
1517
- Task <TResult > executionTask = delegate .call (cacheState , user , cts .getTask ());
1521
+ Task <TResult > executionTask = delegate .call (cacheState , user , tcs .getTask ());
1518
1522
executionTask = ParseTaskUtils .callbackOnMainThreadAsync (executionTask , callback );
1519
1523
return executionTask .continueWithTask (new Continuation <TResult , Task <TResult >>() {
1520
1524
@ Override
1521
1525
public Task <TResult > then (Task <TResult > task ) throws Exception {
1522
1526
if (task .isCancelled ()) {
1523
1527
return task ;
1524
1528
}
1525
- return delegate .call (networkState , user , cts .getTask ());
1529
+ return delegate .call (networkState , user , tcs .getTask ());
1526
1530
}
1527
1531
});
1528
1532
}
1529
1533
});
1530
1534
}
1531
- });
1535
+ }, tcs );
1532
1536
}
1533
1537
1534
1538
private interface CacheThenNetworkCallable <T extends ParseObject , TResult > {
0 commit comments