Concurrency CS 442: Mobile App Development Michael Saelee - - PowerPoint PPT Presentation

concurrency
SMART_READER_LITE
LIVE PREVIEW

Concurrency CS 442: Mobile App Development Michael Saelee - - PowerPoint PPT Presentation

Concurrency CS 442: Mobile App Development Michael Saelee <lee@iit.edu> Computer Science Science note: iOS devices are now (mostly) multi-core; i.e., concurrency may allow for real performance gains! Computer Science Science but


slide-1
SLIDE 1

Concurrency

CS 442: Mobile App Development Michael Saelee <lee@iit.edu>

slide-2
SLIDE 2

Computer Science Science

note: iOS devices are now (mostly) 
 multi-core; i.e., concurrency may allow for real performance gains!

slide-3
SLIDE 3

Computer Science Science

but the more common incentive is to improve interface responsiveness i.e., by taking lengthy computations off the critical path of UI updates

slide-4
SLIDE 4

Computer Science Science

Mechanisms

  • Threads (traditional)
  • Grand Central Dispatch
  • Dispatch queues/sources
  • Operation Queues
slide-5
SLIDE 5

Computer Science Science

Threads:

  • Cocoa threads (NSThread)
  • POSIX threads
  • if you do use PThreads, spawn a single

NSThread first! (way too low level!)

slide-6
SLIDE 6

