emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master d1fde0ab8a 1/2: Use a single global lock for the child frame stat


From: Po Lu
Subject: master d1fde0ab8a 1/2: Use a single global lock for the child frame state on Haiku
Date: Fri, 31 Dec 2021 04:47:02 -0500 (EST)

branch: master
commit d1fde0ab8ae53b684ff4ba858f1e270bc3ba9db6
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    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.
---
 src/haiku_support.cc | 75 +++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 72 insertions(+), 3 deletions(-)

diff --git a/src/haiku_support.cc b/src/haiku_support.cc
index d211f1157d..66b0e519b0 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 ();



reply via email to

[Prev in Thread] Current Thread [Next in Thread]