You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by GitBox <gi...@apache.org> on 2018/11/05 08:18:53 UTC

[GitHub] ECNU3D opened a new issue #452: [Discussion]Why not use nsoperation queue instead of dispatch queue in CDVCommandDelegateImpl.m?

ECNU3D opened a new issue #452: [Discussion]Why not use nsoperation queue instead of dispatch queue in CDVCommandDelegateImpl.m?
URL: https://github.com/apache/cordova-ios/issues/452
 
 
   I'm using cordova 8.0.0 now to develop my hybrid application. I'm writing some plugin api function as followed
   ```
   func pluginAPI( _ command: CDVInvokedUrlCommand ){
       // parameter process
       commandDelegate.run( inBackground: {() -> Void in
           var pluginResult : CDVPluginResult;
           // some logic to handle result
           self.commandDelegate.send( pluginResult, callbackId: command.callbackId );
       } );
   }
   ```
   
   In my scenario, as I'm delivering the plugin to different teams, I can't control how people will call it. In some cases, people will use some **Promise.all** in the front-end to call the pluginAPI function for more than 100 times.
   
   Here brings the problem, I notice that the implementation of above **run** function is as followed:
   ```
   - (void)runInBackground:(void (^)())block
   {
       dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), block);
   }
   ```
   
   It's using the GCD global concurrent queue directly, and I don't have an easy way to control the concurrent number of tasks. If the user calls the API more than 64 times(the maximum number of threads of GCD according to some documents), it will spawn up to 64 threads, and block other dispatch queue if I'm trying to dispatch any concurrent task. 
   
   For example, in my plugin, I've an array to store some data, which needs to be thread safe. So I implemented some read write lock according to the blog: http://basememara.com/creating-thread-safe-arrays-in-swift/ based on GCD. 
   ```
   let queue = DispatchQueue(label: "MyArrayQueue", attributes: .concurrent)
    
   queue.async(flags: .barrier) {
     // Mutate array here
   }
    
   queue.sync() {
     // Read array here
   }
   ```
   In my code, I have some operation like
   ```
   queue.sync()
   queue.async()
   ```
   The combination of queue.async/queue.sync call will actually create deadlock when pluginAPI calls already reach the maximum number of thread limit of GCD. It won't in normal cases.
   
   I assume that it might be a common challenge in cordova plugin development, and I'm not sure what's the best practice here as we don't have an easy control of how javascript code calls the plugin API. One potential solution might be use the NSOperation to control the maximum concurrent number of tasks initiated by plugin API layer, which will leave the space for the following function in the execution chain to dispatch some async/sync to the queue. On the other hand, change the **DispatchQueue** from concurrent to serial will also fix the problem.
   
   Any suggestions or ideas are welcomed!

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org