diff options
| author | Po Lu | 2021-12-31 09:31:27 +0000 |
|---|---|---|
| committer | Po Lu | 2021-12-31 09:31:27 +0000 |
| commit | d1fde0ab8ae53b684ff4ba858f1e270bc3ba9db6 (patch) | |
| tree | ecbe1b069137190bf014466254955c1e7766b90b /src | |
| parent | c452ffe4c28da21991f1f98007fbe1d66c7e0538 (diff) | |
| download | emacs-d1fde0ab8ae53b684ff4ba858f1e270bc3ba9db6.tar.gz emacs-d1fde0ab8ae53b684ff4ba858f1e270bc3ba9db6.zip | |
Use a single global lock for the child frame state on Haiku
Each BWindows (and various system callbacks) runs in a separate
thread, so there are very complicated locking semantics that
used to be handled manually. This changes child frame state to
use a single global lock, which makes things much easier.
* src/haiku_support.cc (child_frame_lock): New variable.
(class EmacsWindow):
(~EmacsWindow):
(Unparent):
(ParentTo):
(MoveChild):
(FrameMoved):
(EmacsHide):
(EmacsShow):
(GetParentWidthHeight):
(OffsetChildRect):
(MakeFullscreen):
(SetUpDoubleBuffering): Use a single lock for controlling access
to child frame state.
Diffstat (limited to 'src')
| -rw-r--r-- | src/haiku_support.cc | 75 |
1 files changed, 72 insertions, 3 deletions
diff --git a/src/haiku_support.cc b/src/haiku_support.cc index d211f1157d3..66b0e519b07 100644 --- a/src/haiku_support.cc +++ b/src/haiku_support.cc | |||
| @@ -85,6 +85,13 @@ static key_map *key_map = NULL; | |||
| 85 | static char *key_chars = NULL; | 85 | static char *key_chars = NULL; |
| 86 | static BLocker key_map_lock; | 86 | static BLocker key_map_lock; |
| 87 | 87 | ||
| 88 | /* The locking semantics of BWindows running in multiple threads are | ||
| 89 | so complex that child frame state (which is the only state that is | ||
| 90 | shared between different BWindows at runtime) does best with a | ||
| 91 | single global lock. */ | ||
| 92 | |||
| 93 | static BLocker child_frame_lock; | ||
| 94 | |||
| 88 | extern "C" | 95 | extern "C" |
| 89 | { | 96 | { |
| 90 | extern _Noreturn void emacs_abort (void); | 97 | extern _Noreturn void emacs_abort (void); |
| @@ -247,6 +254,8 @@ public: | |||
| 247 | 254 | ||
| 248 | ~EmacsWindow () | 255 | ~EmacsWindow () |
| 249 | { | 256 | { |
| 257 | if (!child_frame_lock.Lock ()) | ||
| 258 | gui_abort ("Failed to lock child frame state lock"); | ||
| 250 | struct child_frame *next; | 259 | struct child_frame *next; |
| 251 | for (struct child_frame *f = subset_windows; f; f = next) | 260 | for (struct child_frame *f = subset_windows; f; f = next) |
| 252 | { | 261 | { |
| @@ -257,6 +266,7 @@ public: | |||
| 257 | 266 | ||
| 258 | if (this->parent) | 267 | if (this->parent) |
| 259 | UnparentAndUnlink (); | 268 | UnparentAndUnlink (); |
| 269 | child_frame_lock.Unlock (); | ||
| 260 | } | 270 | } |
| 261 | 271 | ||
| 262 | void | 272 | void |
| @@ -269,10 +279,13 @@ public: | |||
| 269 | void | 279 | void |
| 270 | UpwardsSubsetChildren (EmacsWindow *w) | 280 | UpwardsSubsetChildren (EmacsWindow *w) |
| 271 | { | 281 | { |
| 282 | if (!child_frame_lock.Lock ()) | ||
| 283 | gui_abort ("Failed to lock child frame state lock"); | ||
| 272 | UpwardsSubset (w); | 284 | UpwardsSubset (w); |
| 273 | for (struct child_frame *f = subset_windows; f; | 285 | for (struct child_frame *f = subset_windows; f; |
| 274 | f = f->next) | 286 | f = f->next) |
| 275 | f->window->UpwardsSubsetChildren (w); | 287 | f->window->UpwardsSubsetChildren (w); |
| 288 | child_frame_lock.Unlock (); | ||
| 276 | } | 289 | } |
| 277 | 290 | ||
| 278 | void | 291 | void |
| @@ -285,15 +298,20 @@ public: | |||
| 285 | void | 298 | void |
| 286 | UpwardsUnSubsetChildren (EmacsWindow *w) | 299 | UpwardsUnSubsetChildren (EmacsWindow *w) |
| 287 | { | 300 | { |
| 301 | if (!child_frame_lock.Lock ()) | ||
| 302 | gui_abort ("Failed to lock child frame state lock"); | ||
| 288 | UpwardsUnSubset (w); | 303 | UpwardsUnSubset (w); |
| 289 | for (struct child_frame *f = subset_windows; f; | 304 | for (struct child_frame *f = subset_windows; f; |
| 290 | f = f->next) | 305 | f = f->next) |
| 291 | f->window->UpwardsUnSubsetChildren (w); | 306 | f->window->UpwardsUnSubsetChildren (w); |
| 307 | child_frame_lock.Unlock (); | ||
| 292 | } | 308 | } |
| 293 | 309 | ||
| 294 | void | 310 | void |
| 295 | Unparent (void) | 311 | Unparent (void) |
| 296 | { | 312 | { |
| 313 | if (!child_frame_lock.Lock ()) | ||
| 314 | gui_abort ("Failed to lock child frame state lock"); | ||
| 297 | this->SetFeel (B_NORMAL_WINDOW_FEEL); | 315 | this->SetFeel (B_NORMAL_WINDOW_FEEL); |
| 298 | UpwardsUnSubsetChildren (parent); | 316 | UpwardsUnSubsetChildren (parent); |
| 299 | this->RemoveFromSubset (this); | 317 | this->RemoveFromSubset (this); |
| @@ -303,13 +321,17 @@ public: | |||
| 303 | fullscreen_p = 0; | 321 | fullscreen_p = 0; |
| 304 | MakeFullscreen (1); | 322 | MakeFullscreen (1); |
| 305 | } | 323 | } |
| 324 | child_frame_lock.Unlock (); | ||
| 306 | } | 325 | } |
| 307 | 326 | ||
| 308 | void | 327 | void |
| 309 | UnparentAndUnlink (void) | 328 | UnparentAndUnlink (void) |
| 310 | { | 329 | { |
| 330 | if (!child_frame_lock.Lock ()) | ||
| 331 | gui_abort ("Failed to lock child frame state lock"); | ||
| 311 | this->parent->UnlinkChild (this); | 332 | this->parent->UnlinkChild (this); |
| 312 | this->Unparent (); | 333 | this->Unparent (); |
| 334 | child_frame_lock.Unlock (); | ||
| 313 | } | 335 | } |
| 314 | 336 | ||
| 315 | void | 337 | void |
| @@ -337,6 +359,9 @@ public: | |||
| 337 | void | 359 | void |
| 338 | ParentTo (EmacsWindow *window) | 360 | ParentTo (EmacsWindow *window) |
| 339 | { | 361 | { |
| 362 | if (!child_frame_lock.Lock ()) | ||
| 363 | gui_abort ("Failed to lock child frame state lock"); | ||
| 364 | |||
| 340 | if (this->parent) | 365 | if (this->parent) |
| 341 | UnparentAndUnlink (); | 366 | UnparentAndUnlink (); |
| 342 | 367 | ||
| @@ -352,6 +377,8 @@ public: | |||
| 352 | } | 377 | } |
| 353 | this->Sync (); | 378 | this->Sync (); |
| 354 | window->LinkChild (this); | 379 | window->LinkChild (this); |
| 380 | |||
| 381 | child_frame_lock.Unlock (); | ||
| 355 | } | 382 | } |
| 356 | 383 | ||
| 357 | void | 384 | void |
| @@ -393,6 +420,9 @@ public: | |||
| 393 | MoveChild (EmacsWindow *window, int xoff, int yoff, | 420 | MoveChild (EmacsWindow *window, int xoff, int yoff, |
| 394 | int weak_p) | 421 | int weak_p) |
| 395 | { | 422 | { |
| 423 | if (!child_frame_lock.Lock ()) | ||
| 424 | gui_abort ("Failed to lock child frame state lock"); | ||
| 425 | |||
| 396 | for (struct child_frame *f = subset_windows; f; | 426 | for (struct child_frame *f = subset_windows; f; |
| 397 | f = f->next) | 427 | f = f->next) |
| 398 | { | 428 | { |
| @@ -402,10 +432,13 @@ public: | |||
| 402 | f->yoff = yoff; | 432 | f->yoff = yoff; |
| 403 | if (!weak_p) | 433 | if (!weak_p) |
| 404 | DoMove (f); | 434 | DoMove (f); |
| 435 | |||
| 436 | child_frame_lock.Unlock (); | ||
| 405 | return; | 437 | return; |
| 406 | } | 438 | } |
| 407 | } | 439 | } |
| 408 | 440 | ||
| 441 | child_frame_lock.Unlock (); | ||
| 409 | gui_abort ("Trying to move a child frame that doesn't exist"); | 442 | gui_abort ("Trying to move a child frame that doesn't exist"); |
| 410 | } | 443 | } |
| 411 | 444 | ||
| @@ -606,9 +639,14 @@ public: | |||
| 606 | 639 | ||
| 607 | haiku_write (MOVE_EVENT, &rq); | 640 | haiku_write (MOVE_EVENT, &rq); |
| 608 | 641 | ||
| 642 | if (!child_frame_lock.Lock ()) | ||
| 643 | gui_abort ("Failed to lock child frame state lock"); | ||
| 644 | |||
| 609 | for (struct child_frame *f = subset_windows; | 645 | for (struct child_frame *f = subset_windows; |
| 610 | f; f = f->next) | 646 | f; f = f->next) |
| 611 | DoMove (f); | 647 | DoMove (f); |
| 648 | |||
| 649 | child_frame_lock.Unlock (); | ||
| 612 | BWindow::FrameMoved (newPosition); | 650 | BWindow::FrameMoved (newPosition); |
| 613 | } | 651 | } |
| 614 | 652 | ||
| @@ -623,10 +661,14 @@ public: | |||
| 623 | void | 661 | void |
| 624 | EmacsMoveTo (int x, int y) | 662 | EmacsMoveTo (int x, int y) |
| 625 | { | 663 | { |
| 664 | if (!child_frame_lock.Lock ()) | ||
| 665 | gui_abort ("Failed to lock child frame state lock"); | ||
| 666 | |||
| 626 | if (!this->parent) | 667 | if (!this->parent) |
| 627 | this->MoveTo (x, y); | 668 | this->MoveTo (x, y); |
| 628 | else | 669 | else |
| 629 | this->parent->MoveChild (this, x, y, 0); | 670 | this->parent->MoveChild (this, x, y, 0); |
| 671 | child_frame_lock.Unlock (); | ||
| 630 | } | 672 | } |
| 631 | 673 | ||
| 632 | bool | 674 | bool |
| @@ -654,9 +696,14 @@ public: | |||
| 654 | { | 696 | { |
| 655 | if (this->IsHidden ()) | 697 | if (this->IsHidden ()) |
| 656 | return; | 698 | return; |
| 699 | if (!child_frame_lock.Lock ()) | ||
| 700 | gui_abort ("Failed to lock child frame state lock"); | ||
| 701 | |||
| 657 | Hide (); | 702 | Hide (); |
| 658 | if (this->parent) | 703 | if (this->parent) |
| 659 | UpwardsUnSubsetChildren (this->parent); | 704 | UpwardsUnSubsetChildren (this->parent); |
| 705 | |||
| 706 | child_frame_lock.Unlock (); | ||
| 660 | } | 707 | } |
| 661 | 708 | ||
| 662 | void | 709 | void |
| @@ -664,11 +711,17 @@ public: | |||
| 664 | { | 711 | { |
| 665 | if (!this->IsHidden ()) | 712 | if (!this->IsHidden ()) |
| 666 | return; | 713 | return; |
| 714 | |||
| 715 | if (!child_frame_lock.Lock ()) | ||
| 716 | gui_abort ("Failed to lock child frame state lock"); | ||
| 717 | |||
| 667 | if (this->parent) | 718 | if (this->parent) |
| 668 | shown_flag = 1; | 719 | shown_flag = 1; |
| 669 | Show (); | 720 | Show (); |
| 670 | if (this->parent) | 721 | if (this->parent) |
| 671 | UpwardsSubsetChildren (this->parent); | 722 | UpwardsSubsetChildren (this->parent); |
| 723 | |||
| 724 | child_frame_lock.Unlock (); | ||
| 672 | } | 725 | } |
| 673 | 726 | ||
| 674 | void | 727 | void |
| @@ -719,6 +772,9 @@ public: | |||
| 719 | void | 772 | void |
| 720 | GetParentWidthHeight (int *width, int *height) | 773 | GetParentWidthHeight (int *width, int *height) |
| 721 | { | 774 | { |
| 775 | if (!child_frame_lock.Lock ()) | ||
| 776 | gui_abort ("Failed to lock child frame state lock"); | ||
| 777 | |||
| 722 | if (parent) | 778 | if (parent) |
| 723 | { | 779 | { |
| 724 | *width = parent->Frame ().Width (); | 780 | *width = parent->Frame ().Width (); |
| @@ -730,11 +786,16 @@ public: | |||
| 730 | *width = s.Frame ().Width (); | 786 | *width = s.Frame ().Width (); |
| 731 | *height = s.Frame ().Height (); | 787 | *height = s.Frame ().Height (); |
| 732 | } | 788 | } |
| 789 | |||
| 790 | child_frame_lock.Unlock (); | ||
| 733 | } | 791 | } |
| 734 | 792 | ||
| 735 | void | 793 | void |
| 736 | OffsetChildRect (BRect *r, EmacsWindow *c) | 794 | OffsetChildRect (BRect *r, EmacsWindow *c) |
| 737 | { | 795 | { |
| 796 | if (!child_frame_lock.Lock ()) | ||
| 797 | gui_abort ("Failed to lock child frame state lock"); | ||
| 798 | |||
| 738 | for (struct child_frame *f; f; f = f->next) | 799 | for (struct child_frame *f; f; f = f->next) |
| 739 | if (f->window == c) | 800 | if (f->window == c) |
| 740 | { | 801 | { |
| @@ -742,9 +803,11 @@ public: | |||
| 742 | r->bottom -= f->yoff; | 803 | r->bottom -= f->yoff; |
| 743 | r->left -= f->xoff; | 804 | r->left -= f->xoff; |
| 744 | r->right -= f->xoff; | 805 | r->right -= f->xoff; |
| 806 | child_frame_lock.Unlock (); | ||
| 745 | return; | 807 | return; |
| 746 | } | 808 | } |
| 747 | 809 | ||
| 810 | child_frame_lock.Lock (); | ||
| 748 | gui_abort ("Trying to calculate offsets for a child frame that doesn't exist"); | 811 | gui_abort ("Trying to calculate offsets for a child frame that doesn't exist"); |
| 749 | } | 812 | } |
| 750 | 813 | ||
| @@ -753,8 +816,8 @@ public: | |||
| 753 | { | 816 | { |
| 754 | BScreen screen (this); | 817 | BScreen screen (this); |
| 755 | 818 | ||
| 756 | if (!screen.IsValid ()) | 819 | if (!screen.IsValid ()) |
| 757 | gui_abort ("Trying to make a window fullscreen without a screen"); | 820 | gui_abort ("Trying to make a window fullscreen without a screen"); |
| 758 | 821 | ||
| 759 | if (make_fullscreen_p == fullscreen_p) | 822 | if (make_fullscreen_p == fullscreen_p) |
| 760 | return; | 823 | return; |
| @@ -768,9 +831,15 @@ public: | |||
| 768 | 831 | ||
| 769 | flags |= B_NOT_MOVABLE | B_NOT_ZOOMABLE; | 832 | flags |= B_NOT_MOVABLE | B_NOT_ZOOMABLE; |
| 770 | pre_fullscreen_rect = Frame (); | 833 | pre_fullscreen_rect = Frame (); |
| 834 | |||
| 835 | if (!child_frame_lock.Lock ()) | ||
| 836 | gui_abort ("Failed to lock child frame state lock"); | ||
| 837 | |||
| 771 | if (parent) | 838 | if (parent) |
| 772 | parent->OffsetChildRect (&pre_fullscreen_rect, this); | 839 | parent->OffsetChildRect (&pre_fullscreen_rect, this); |
| 773 | 840 | ||
| 841 | child_frame_lock.Unlock (); | ||
| 842 | |||
| 774 | int w, h; | 843 | int w, h; |
| 775 | EmacsMoveTo (0, 0); | 844 | EmacsMoveTo (0, 0); |
| 776 | GetParentWidthHeight (&w, &h); | 845 | GetParentWidthHeight (&w, &h); |
| @@ -1065,7 +1134,7 @@ public: | |||
| 1065 | if (looper_locked_count) | 1134 | if (looper_locked_count) |
| 1066 | { | 1135 | { |
| 1067 | if (!offscreen_draw_bitmap_1->Lock ()) | 1136 | if (!offscreen_draw_bitmap_1->Lock ()) |
| 1068 | gui_abort ("Failed to lock bitmap after double buffering was set up."); | 1137 | gui_abort ("Failed to lock bitmap after double buffering was set up"); |
| 1069 | } | 1138 | } |
| 1070 | 1139 | ||
| 1071 | UnlockLooper (); | 1140 | UnlockLooper (); |