Hi all,
-----------------------------------------------------------------------
---- Skip if you don't want to verify my iOS tracking ----
-----------------------------------------------------------------------
------------------------------ Start
---------------------------------
-----------------------------------------------------------------------
First, here is what I could track on the iOS side (please
correct me if there's any mistake):
- AGRESTPipe cancel method simply calls the
cancelAllOperations on its restClient's operationQueue [1].
- AGRESTPipe's restClient is a AGHttpClient [2].
- AGHttpClient is a AFHttpClient [3].
- AFHttpClient's operationQueue is a NSOperationQueue [4].
- Calling cancelAllOperations on NSOperationQueue sends
cancel message to all Operations in the queue [5]. If the
operation is still in the queue (waiting to be executed), they
are not being executed. If the operation is alread started to
it's execution, it's up to the "Operation" how to respond to
cancel message.
- Sending cancel message to operations sets their isCancelled
flag. Any custom NSOperation extension is recommended to handle
this cancel operation [6].
- AGHttpClient creates the operation by calling
HTTPRequestOperationWithRequest [7], which is AFHttpClient
method. It creates either custom (AFImage, AFJSON,
AFPropertyList, AFXML) operation [8] or AFHttpRequestOperation
[9]. All custom operations are AFHttpRequestOperation, which is
a AFURLConnectionOperation [10].
- AFURLConnectionOperation implements cancel method [11] and
simply cancels the operation's NSURLConnection, the connection
is cancelled and no delegate is called [12].
- Then AFURLConnectionOperation calls its delegate method
manually to finish the operation [13].
- The delegate handles the case [14] and finishes the
operation [15].
-----------------------------------------------------------------------
------------------------------- End
---------------------------------
-----------------------------------------------------------------------
---- Skip if you don't want to verify my iOS tracking ----
-----------------------------------------------------------------------
Simply, what I understand is, operation itself is responsible
to handle the cancel message sent by any pipe implementation.
And on the Android side, the operations are runnables [16, 17,
18, 19] as far as I could interpret. So, these runnables should
be able to handle cancel messages which means they should catch
or throw the thrown InterruptedException.
So, the problem is, find a way to send cancel message to the
tasks, and handle the cancel message on the tasks.
HOW TO SEND CANCEL MESSAGE TO THE TASKS?
1ST PROPOSAL:
RestAdapter is using ThreadPoolExecutor [20]. So, one way to
send cancel message to all running and queued runnables is to
call shutDownNow on the ThreadPoolExecutor [21]. It has some
limitations. First, shut down destroys the ThreadPoolExecutor,
so it needs to be recreated. Second, the current
ThredPoolExecutor is static, means it will cancel all pipes if
it is shut down, so it needs to be an instance variable instead
of static.
2ND PROPOSAL:
Instead of calling THREAD_POOL_EXECUTOR.execute(), if we call
THREAD_POOL_EXECUTOR.submit() [22], then it returns a Future
representing the task. Future has cancel() [23], which prevents
running the task if it is not started, and interrupts the task
if it is currently running. Therefore, if we have a collection
of <Future> in RestAdapter (i.e. pipe), then we can cancel
the operations by iterating over the collection and calling
cancel() on each Future. In this case, at some point, we need to
clean <Future> collection to get rid of the already
cancelled tasks.
HOW TO HANDLE THE CANCEL MESSAGE ON THE TASKS?
I could only come up with a single solution, which is, adding
another catch block to each of the runnables [16, 17, 18, 19].
Here is what it will look like:
try {
this.result = ...
} catch (InterruptedException e) {
return; // don't call the callbacks, may need to check
the cause of the interrupt???
} catch (Exception e) {
Log.e(TAG, e.getMessage(), e);
this.exception = e;
}
So, I would like to hear what you think about my solution,
and if you have any corrections, better solutions, comments,
anything... All are most welcome.
Kind regards,
--- REFERENCES ---
---
Yavuz Selim Yilmaz
SUNY at Buffalo
Computer Science and
Engineering
PhD Candidate
_______________________________________________
aerogear-dev mailing list
aerogear-dev@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/aerogear-dev