[aerogear-dev] AGDROID-11

Summers Pittman supittma at redhat.com
Thu Aug 15 13:46:09 EDT 2013


On 08/15/2013 12:23 PM, Yavuz Selim YILMAZ wrote:
> So, if I get it right, each pipe will have it's runnable list. When 
> the pipe is cancelled, it'll remove all waiting runnable's from 
> threadpoolexecutor, and cancel the ones currently running. Am I right?
Not exactly.  When the Runnable is finished, it removes itself form the 
thread pool executor.  You will need some other collection which is 
modified when a pipe operation begins or completes.
>
> If so, then what'd be the proper way of cleaning the successfully 
> completed runnable's from pipe's list?
For example RestAdapter.java#131:

if (exception == null) {
   runnableCollection.remove(this);
   callback.onSuccess(this.result);
} else {
   runnableCollection.remove(this);
   callback.onFailure(exception);
}

Would be my first guess.

>
> For the loader part, I'll check on how to implement your suggestion,
>
> Regards,
>
> ---
> Yavuz Selim Yilmaz
> SUNY at Buffalo
> Computer Science and Engineering
> PhD Candidate
>
> On Aug 15, 2013, at 10:54 AM, Summers Pittman <supittma at redhat.com 
> <mailto:supittma at redhat.com>> wrote:
>
>> Wow you don't make this easy on us ;)
>>
>> Killing the thread/thread pool is probably a bad idea. It may be 
>> cleaner to make the anonymous runner classes in RestAdatper into 
>> static classes which implement Runnable and provide a cancel method.  
>> In the RestAdapter you could do some bookkeeping to provide 
>> references to the Threads so you can call cancel on each one which is 
>> currently running.
>>
>> Also, the LoaderAdapters will need a different solution (but theirs 
>> is MUCH easier, you just call cancelLoader and implement onCancel in 
>> the Loader implementations).
>>
>> Summers
>>
>> PS bookkeeping is one of my favorite words.
>>
>>
>> On 08/14/2013 03:36 PM, Yavuz Selim YILMAZ wrote:
>>> Hi all,
>>>
>>> I am working on AGDROID-11 
>>> [https://issues.jboss.org/browse/AGDROID-11]. As suggested on the 
>>> JIRA, I started with investigating how AeroGear iOS handles pipe 
>>> cancel operation.
>>>
>>> -----------------------------------------------------------------------
>>> ---- 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 ---
>>> [1] 
>>> https://github.com/aerogear/aerogear-ios/blob/master/AeroGear-iOS/AeroGear-iOS/pipeline/AGRESTPipe.m#L283
>>> [2] 
>>> https://github.com/aerogear/aerogear-ios/blob/master/AeroGear-iOS/AeroGear-iOS/pipeline/AGRESTPipe.m#L71
>>> [3] 
>>> https://github.com/aerogear/aerogear-ios/blob/master/AeroGear-iOS/AeroGear-iOS/core/AGHttpClient.h#L21
>>> [4] 
>>> https://github.com/AFNetworking/AFNetworking/blob/master/AFNetworking/AFHTTPClient.m#L189
>>> [5] 
>>> http://developer.apple.com/library/ios/DOCUMENTATION/Cocoa/Reference/NSOperationQueue_class/Reference/Reference.html#//apple_ref/occ/instm/NSOperationQueue/cancelAllOperations
>>> [6] 
>>> http://developer.apple.com/library/mac/documentation/Cocoa/Reference/NSOperation_class/Reference/Reference.html#//apple_ref/doc/uid/TP40004591-RH2-SW18
>>> [7] 
>>> https://github.com/aerogear/aerogear-ios/blob/master/AeroGear-iOS/AeroGear-iOS/core/AGHttpClient.m#L158
>>> [8] 
>>> https://github.com/AFNetworking/AFNetworking/blob/master/AFNetworking/AFHTTPClient.m#L554
>>> [9] 
>>> https://github.com/AFNetworking/AFNetworking/blob/master/AFNetworking/AFHTTPClient.m#L560
>>> [10] 
>>> https://github.com/AFNetworking/AFNetworking/blob/master/AFNetworking/AFHTTPRequestOperation.h#L29
>>> [11] 
>>> https://github.com/AFNetworking/AFNetworking/blob/master/AFNetworking/AFURLConnectionOperation.m#L548
>>> [12] 
>>> http://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/Reference/Reference.html#//apple_ref/occ/instm/NSURLConnection/cancel
>>> [13] 
>>> https://github.com/AFNetworking/AFNetworking/blob/master/AFNetworking/AFURLConnectionOperation.m#L573
>>> [14] 
>>> https://github.com/AFNetworking/AFNetworking/blob/master/AFNetworking/AFURLConnectionOperation.m#L760
>>> [15] 
>>> https://github.com/AFNetworking/AFNetworking/blob/master/AFNetworking/AFURLConnectionOperation.m#L540
>>>
>>> [16] 
>>> https://github.com/aerogear/aerogear-android/blob/master/src/org/jboss/aerogear/android/impl/pipeline/RestAdapter.java#L119
>>> [17] 
>>> https://github.com/aerogear/aerogear-android/blob/master/src/org/jboss/aerogear/android/impl/pipeline/RestAdapter.java#L146
>>> [18] 
>>> https://github.com/aerogear/aerogear-android/blob/master/src/org/jboss/aerogear/android/impl/pipeline/RestAdapter.java#L170
>>> [19] 
>>> https://github.com/aerogear/aerogear-android/blob/master/src/org/jboss/aerogear/android/impl/pipeline/RestAdapter.java#L198
>>> [20] 
>>> https://github.com/aerogear/aerogear-android/blob/master/src/org/jboss/aerogear/android/impl/pipeline/RestAdapter.java#L50
>>> [21] 
>>> http://developer.android.com/reference/java/util/concurrent/ThreadPoolExecutor.html#shutdownNow() 
>>> <http://developer.android.com/reference/java/util/concurrent/ThreadPoolExecutor.html#shutdownNow%28%29>
>>> [22] 
>>> http://developer.android.com/reference/java/util/concurrent/AbstractExecutorService.html#submit(java.lang.Runnable) 
>>> <http://developer.android.com/reference/java/util/concurrent/AbstractExecutorService.html#submit%28java.lang.Runnable%29>
>>> [23] 
>>> http://developer.android.com/reference/java/util/concurrent/Future.html#cancel(boolean) 
>>> <http://developer.android.com/reference/java/util/concurrent/Future.html#cancel%28boolean%29>
>>>
>>> ---
>>> Yavuz Selim Yilmaz
>>> SUNY at Buffalo
>>> Computer Science and Engineering
>>> PhD Candidate
>>>
>>>
>>>
>>> _______________________________________________
>>> aerogear-dev mailing list
>>> aerogear-dev at lists.jboss.org
>>> https://lists.jboss.org/mailman/listinfo/aerogear-dev
>>
>> _______________________________________________
>> aerogear-dev mailing list
>> aerogear-dev at lists.jboss.org <mailto:aerogear-dev at lists.jboss.org>
>> https://lists.jboss.org/mailman/listinfo/aerogear-dev
>
>
>
> _______________________________________________
> aerogear-dev mailing list
> aerogear-dev at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/aerogear-dev

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/aerogear-dev/attachments/20130815/30bb1374/attachment-0001.html 


More information about the aerogear-dev mailing list