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