| 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 |