diff options
author | Po Lu <luangruo@yahoo.com> | 2021-12-31 09:31:27 +0000 |
---|---|---|
committer | Po Lu <luangruo@yahoo.com> | 2021-12-31 09:31:27 +0000 |
commit | d1fde0ab8ae53b684ff4ba858f1e270bc3ba9db6 (patch) | |
tree | ecbe1b069137190bf014466254955c1e7766b90b /src | |
parent | c452ffe4c28da21991f1f98007fbe1d66c7e0538 (diff) | |
download | emacs-d1fde0ab8ae53b684ff4ba858f1e270bc3ba9db6.tar.gz emacs-d1fde0ab8ae53b684ff4ba858f1e270bc3ba9db6.tar.bz2 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; static char *key_chars = NULL; static BLocker key_map_lock; +/* The locking semantics of BWindows running in multiple threads are + so complex that child frame state (which is the only state that is + shared between different BWindows at runtime) does best with a + single global lock. */ + +static BLocker child_frame_lock; + extern "C" { extern _Noreturn void emacs_abort (void); @@ -247,6 +254,8 @@ public: ~EmacsWindow () { + if (!child_frame_lock.Lock ()) + gui_abort ("Failed to lock child frame state lock"); struct child_frame *next; for (struct child_frame *f = subset_windows; f; f = next) { @@ -257,6 +266,7 @@ public: if (this->parent) UnparentAndUnlink (); + child_frame_lock.Unlock (); } void @@ -269,10 +279,13 @@ public: void UpwardsSubsetChildren (EmacsWindow *w) { + if (!child_frame_lock.Lock ()) + gui_abort ("Failed to lock child frame state lock"); UpwardsSubset (w); for (struct child_frame *f = subset_windows; f; f = f->next) f->window->UpwardsSubsetChildren (w); + child_frame_lock.Unlock (); } void @@ -285,15 +298,20 @@ public: void UpwardsUnSubsetChildren (EmacsWindow *w) { + if (!child_frame_lock.Lock ()) + gui_abort ("Failed to lock child frame state lock"); UpwardsUnSubset (w); for (struct child_frame *f = subset_windows; f; f = f->next) f->window->UpwardsUnSubsetChildren (w); + child_frame_lock.Unlock (); } void Unparent (void) { + if (!child_frame_lock.Lock ()) + gui_abort ("Failed to lock child frame state lock"); this->SetFeel (B_NORMAL_WINDOW_FEEL); UpwardsUnSubsetChildren (parent); this->RemoveFromSubset (this); @@ -303,13 +321,17 @@ public: fullscreen_p = 0; MakeFullscreen (1); } + child_frame_lock.Unlock (); } void UnparentAndUnlink (void) { + if (!child_frame_lock.Lock ()) + gui_abort ("Failed to lock child frame state lock"); this->parent->UnlinkChild (this); this->Unparent (); + child_frame_lock.Unlock (); } void @@ -337,6 +359,9 @@ public: void ParentTo (EmacsWindow *window) { + if (!child_frame_lock.Lock ()) + gui_abort ("Failed to lock child frame state lock"); + if (this->parent) UnparentAndUnlink (); @@ -352,6 +377,8 @@ public: } this->Sync (); window->LinkChild (this); + + child_frame_lock.Unlock (); } void @@ -393,6 +420,9 @@ public: MoveChild (EmacsWindow *window, int xoff, int yoff, int weak_p) { + if (!child_frame_lock.Lock ()) + gui_abort ("Failed to lock child frame state lock"); + for (struct child_frame *f = subset_windows; f; f = f->next) { @@ -402,10 +432,13 @@ public: f->yoff = yoff; if (!weak_p) DoMove (f); + + child_frame_lock.Unlock (); return; } } + child_frame_lock.Unlock (); gui_abort ("Trying to move a child frame that doesn't exist"); } @@ -606,9 +639,14 @@ public: haiku_write (MOVE_EVENT, &rq); + if (!child_frame_lock.Lock ()) + gui_abort ("Failed to lock child frame state lock"); + for (struct child_frame *f = subset_windows; f; f = f->next) DoMove (f); + + child_frame_lock.Unlock (); BWindow::FrameMoved (newPosition); } @@ -623,10 +661,14 @@ public: void EmacsMoveTo (int x, int y) { + if (!child_frame_lock.Lock ()) + gui_abort ("Failed to lock child frame state lock"); + if (!this->parent) this->MoveTo (x, y); else this->parent->MoveChild (this, x, y, 0); + child_frame_lock.Unlock (); } bool @@ -654,9 +696,14 @@ public: { if (this->IsHidden ()) return; + if (!child_frame_lock.Lock ()) + gui_abort ("Failed to lock child frame state lock"); + Hide (); if (this->parent) UpwardsUnSubsetChildren (this->parent); + + child_frame_lock.Unlock (); } void @@ -664,11 +711,17 @@ public: { if (!this->IsHidden ()) return; + + if (!child_frame_lock.Lock ()) + gui_abort ("Failed to lock child frame state lock"); + if (this->parent) shown_flag = 1; Show (); if (this->parent) UpwardsSubsetChildren (this->parent); + + child_frame_lock.Unlock (); } void @@ -719,6 +772,9 @@ public: void GetParentWidthHeight (int *width, int *height) { + if (!child_frame_lock.Lock ()) + gui_abort ("Failed to lock child frame state lock"); + if (parent) { *width = parent->Frame ().Width (); @@ -730,11 +786,16 @@ public: *width = s.Frame ().Width (); *height = s.Frame ().Height (); } + + child_frame_lock.Unlock (); } void OffsetChildRect (BRect *r, EmacsWindow *c) { + if (!child_frame_lock.Lock ()) + gui_abort ("Failed to lock child frame state lock"); + for (struct child_frame *f; f; f = f->next) if (f->window == c) { @@ -742,9 +803,11 @@ public: r->bottom -= f->yoff; r->left -= f->xoff; r->right -= f->xoff; + child_frame_lock.Unlock (); return; } + child_frame_lock.Lock (); gui_abort ("Trying to calculate offsets for a child frame that doesn't exist"); } @@ -753,8 +816,8 @@ public: { BScreen screen (this); - if (!screen.IsValid ()) - gui_abort ("Trying to make a window fullscreen without a screen"); + if (!screen.IsValid ()) + gui_abort ("Trying to make a window fullscreen without a screen"); if (make_fullscreen_p == fullscreen_p) return; @@ -768,9 +831,15 @@ public: flags |= B_NOT_MOVABLE | B_NOT_ZOOMABLE; pre_fullscreen_rect = Frame (); + + if (!child_frame_lock.Lock ()) + gui_abort ("Failed to lock child frame state lock"); + if (parent) parent->OffsetChildRect (&pre_fullscreen_rect, this); + child_frame_lock.Unlock (); + int w, h; EmacsMoveTo (0, 0); GetParentWidthHeight (&w, &h); @@ -1065,7 +1134,7 @@ public: if (looper_locked_count) { if (!offscreen_draw_bitmap_1->Lock ()) - gui_abort ("Failed to lock bitmap after double buffering was set up."); + gui_abort ("Failed to lock bitmap after double buffering was set up"); } UnlockLooper (); |