Computer Science Science public class NSThread : NSObject { public class func currentThread() -> NSThread public class func detachNewThreadSelector(selector: Selector, toTarget target: AnyObject, withObject argument: AnyObject?) public class func sleepForTimeInterval(ti: NSTimeInterval) public class func exit() public class func isMainThread() -> Bool // reports whether current thread is main public class func mainThread() -> NSThread public convenience init(target: AnyObject, selector: Selector, object argument: AnyObject?) public func cancel() public func start() public func main() // thread body method }

slide-7
SLIDE 7

Computer Science Science extension NSObject { public func performSelectorInBackground(aSelector: Selector, 
 withObject arg: AnyObject?) }

slide-8
SLIDE 8

Computer Science Science let thread = NSThread(target: self, selector: #selector(self.someMethod(_:)), object: arg) thread.start() NSThread.detachNewThreadSelector(#selector(self.someMethod(_:)), toTarget: self, withObject: arg)

self.performSelectorInBackground(#selector(self.someMethod(_:)), withObject: arg)

slide-9
SLIDE 9

Computer Science Science

we often want threads to stick around and process multiple work items — design pattern: thread work queue

slide-10
SLIDE 10

Computer Science Science

var workQueue = [AnyObject]() workQueue.append("hello") workQueue.append("world") func threadMain(queue: [AnyObject]) { while !NSThread.currentThread().cancelled { if workQueue.count == 0 { NSThread.sleepForTimeInterval(1.0) continue } let workItem = workQueue.removeFirst() print(workItem) } } self.performSelectorInBackground(#selector(self.threadMain(_:)), 
 withObject: workQueue)

slide-11
SLIDE 11

Computer Science Science

possible extensions:

  • more than one work queue
  • timed (periodic/delayed) work items
  • notifying observers of work completion
  • monitoring of input devices

(asynchronous I/O)

slide-12
SLIDE 12

Computer Science Science

all this and more provided by NSRunLoop — encapsulates multiple input sources & timers, and provides API to dequeue and process work items in the current thread

slide-13
SLIDE 13

Computer Science Science

each work source is associated with one or more run loop modes

  • when executing a run loop, can specify

mode to narrow down work sources

slide-14
SLIDE 14

Computer Science Science

@interface NSRunLoop : NSObject + (NSRunLoop *)currentRunLoop; // enter a permanent run loop, processing items from sources


  • (void)run; 


// process timers and/or one input source before `limitDate'


  • (void)runUntilDate:(NSDate *)limitDate;


 // like runUntilDate, but only for sources in `mode'


  • (BOOL)runMode:(NSString *)mode beforeDate:(NSDate *)limitDate;

@end

slide-15
SLIDE 15

Computer Science Science

  • (void)threadMain {

@autoreleasepool { while (![[NSThread currentThread] isCancelled]) { // process a run loop input source (and/or timers) [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; // now do other work before processing run loop sources again NSLog(@"Run loop iteration complete"); } } }

slide-16
SLIDE 16

Computer Science Science

Built in support for delegating work between threads, and for scheduling 
 timed events:

@interface NSObject (NSDelayedPerforming)

  • (void)performSelector:(SEL)aSelector 


withObject:(id)anArgument 
 afterDelay:(NSTimeInterval)delay; @end @interface NSObject (NSThreadPerformAdditions)

  • (void)performSelector:(SEL)aSelector 

  • nThread:(NSThread *)thr 


withObject:(id)arg 
 waitUntilDone:(BOOL)wait;
 @end

slide-17
SLIDE 17

Computer Science Science

  • (void)blinkView {

self.blinkerView.backgroundColor = [UIColor whiteColor]; [UIView animateWithDuration:1.0 animations:^{ self.blinkerView.backgroundColor = [UIColor redColor]; }]; // not a recursive call! [self performSelector:@selector(blinkView) withObject:nil afterDelay:3.0]; }

slide-18
SLIDE 18

Computer Science Science

the main run loop: 
 [NSRunLoop mainRunLoop]

  • this is where everything’s been

happening (until now)!

  • event handling, UI drawing, etc.
slide-19
SLIDE 19

Computer Science Science

event handling can be handed off to other threads, but all UI updates must be performed by the main thread!

slide-20
SLIDE 20

Computer Science Science

dilemma: if UI updates must happen in main thread, how can UI events be processed in secondary threads?

slide-21
SLIDE 21

Computer Science Science

Main Queue execution

Touch Draw Motion Web response needs to perform lengthy processing … but would hold up the main thread if done here

slide-22
SLIDE 22

Computer Science Science

Main Queue execution

Touch Draw Motion Web response

Secondary (background) Queue execution

slide-23
SLIDE 23

Computer Science Science

Main Queue execution

Draw Motion Web response

Secondary (background) Queue execution

Processing Touch

slide-24
SLIDE 24

Computer Science Science

Main Queue execution

Motion Web response

Secondary (background) Queue execution

Processing Draw

slide-25
SLIDE 25

Computer Science Science

Main Queue execution

Web response

Secondary (background) Queue execution

Processing

slide-26
SLIDE 26

Computer Science Science

Main Queue execution

Web response

Secondary (background) Queue execution

Draw Processing

slide-27
SLIDE 27

Computer Science Science

Main Queue execution Secondary (background) Queue execution

Draw

slide-28
SLIDE 28

Computer Science Science

i.e., event processing is outsourced to secondary threads (via run loop); UI updates are performed in the main thread (via main run loop)

slide-29
SLIDE 29

Computer Science Science

@interface NSObject (NSThreadPerformAdditions)

  • (void)performSelectorOnMainThread:(SEL)aSelector 


withObject:(id)arg 
 waitUntilDone:(BOOL)wait; @end @interface NSRunLoop : NSObject + (NSRunLoop *)mainRunLoop; @end interface NSThread : NSObject + (NSThread *)mainThread; @end

Convenience APIs for accessing the main thread / run loop:

slide-30
SLIDE 30

Computer Science Science

  • (IBAction)action:(id)sender forEvent:(UIEvent *)event

{ // outsource event handling to background thread [self performSelector:@selector(processEvent:)

  • nThread:processingThread

withObject:event waitUntilDone:NO]; }

  • (void)processEvent:(UIEvent *)event

{ // process event (in background thread) id result = lengthyProcessing(event); // queue UI update with result in main run loop [self performSelectorOnMainThread:@selector(updateUI:) 
 withObject:result 
 waitUntilDone:NO]; }

  • (void)updateUI:(id)result

{ // update the UI (happens in the main thread) self.label.text = [result description]; }

slide-31
SLIDE 31

Computer Science Science

important: run loops are not thread safe! i.e., don’t access other threads’ run loops directly (use performSelector…)

slide-32
SLIDE 32

Computer Science Science

but manual threading is old school! a host of issues:

  • reusing threads (thread pools)
  • interdependencies & synchronization
  • ideal number of threads?
slide-33
SLIDE 33

Computer Science Science

Grand Central Dispatch is a facility that abstracts away thread-level concurrency with a queue-based API

slide-34
SLIDE 34

Computer Science Science

C API for system-managed concurrency (note: GCD is open sourced by Apple!)

slide-35
SLIDE 35

Computer Science Science

  • 1. Dispatch queues
  • 2. Dispatch sources
slide-36
SLIDE 36

Computer Science Science

void dispatch_async(dispatch_queue_t queue,
 dispatch_block_t block); void dispatch_async_f(dispatch_queue_t queue,
 void *context,
 dispatch_function_t work); void dispatch_sync(dispatch_queue_t queue,
 dispatch_block_t block); void dispatch_sync_f(dispatch_queue_t queue,
 void *context,
 dispatch_function_t work); void dispatch_apply(size_t iterations,
 dispatch_queue_t queue,
 void (^block)(size_t));

slide-37
SLIDE 37

Computer Science Science

// serially process work items for (int i=0; i<N_WORK_ITEMS; i++) { results[i] = process_data(data[i]); } summarize(results, N_WORK_ITEMS); dispatch_queue_t queue = dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_HIGH, 0); // process work items in blocks added to queue dispatch_apply(N_WORK_ITEMS, queue, ^(size_t i){ // block code automagically run in threads results[i] = process_data(data[i]); }); summarize(results, N_WORK_ITEMS);

(mini map-reduce)

slide-38
SLIDE 38

Computer Science Science

dispatch queues are backed by threads 
 (# threads determined by system) main & global queues created for every application; can create more if needed

slide-39
SLIDE 39

Computer Science Science

dispatch sources automatically monitor different input sources (e.g., timers, file descriptors, system events) … and schedule blocks on dispatch queues

slide-40
SLIDE 40

Computer Science Science

dispatch_queue_t queue = dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_HIGH, 0); dispatch_source_t timer = dispatch_source_create(
 DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue); dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 0.0); dispatch_source_set_event_handler(timer, ^{ NSLog(@"Beep!"); }); dispatch_resume(timer); 12:28:55.184 QueueTest[72282:1303] Beep! 12:28:56.184 QueueTest[72282:1a03] Beep! 12:28:57.184 QueueTest[72282:1a03] Beep! 12:28:58.184 QueueTest[72282:1a03] Beep! 12:28:59.184 QueueTest[72282:1a03] Beep!

slide-41
SLIDE 41

Computer Science Science

but we rarely use GCD directly

  • low level (ugly) C API
  • source creation is especially irritating
slide-42
SLIDE 42

Computer Science Science

Operation Queue (Cocoa wrapper for GCD)

slide-43
SLIDE 43

Computer Science Science

NSOperationQueue manages operation execution, prioritization, and inter-dependencies

slide-44
SLIDE 44

Computer Science Science

Tasks = NSOperation

slide-45
SLIDE 45

Computer Science Science

concrete subclasses:

  • NSInvocationOperation
  • NSBlockOperation
slide-46
SLIDE 46

Computer Science Science

NSOperationQueue *queue = [[NSOperationQueue alloc] init]; [queue setMaxConcurrentOperationCount:2]; // amount of concurrency 
 NSInvocationOperation *op;


  • p = [[NSInvocationOperation alloc] initWithTarget:self


selector:@selector(taskMethod:)


  • bject:nil];


 NSBlockOperation *bop = [NSBlockOperation blockOperationWithBlock:^{
 // task body
 }]; 
 [bop addExecutionBlock:^{
 // can have multiple concurrent blocks in this operation!
 }]; 
 [bop setCompletionBlock:^{
 // this is run when all execution blocks complete
 }]; 
 [bop addDependency:op]; // bop needs op to complete first (beware cycles!) 
 [queue addOperation:op];
 [queue addOperation:bop]; 
 [queue addOperationWithBlock:^{
 // easier way to schedule a single block as an operation
 }];

slide-47
SLIDE 47

Computer Science Science

but we run into the same issue as before:

  • operation queues are backed by 1+

thread(s), and only the main thread can perform UI updates

  • how to return control to main thread

from operation queues?

slide-48
SLIDE 48

Computer Science Science

as with run loops, currentQueue, mainQueue access specific op-queues — backed by current and main threads

slide-49
SLIDE 49

Computer Science Science

solution:

  • schedule background operations in

secondary queues

  • background operations schedule UI

updates in main queue

slide-50
SLIDE 50

Computer Science Science

  • (IBAction)action:(id)sender forEvent:(UIEvent *)event

[operationQueue addOperationWithBlock:^{ // process event (in background thread) id result = lengthyProcessing(event); [[NSOperationQueue mainQueue] addOperationWithBlock:^{ // update the UI (happens in the main thread) self.label.text = [result description]; }]; }]; }

slide-51
SLIDE 51

Computer Science Science

  • (IBAction)action:(id)sender forEvent:(UIEvent *)event

{ // outsource event handling to background thread [self performSelector:@selector(processEvent:)

  • nThread:processingThread

withObject:event waitUntilDone:NO]; }

  • (void)processEvent:(UIEvent *)event

{ // process event (in background thread) id result = lengthyProcessing(event); // queue UI update with result in main run loop [self performSelectorOnMainThread:@selector(updateUI:) 
 withObject:result 
 waitUntilDone:NO]; }

  • (void)updateUI:(id)result

{ // update the UI (happens in the main thread) self.label.text = [result description]; }

(compare to:)