OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #import "base/message_loop/message_pump_mac.h" | 5 #import "base/message_loop/message_pump_mac.h" |
6 | 6 |
7 #include <dlfcn.h> | 7 #include <dlfcn.h> |
8 #import <Foundation/Foundation.h> | 8 #import <Foundation/Foundation.h> |
9 | 9 |
10 #include <limits> | 10 #include <limits> |
11 | 11 |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/mac/call_with_eh_frame.h" |
13 #include "base/mac/scoped_cftyperef.h" | 14 #include "base/mac/scoped_cftyperef.h" |
14 #include "base/message_loop/timer_slack.h" | 15 #include "base/message_loop/timer_slack.h" |
15 #include "base/run_loop.h" | 16 #include "base/run_loop.h" |
16 #include "base/time/time.h" | 17 #include "base/time/time.h" |
17 | 18 |
18 #if !defined(OS_IOS) | 19 #if !defined(OS_IOS) |
19 #import <AppKit/AppKit.h> | 20 #import <AppKit/AppKit.h> |
20 #endif // !defined(OS_IOS) | 21 #endif // !defined(OS_IOS) |
21 | 22 |
22 namespace base { | 23 namespace base { |
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
293 // In order to establish the proper priority in which work and delayed work | 294 // In order to establish the proper priority in which work and delayed work |
294 // are processed one for one, the timer used to schedule delayed work must | 295 // are processed one for one, the timer used to schedule delayed work must |
295 // signal a CFRunLoopSource used to dispatch both work and delayed work. | 296 // signal a CFRunLoopSource used to dispatch both work and delayed work. |
296 CFRunLoopSourceSignal(self->work_source_); | 297 CFRunLoopSourceSignal(self->work_source_); |
297 } | 298 } |
298 | 299 |
299 // Called from the run loop. | 300 // Called from the run loop. |
300 // static | 301 // static |
301 void MessagePumpCFRunLoopBase::RunWorkSource(void* info) { | 302 void MessagePumpCFRunLoopBase::RunWorkSource(void* info) { |
302 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); | 303 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); |
303 self->RunWork(); | 304 base::mac::CallWithEHFrame(^{ |
| 305 self->RunWork(); |
| 306 }); |
304 } | 307 } |
305 | 308 |
306 // Called by MessagePumpCFRunLoopBase::RunWorkSource. | 309 // Called by MessagePumpCFRunLoopBase::RunWorkSource. |
307 bool MessagePumpCFRunLoopBase::RunWork() { | 310 bool MessagePumpCFRunLoopBase::RunWork() { |
308 if (!delegate_) { | 311 if (!delegate_) { |
309 // This point can be reached with a NULL delegate_ if Run is not on the | 312 // This point can be reached with a NULL delegate_ if Run is not on the |
310 // stack but foreign code is spinning the CFRunLoop. Arrange to come back | 313 // stack but foreign code is spinning the CFRunLoop. Arrange to come back |
311 // here when a delegate is available. | 314 // here when a delegate is available. |
312 delegateless_work_ = true; | 315 delegateless_work_ = true; |
313 return false; | 316 return false; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
352 CFRunLoopSourceSignal(work_source_); | 355 CFRunLoopSourceSignal(work_source_); |
353 } | 356 } |
354 | 357 |
355 return resignal_work_source; | 358 return resignal_work_source; |
356 } | 359 } |
357 | 360 |
358 // Called from the run loop. | 361 // Called from the run loop. |
359 // static | 362 // static |
360 void MessagePumpCFRunLoopBase::RunIdleWorkSource(void* info) { | 363 void MessagePumpCFRunLoopBase::RunIdleWorkSource(void* info) { |
361 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); | 364 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); |
362 self->RunIdleWork(); | 365 base::mac::CallWithEHFrame(^{ |
| 366 self->RunIdleWork(); |
| 367 }); |
363 } | 368 } |
364 | 369 |
365 // Called by MessagePumpCFRunLoopBase::RunIdleWorkSource. | 370 // Called by MessagePumpCFRunLoopBase::RunIdleWorkSource. |
366 bool MessagePumpCFRunLoopBase::RunIdleWork() { | 371 bool MessagePumpCFRunLoopBase::RunIdleWork() { |
367 if (!delegate_) { | 372 if (!delegate_) { |
368 // This point can be reached with a NULL delegate_ if Run is not on the | 373 // This point can be reached with a NULL delegate_ if Run is not on the |
369 // stack but foreign code is spinning the CFRunLoop. Arrange to come back | 374 // stack but foreign code is spinning the CFRunLoop. Arrange to come back |
370 // here when a delegate is available. | 375 // here when a delegate is available. |
371 delegateless_idle_work_ = true; | 376 delegateless_idle_work_ = true; |
372 return false; | 377 return false; |
(...skipping 13 matching lines...) Expand all Loading... |
386 CFRunLoopSourceSignal(idle_work_source_); | 391 CFRunLoopSourceSignal(idle_work_source_); |
387 } | 392 } |
388 | 393 |
389 return did_work; | 394 return did_work; |
390 } | 395 } |
391 | 396 |
392 // Called from the run loop. | 397 // Called from the run loop. |
393 // static | 398 // static |
394 void MessagePumpCFRunLoopBase::RunNestingDeferredWorkSource(void* info) { | 399 void MessagePumpCFRunLoopBase::RunNestingDeferredWorkSource(void* info) { |
395 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); | 400 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); |
396 self->RunNestingDeferredWork(); | 401 base::mac::CallWithEHFrame(^{ |
| 402 self->RunNestingDeferredWork(); |
| 403 }); |
397 } | 404 } |
398 | 405 |
399 // Called by MessagePumpCFRunLoopBase::RunNestingDeferredWorkSource. | 406 // Called by MessagePumpCFRunLoopBase::RunNestingDeferredWorkSource. |
400 bool MessagePumpCFRunLoopBase::RunNestingDeferredWork() { | 407 bool MessagePumpCFRunLoopBase::RunNestingDeferredWork() { |
401 if (!delegate_) { | 408 if (!delegate_) { |
402 // This point can be reached with a NULL delegate_ if Run is not on the | 409 // This point can be reached with a NULL delegate_ if Run is not on the |
403 // stack but foreign code is spinning the CFRunLoop. There's no sense in | 410 // stack but foreign code is spinning the CFRunLoop. There's no sense in |
404 // attempting to do any work or signalling the work sources because | 411 // attempting to do any work or signalling the work sources because |
405 // without a delegate, work is not possible. | 412 // without a delegate, work is not possible. |
406 return false; | 413 return false; |
(...skipping 26 matching lines...) Expand all Loading... |
433 CFRunLoopSourceSignal(nesting_deferred_work_source_); | 440 CFRunLoopSourceSignal(nesting_deferred_work_source_); |
434 } | 441 } |
435 } | 442 } |
436 | 443 |
437 // Called from the run loop. | 444 // Called from the run loop. |
438 // static | 445 // static |
439 void MessagePumpCFRunLoopBase::PreWaitObserver(CFRunLoopObserverRef observer, | 446 void MessagePumpCFRunLoopBase::PreWaitObserver(CFRunLoopObserverRef observer, |
440 CFRunLoopActivity activity, | 447 CFRunLoopActivity activity, |
441 void* info) { | 448 void* info) { |
442 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); | 449 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); |
| 450 base::mac::CallWithEHFrame(^{ |
| 451 // Attempt to do some idle work before going to sleep. |
| 452 self->RunIdleWork(); |
443 | 453 |
444 // Attempt to do some idle work before going to sleep. | 454 // The run loop is about to go to sleep. If any of the work done since it |
445 self->RunIdleWork(); | 455 // started or woke up resulted in a nested run loop running, |
446 | 456 // nesting-deferred work may have accumulated. Schedule it for processing |
447 // The run loop is about to go to sleep. If any of the work done since it | 457 // if appropriate. |
448 // started or woke up resulted in a nested run loop running, | 458 self->MaybeScheduleNestingDeferredWork(); |
449 // nesting-deferred work may have accumulated. Schedule it for processing | 459 }); |
450 // if appropriate. | |
451 self->MaybeScheduleNestingDeferredWork(); | |
452 } | 460 } |
453 | 461 |
454 // Called from the run loop. | 462 // Called from the run loop. |
455 // static | 463 // static |
456 void MessagePumpCFRunLoopBase::PreSourceObserver(CFRunLoopObserverRef observer, | 464 void MessagePumpCFRunLoopBase::PreSourceObserver(CFRunLoopObserverRef observer, |
457 CFRunLoopActivity activity, | 465 CFRunLoopActivity activity, |
458 void* info) { | 466 void* info) { |
459 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); | 467 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); |
460 | 468 |
461 // The run loop has reached the top of the loop and is about to begin | 469 // The run loop has reached the top of the loop and is about to begin |
462 // processing sources. If the last iteration of the loop at this nesting | 470 // processing sources. If the last iteration of the loop at this nesting |
463 // level did not sleep or exit, nesting-deferred work may have accumulated | 471 // level did not sleep or exit, nesting-deferred work may have accumulated |
464 // if a nested loop ran. Schedule nesting-deferred work for processing if | 472 // if a nested loop ran. Schedule nesting-deferred work for processing if |
465 // appropriate. | 473 // appropriate. |
466 self->MaybeScheduleNestingDeferredWork(); | 474 base::mac::CallWithEHFrame(^{ |
| 475 self->MaybeScheduleNestingDeferredWork(); |
| 476 }); |
467 } | 477 } |
468 | 478 |
469 // Called from the run loop. | 479 // Called from the run loop. |
470 // static | 480 // static |
471 void MessagePumpCFRunLoopBase::EnterExitObserver(CFRunLoopObserverRef observer, | 481 void MessagePumpCFRunLoopBase::EnterExitObserver(CFRunLoopObserverRef observer, |
472 CFRunLoopActivity activity, | 482 CFRunLoopActivity activity, |
473 void* info) { | 483 void* info) { |
474 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); | 484 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); |
475 | 485 |
476 switch (activity) { | 486 switch (activity) { |
(...skipping 14 matching lines...) Expand all Loading... |
491 // native loops use CFRunLoop in this way. Because PreWaitObserver will | 501 // native loops use CFRunLoop in this way. Because PreWaitObserver will |
492 // not be called in these case, MaybeScheduleNestingDeferredWork needs | 502 // not be called in these case, MaybeScheduleNestingDeferredWork needs |
493 // to be called here, as the run loop exits. | 503 // to be called here, as the run loop exits. |
494 // | 504 // |
495 // MaybeScheduleNestingDeferredWork consults self->nesting_level_ | 505 // MaybeScheduleNestingDeferredWork consults self->nesting_level_ |
496 // to determine whether to schedule nesting-deferred work. It expects | 506 // to determine whether to schedule nesting-deferred work. It expects |
497 // the nesting level to be set to the depth of the loop that is going | 507 // the nesting level to be set to the depth of the loop that is going |
498 // to sleep or exiting. It must be called before decrementing the | 508 // to sleep or exiting. It must be called before decrementing the |
499 // value so that the value still corresponds to the level of the exiting | 509 // value so that the value still corresponds to the level of the exiting |
500 // loop. | 510 // loop. |
501 self->MaybeScheduleNestingDeferredWork(); | 511 base::mac::CallWithEHFrame(^{ |
| 512 self->MaybeScheduleNestingDeferredWork(); |
| 513 }); |
502 --self->nesting_level_; | 514 --self->nesting_level_; |
503 break; | 515 break; |
504 | 516 |
505 default: | 517 default: |
506 break; | 518 break; |
507 } | 519 } |
508 | 520 |
509 self->EnterExitRunLoop(activity); | 521 base::mac::CallWithEHFrame(^{ |
| 522 self->EnterExitRunLoop(activity); |
| 523 }); |
510 } | 524 } |
511 | 525 |
512 // Called by MessagePumpCFRunLoopBase::EnterExitRunLoop. The default | 526 // Called by MessagePumpCFRunLoopBase::EnterExitRunLoop. The default |
513 // implementation is a no-op. | 527 // implementation is a no-op. |
514 void MessagePumpCFRunLoopBase::EnterExitRunLoop(CFRunLoopActivity activity) { | 528 void MessagePumpCFRunLoopBase::EnterExitRunLoop(CFRunLoopActivity activity) { |
515 } | 529 } |
516 | 530 |
517 // Base version returns a standard NSAutoreleasePool. | 531 // Base version returns a standard NSAutoreleasePool. |
518 AutoreleasePoolType* MessagePumpCFRunLoopBase::CreateAutoreleasePool() { | 532 AutoreleasePoolType* MessagePumpCFRunLoopBase::CreateAutoreleasePool() { |
519 return [[NSAutoreleasePool alloc] init]; | 533 return [[NSAutoreleasePool alloc] init]; |
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
768 [NSApplication sharedApplication]; | 782 [NSApplication sharedApplication]; |
769 g_not_using_cr_app = true; | 783 g_not_using_cr_app = true; |
770 return new MessagePumpNSApplication; | 784 return new MessagePumpNSApplication; |
771 #endif | 785 #endif |
772 } | 786 } |
773 | 787 |
774 return new MessagePumpNSRunLoop; | 788 return new MessagePumpNSRunLoop; |
775 } | 789 } |
776 | 790 |
777 } // namespace base | 791 } // namespace base |
OLD | NEW |