[haiku-commits] r33876 - haiku/trunk/src/servers/app

  • From: axeld@xxxxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Wed, 4 Nov 2009 14:28:32 +0100 (CET)

Author: axeld
Date: 2009-11-04 14:28:32 +0100 (Wed, 04 Nov 2009)
New Revision: 33876
Changeset: http://dev.haiku-os.org/changeset/33876/haiku

Modified:
   haiku/trunk/src/servers/app/BitmapManager.cpp
   haiku/trunk/src/servers/app/OffscreenServerWindow.cpp
   haiku/trunk/src/servers/app/ServerApp.cpp
   haiku/trunk/src/servers/app/ServerApp.h
   haiku/trunk/src/servers/app/ServerBitmap.cpp
   haiku/trunk/src/servers/app/ServerBitmap.h
   haiku/trunk/src/servers/app/ServerPicture.cpp
   haiku/trunk/src/servers/app/ServerPicture.h
   haiku/trunk/src/servers/app/ServerWindow.cpp
   haiku/trunk/src/servers/app/View.cpp
Log:
* ServerApp's bitmap and picture handling was completely broken, as it ignored
  concurrency as well as reference counting, causing occasional crashes and
  memory corruption.
* ServerPicture now subclasses Referenceable, and will notify its owner when
  it's going to be deleted. This might bring some regressions, although I
  couldn't spot anything wrong yet.
* ServerBitmap will now also notify its owner when it's going to be deleted as
  well.
* Switched from the former picture/bitmap lists to a std::map. This also solves
  the issue of not checking whether or not the bitmap/picture actually belongs
  to the ServerApp (before, all apps could access and delete all
  pictures/bitmaps)
* Introduced a new fMapLocker that guards the new maps.
* ServerWindow now uses GetBitmap()/GetPicture(), and gives up its reference
  after use.


Modified: haiku/trunk/src/servers/app/BitmapManager.cpp
===================================================================
--- haiku/trunk/src/servers/app/BitmapManager.cpp       2009-11-04 13:05:18 UTC 
(rev 33875)
+++ haiku/trunk/src/servers/app/BitmapManager.cpp       2009-11-04 13:28:32 UTC 
(rev 33876)
@@ -220,6 +220,9 @@
        if (bitmap->Overlay() != NULL)
                fOverlays.RemoveItem(bitmap);
 
+       if (bitmap->Owner() != NULL)
+               bitmap->Owner()->BitmapRemoved(bitmap);
+
        if (fBitmapList.RemoveItem(bitmap))
                delete bitmap;
 }

Modified: haiku/trunk/src/servers/app/OffscreenServerWindow.cpp
===================================================================
--- haiku/trunk/src/servers/app/OffscreenServerWindow.cpp       2009-11-04 
13:05:18 UTC (rev 33875)
+++ haiku/trunk/src/servers/app/OffscreenServerWindow.cpp       2009-11-04 
13:28:32 UTC (rev 33876)
@@ -24,6 +24,7 @@
 
 OffscreenServerWindow::~OffscreenServerWindow()
 {
+       fBitmap->Release();
 }
 
 

Modified: haiku/trunk/src/servers/app/ServerApp.cpp
===================================================================
--- haiku/trunk/src/servers/app/ServerApp.cpp   2009-11-04 13:05:18 UTC (rev 
33875)
+++ haiku/trunk/src/servers/app/ServerApp.cpp   2009-11-04 13:28:32 UTC (rev 
33876)
@@ -97,6 +97,7 @@
        fClientTeam(clientTeam),
        fWindowListLock("window list"),
        fTemporaryDisplayModeChange(0),
+       fMapLocker("server app maps"),
        fAppCursor(NULL),
        fViewCursor(NULL),
        fCursorHideLevel(0),
@@ -188,12 +189,20 @@
                fWindowListLock.Lock();
        }
 
-       for (int32 i = fBitmapList.CountItems(); i-- > 0;) {
-               
gBitmapManager->DeleteBitmap((ServerBitmap*)fBitmapList.ItemAt(i));
+       fMapLocker.Lock();
+
+       while (!fBitmapMap.empty()) {
+               ServerBitmap* bitmap = fBitmapMap.begin()->second;
+
+               fBitmapMap.erase(fBitmapMap.begin());
+               bitmap->Release();
        }
 
-       for (int32 i = fPictureList.CountItems(); i-- > 0;) {
-               delete fPictureList.ItemAt(i);
+       while (!fPictureMap.empty()) {
+               ServerPicture* picture = fPictureMap.begin()->second;
+
+               fPictureMap.erase(fPictureMap.begin());
+               picture->ReleaseReference();
        }
 
        fDesktop->GetCursorManager().DeleteCursors(fClientTeam);
@@ -243,37 +252,6 @@
 }
 
 
-/*!    \brief Send a message to the ServerApp's BApplication
-       \param message The message to send
-*/
-void
-ServerApp::SendMessageToClient(BMessage* message) const
-{
-       status_t status = fHandlerMessenger.SendMessage(message, 
(BHandler*)NULL,
-               100000);
-       if (status != B_OK) {
-               syslog(LOG_ERR, "app %s send to client failed: %s\n", 
Signature(),
-                       strerror(status));
-       }
-}
-
-
-bool
-ServerApp::_HasWindowUnderMouse()
-{
-       BAutolock locker(fWindowListLock);
-
-       for (int32 i = fWindowList.CountItems(); i-- > 0;) {
-               ServerWindow* serverWindow = fWindowList.ItemAt(i);
-
-               if (fDesktop->ViewUnderMouse(serverWindow->Window()) != 
B_NULL_TOKEN)
-                       return true;
-       }
-
-       return false;
-}
-
-
 /*!    \brief Sets the ServerApp's active status
        \param value The new status of the ServerApp.
 
@@ -302,7 +280,22 @@
 }
 
 
+/*!    \brief Send a message to the ServerApp's BApplication
+       \param message The message to send
+*/
 void
+ServerApp::SendMessageToClient(BMessage* message) const
+{
+       status_t status = fHandlerMessenger.SendMessage(message, 
(BHandler*)NULL,
+               100000);
+       if (status != B_OK) {
+               syslog(LOG_ERR, "app %s send to client failed: %s\n", 
Signature(),
+                       strerror(status));
+       }
+}
+
+
+void
 ServerApp::SetCurrentCursor(ServerCursor* cursor)
 {
        if (fViewCursor == cursor)
@@ -330,95 +323,192 @@
 }
 
 
+bool
+ServerApp::AddWindow(ServerWindow* window)
+{
+       BAutolock locker(fWindowListLock);
+
+       return fWindowList.AddItem(window);
+}
+
+
 void
-ServerApp::_GetLooperName(char* name, size_t length)
+ServerApp::RemoveWindow(ServerWindow* window)
 {
-       snprintf(name, length, "a:%ld:%s", ClientTeam(), SignatureLeaf());
+       BAutolock locker(fWindowListLock);
+
+       fWindowList.RemoveItem(window);
 }
 
 
-/*!    \brief The thread function ServerApps use to monitor messages
+bool
+ServerApp::InWorkspace(int32 index) const
+{
+       BAutolock locker(fWindowListLock);
+
+       // we could cache this, but then we'd have to recompute the cached
+       // value everytime a window has closed or changed workspaces
+
+       // TODO: support initial application workspace!
+
+       for (int32 i = fWindowList.CountItems(); i-- > 0;) {
+               ServerWindow* serverWindow = fWindowList.ItemAt(i);
+
+               const Window* window = serverWindow->Window();
+               if (window == NULL || window->IsOffscreenWindow())
+                       continue;
+
+               // only normal and unhidden windows count
+
+               if (window->IsNormal() && !window->IsHidden()
+                       && window->InWorkspace(index))
+                       return true;
+       }
+
+       return false;
+}
+
+
+uint32
+ServerApp::Workspaces() const
+{
+       uint32 workspaces = 0;
+
+       BAutolock locker(fWindowListLock);
+
+       // we could cache this, but then we'd have to recompute the cached
+       // value everytime a window has closed or changed workspaces
+
+       for (int32 i = fWindowList.CountItems(); i-- > 0;) {
+               ServerWindow* serverWindow = fWindowList.ItemAt(i);
+
+               const Window* window = serverWindow->Window();
+               if (window == NULL || window->IsOffscreenWindow())
+                       continue;
+
+               // only normal and unhidden windows count
+
+               if (window->IsNormal() && !window->IsHidden())
+                       workspaces |= window->Workspaces();
+       }
+
+       // TODO: add initial application workspace!
+       return workspaces;
+}
+
+
+/*!    \brief Acquires a reference of the desired bitmap, if available.
+       \param token ID token of the bitmap to find
+       \return The bitmap having that ID or NULL if not found
 */
+ServerBitmap*
+ServerApp::GetBitmap(int32 token) const
+{
+       if (token < 1)
+               return NULL;
+
+       BAutolock _(fMapLocker);
+
+       ServerBitmap* bitmap = _FindBitmap(token);
+       if (bitmap == NULL)
+               return NULL;
+
+       bitmap->Acquire();
+
+       return bitmap;
+}
+
+
+bool
+ServerApp::BitmapAdded(ServerBitmap* bitmap)
+{
+       BAutolock _(fMapLocker);
+
+       try {
+               fBitmapMap.insert(std::make_pair(bitmap->Token(), bitmap));
+       } catch (std::bad_alloc& exception) {
+               return false;
+       }
+
+       return true;
+}
+
+
 void
-ServerApp::_MessageLooper()
+ServerApp::BitmapRemoved(ServerBitmap* bitmap)
 {
-       // Message-dispatching loop for the ServerApp
+       BAutolock _(fMapLocker);
+       fBitmapMap.erase(bitmap->Token());
+}
 
-       // First let's tell the client how to talk with us.
-       fLink.StartMessage(B_OK);
-       fLink.Attach<port_id>(fMessagePort);
-       fLink.Attach<area_id>(fDesktop->SharedReadOnlyArea());
-       fLink.Flush();
 
-       BPrivate::LinkReceiver &receiver = fLink.Receiver();
+ServerPicture*
+ServerApp::CreatePicture(const ServerPicture* original)
+{
+       ServerPicture* picture;
+       if (original != NULL)
+               picture = new(std::nothrow) ServerPicture(*original);
+       else
+               picture = new(std::nothrow) ServerPicture();
 
-       int32 code;
-       status_t err = B_OK;
+       if (picture != NULL && !picture->SetOwner(this))
+               picture->ReleaseReference();
 
-       while (!fQuitting) {
-               STRACE(("info: ServerApp::_MessageLooper() listening on port 
%ld.\n",
-                       fMessagePort));
+       return picture;
+}
 
-               err = receiver.GetNextMessage(code, B_INFINITE_TIMEOUT);
-               if (err != B_OK || code == B_QUIT_REQUESTED) {
-                       STRACE(("ServerApp: application seems to be 
gone...\n"));
 
-                       // Tell desktop to quit us
-                       BPrivate::LinkSender link(fDesktop->MessagePort());
-                       link.StartMessage(AS_DELETE_APP);
-                       link.Attach<thread_id>(Thread());
-                       link.Flush();
-                       break;
-               }
+ServerPicture*
+ServerApp::GetPicture(int32 token) const
+{
+       if (token < 1)
+               return NULL;
 
-               switch (code) {
-                       case kMsgAppQuit:
-                               // we receive this from our destructor on quit
-                               fQuitting = true;
-                               break;
+       BAutolock _(fMapLocker);
 
-                       case AS_QUIT_APP:
-                       {
-                               // This message is received only when the 
app_server is asked
-                               // to shut down in test/debug mode. Of course, 
if we are testing
-                               // while using AccelerantDriver, we do NOT want 
to shut down
-                               // client applications. The server can be quit 
in this fashion
-                               // through the driver's interface, such as 
closing the
-                               // ViewDriver's window.
+       ServerPicture* picture = _FindPicture(token);
+       if (picture == NULL)
+               return NULL;
 
-                               STRACE(("ServerApp %s:Server shutdown 
notification received\n",
-                                       Signature()));
+       picture->AcquireReference();
 
-                               // If we are using the real, accelerated 
version of the
-                               // DrawingEngine, we do NOT want the user to be 
able shut down
-                               // the server. The results would NOT be pretty
-#if TEST_MODE
-                               BMessage pleaseQuit(B_QUIT_REQUESTED);
-                               SendMessageToClient(&pleaseQuit);
-#endif
-                               break;
-                       }
+       return picture;
+}
 
-                       default:
-                               STRACE(("ServerApp %s: Got a Message to 
dispatch\n",
-                                       Signature()));
-                               _DispatchMessage(code, receiver);
-                               break;
-               }
+
+bool
+ServerApp::PictureAdded(ServerPicture* picture)
+{
+       BAutolock _(fMapLocker);
+
+       try {
+               fPictureMap.insert(std::make_pair(picture->Token(), picture));
+       } catch (std::bad_alloc& exception) {
+               return false;
        }
 
-       // Quit() will send us a message; we're handling the exiting procedure
-       thread_id sender;
-       sem_id shutdownSemaphore;
-       receive_data(&sender, &shutdownSemaphore, sizeof(sem_id));
+       return true;
+}
 
-       delete this;
 
-       if (shutdownSemaphore >= B_OK)
-               release_sem(shutdownSemaphore);
+void
+ServerApp::PictureRemoved(ServerPicture* picture)
+{
+       BAutolock _(fMapLocker);
+       fPictureMap.erase(picture->Token());
 }
 
 
+// #pragma mark - private methods
+
+
+void
+ServerApp::_GetLooperName(char* name, size_t length)
+{
+       snprintf(name, length, "a:%ld:%s", ClientTeam(), SignatureLeaf());
+}
+
+
 /*!    \brief Handler function for BApplication API messages
        \param code Identifier code for the message. Equivalent to 
BMessage::what
        \param buffer Any attachments
@@ -653,9 +743,7 @@
                        STRACE(("ServerApp %s: Create Bitmap (%.1fx%.1f)\n",
                                Signature(), frame.Width() + 1, frame.Height() 
+ 1));
 
-                       if (bitmap != NULL && fBitmapList.AddItem(bitmap)) {
-                               bitmap->SetOwner(this);
-
+                       if (bitmap != NULL && bitmap->SetOwner(this)) {
                                fLink.StartMessage(B_OK);
                                fLink.Attach<int32>(bitmap->Token());
                                fLink.Attach<uint8>(allocationFlags);
@@ -665,11 +753,11 @@
                                fLink.Attach<int32>(
                                        
fMemoryAllocator.AreaOffset(bitmap->AllocationCookie()));
 
-                               if (allocationFlags & kFramebuffer)
+                               if ((allocationFlags & kFramebuffer) != 0)
                                        
fLink.Attach<int32>(bitmap->BytesPerRow());
                        } else {
                                if (bitmap != NULL)
-                                       gBitmapManager->DeleteBitmap(bitmap);
+                                       bitmap->Release();
 
                                fLink.StartMessage(B_NO_MEMORY);
                        }
@@ -689,13 +777,17 @@
                        int32 token;
                        link.Read<int32>(&token);
 
-                       ServerBitmap *bitmap = FindBitmap(token);
-                       if (bitmap && fBitmapList.RemoveItem(bitmap)) {
+                       fMapLocker.Lock();
+
+                       ServerBitmap* bitmap = _FindBitmap(token);
+                       if (bitmap != NULL) {
                                STRACE(("ServerApp %s: Deleting Bitmap %ld\n", 
Signature(),
                                        token));
 
-                               gBitmapManager->DeleteBitmap(bitmap);
+                               bitmap->Release();
                        }
+
+                       fMapLocker.Unlock();
                        break;
                }
                case AS_GET_BITMAP_OVERLAY_RESTRICTIONS:
@@ -707,13 +799,15 @@
                        if (link.Read<int32>(&token) != B_OK)
                                break;
 
-                       ServerBitmap *bitmap = FindBitmap(token);
+                       ServerBitmap* bitmap = GetBitmap(token);
                        if (bitmap != NULL) {
                                STRACE(("ServerApp %s: Get overlay restrictions 
for bitmap "
                                        "%ld\n", Signature(), token));
 
                                status = 
fDesktop->HWInterface()->GetOverlayRestrictions(
                                        bitmap->Overlay(), &restrictions);
+
+                               bitmap->Release();
                        }
 
                        fLink.StartMessage(status);
@@ -752,7 +846,9 @@
                                for (int32 i = 0; i < subPicturesCount; i++) {
                                        int32 token = -1;
                                        link.Read<int32>(&token);
-                                       if (ServerPicture* subPicture = 
FindPicture(token))
+
+                                       // TODO: do we actually need another 
reference here?
+                                       if (ServerPicture* subPicture = 
GetPicture(token))
                                                
picture->NestPicture(subPicture);
                                }
                                status = picture->ImportData(link);
@@ -771,8 +867,13 @@
                {
                        STRACE(("ServerApp %s: Delete Picture\n", Signature()));
                        int32 token;
-                       if (link.Read<int32>(&token) == B_OK)
-                               DeletePicture(token);
+                       if (link.Read<int32>(&token) == B_OK) {
+                               BAutolock _(fMapLocker);
+
+                               ServerPicture* picture = _FindPicture(token);
+                               if (picture != NULL)
+                                       picture->ReleaseReference();
+                       }
                        break;
                }
 
@@ -782,7 +883,7 @@
                        int32 token;
                        ServerPicture* original = NULL;
                        if (link.Read<int32>(&token) == B_OK)
-                               original = FindPicture(token);
+                               original = GetPicture(token);
 
                        if (original != NULL) {
                                ServerPicture* cloned = CreatePicture(original);
@@ -791,6 +892,8 @@
                                        fLink.Attach<int32>(cloned->Token());
                                } else
                                        fLink.StartMessage(B_NO_MEMORY);
+
+                               original->ReleaseReference();
                        } else
                                fLink.StartMessage(B_BAD_VALUE);
 
@@ -803,10 +906,11 @@
                        STRACE(("ServerApp %s: Download Picture\n", 
Signature()));
                        int32 token;
                        link.Read<int32>(&token);
-                       ServerPicture* picture = FindPicture(token);
+                       ServerPicture* picture = GetPicture(token);
                        if (picture != NULL) {
                                picture->ExportData(fLink);
                                        // ExportData() calls StartMessage() 
already
+                               picture->ReleaseReference();
                        } else
                                fLink.StartMessage(B_ERROR);
 
@@ -2740,8 +2844,8 @@
                case AS_READ_BITMAP:
                {
                        STRACE(("ServerApp %s: AS_READ_BITMAP\n", Signature()));
-                       int32 bitmapToken;
-                       link.Read<int32>(&bitmapToken);
+                       int32 token;
+                       link.Read<int32>(&token);
 
                        bool drawCursor = true;
                        link.Read<bool>(&drawCursor);
@@ -2749,13 +2853,15 @@
                        BRect bounds;
                        link.Read<BRect>(&bounds);
 
-                       ServerBitmap *bitmap = FindBitmap(bitmapToken);
+                       ServerBitmap* bitmap = GetBitmap(token);
                        if (bitmap != NULL) {
                                if 
(fDesktop->GetDrawingEngine()->ReadBitmap(bitmap,
-                                       drawCursor, bounds) == B_OK) {
+                                               drawCursor, bounds) == B_OK) {
                                        fLink.StartMessage(B_OK);
                                } else
                                        fLink.StartMessage(B_BAD_VALUE);
+
+                               gBitmapManager->DeleteBitmap(bitmap);
                        } else
                                fLink.StartMessage(B_BAD_VALUE);
 
@@ -2910,6 +3016,88 @@
 }
 
 
+/*!    \brief The thread function ServerApps use to monitor messages
+*/
+void
+ServerApp::_MessageLooper()
+{
+       // Message-dispatching loop for the ServerApp
+
+       // First let's tell the client how to talk with us.
+       fLink.StartMessage(B_OK);
+       fLink.Attach<port_id>(fMessagePort);
+       fLink.Attach<area_id>(fDesktop->SharedReadOnlyArea());
+       fLink.Flush();
+
+       BPrivate::LinkReceiver &receiver = fLink.Receiver();
+
+       int32 code;
+       status_t err = B_OK;
+
+       while (!fQuitting) {
+               STRACE(("info: ServerApp::_MessageLooper() listening on port 
%ld.\n",
+                       fMessagePort));
+
+               err = receiver.GetNextMessage(code, B_INFINITE_TIMEOUT);
+               if (err != B_OK || code == B_QUIT_REQUESTED) {
+                       STRACE(("ServerApp: application seems to be 
gone...\n"));
+
+                       // Tell desktop to quit us
+                       BPrivate::LinkSender link(fDesktop->MessagePort());
+                       link.StartMessage(AS_DELETE_APP);
+                       link.Attach<thread_id>(Thread());
+                       link.Flush();
+                       break;
+               }
+
+               switch (code) {
+                       case kMsgAppQuit:
+                               // we receive this from our destructor on quit
+                               fQuitting = true;
+                               break;
+
+                       case AS_QUIT_APP:
+                       {
+                               // This message is received only when the 
app_server is asked
+                               // to shut down in test/debug mode. Of course, 
if we are testing
+                               // while using AccelerantDriver, we do NOT want 
to shut down
+                               // client applications. The server can be quit 
in this fashion
+                               // through the driver's interface, such as 
closing the
+                               // ViewDriver's window.
+
+                               STRACE(("ServerApp %s:Server shutdown 
notification received\n",
+                                       Signature()));
+
+                               // If we are using the real, accelerated 
version of the
+                               // DrawingEngine, we do NOT want the user to be 
able shut down
+                               // the server. The results would NOT be pretty
+#if TEST_MODE
+                               BMessage pleaseQuit(B_QUIT_REQUESTED);
+                               SendMessageToClient(&pleaseQuit);
+#endif
+                               break;
+                       }
+
+                       default:
+                               STRACE(("ServerApp %s: Got a Message to 
dispatch\n",
+                                       Signature()));
+                               _DispatchMessage(code, receiver);
+                               break;
+               }
+       }
+
+       // Quit() will send us a message; we're handling the exiting procedure
+       thread_id sender;
+       sem_id shutdownSemaphore;
+       receive_data(&sender, &shutdownSemaphore, sizeof(sem_id));
+
+       delete this;
+
+       if (shutdownSemaphore >= B_OK)
+               release_sem(shutdownSemaphore);
+}
+
+
 status_t
 ServerApp::_CreateWindow(int32 code, BPrivate::LinkReceiver& link,
        port_id& clientReplyPort)
@@ -2960,7 +3148,7 @@
        ServerWindow *window = NULL;
 
        if (code == AS_CREATE_OFFSCREEN_WINDOW) {
-               ServerBitmap* bitmap = FindBitmap(bitmapToken);
+               ServerBitmap* bitmap = GetBitmap(bitmapToken);
 
                if (bitmap != NULL) {
                        window = new (nothrow) OffscreenServerWindow(title, 
this,
@@ -2996,44 +3184,14 @@
 
 
 bool
-ServerApp::AddWindow(ServerWindow* window)
+ServerApp::_HasWindowUnderMouse()
 {
        BAutolock locker(fWindowListLock);
 
-       return fWindowList.AddItem(window);
-}
-
-
-void
-ServerApp::RemoveWindow(ServerWindow* window)
-{
-       BAutolock locker(fWindowListLock);
-
-       fWindowList.RemoveItem(window);
-}
-
-
-bool
-ServerApp::InWorkspace(int32 index) const
-{
-       BAutolock locker(fWindowListLock);
-
-       // we could cache this, but then we'd have to recompute the cached
-       // value everytime a window has closed or changed workspaces
-
-       // TODO: support initial application workspace!
-
        for (int32 i = fWindowList.CountItems(); i-- > 0;) {
                ServerWindow* serverWindow = fWindowList.ItemAt(i);
 
-               const Window* window = serverWindow->Window();
-               if (window == NULL || window->IsOffscreenWindow())
-                       continue;
-
-               // only normal and unhidden windows count
-
-               if (window->IsNormal() && !window->IsHidden()
-                       && window->InWorkspace(index))
+               if (fDesktop->ViewUnderMouse(serverWindow->Window()) != 
B_NULL_TOKEN)
                        return true;
        }
 
@@ -3041,110 +3199,27 @@
 }
 
 
-uint32
-ServerApp::Workspaces() const
-{
-       uint32 workspaces = 0;
-
-       BAutolock locker(fWindowListLock);
-
-       // we could cache this, but then we'd have to recompute the cached
-       // value everytime a window has closed or changed workspaces
-
-       for (int32 i = fWindowList.CountItems(); i-- > 0;) {
-               ServerWindow* serverWindow = fWindowList.ItemAt(i);
-
-               const Window* window = serverWindow->Window();
-               if (window == NULL || window->IsOffscreenWindow())
-                       continue;
-
-               // only normal and unhidden windows count
-
-               if (window->IsNormal() && !window->IsHidden())
-                       workspaces |= window->Workspaces();
-       }
-
-       // TODO: add initial application workspace!
-       return workspaces;
-}
-
-
-int32
-ServerApp::CountBitmaps() const
-{
-       return fBitmapList.CountItems();
-}
-
-
-/*!    \brief Looks up a ServerApp's ServerBitmap in its list
-       \param token ID token of the bitmap to find
-       \return The bitmap having that ID or NULL if not found
-*/
 ServerBitmap*
-ServerApp::FindBitmap(int32 token) const
+ServerApp::_FindBitmap(int32 token) const
 {
-       // TODO: we need to make sure the bitmap is ours?!
-       ServerBitmap* bitmap;
-       if (gTokenSpace.GetToken(token, kBitmapToken, (void**)&bitmap) == B_OK)
-               return bitmap;
+       ASSERT(fMapLock.IsLocked());
 
-       return NULL;
-}
+       BitmapMap::const_iterator iterator = fBitmapMap.find(token);
+       if (iterator == fBitmapMap.end())
+               return NULL;
 
-
-int32
-ServerApp::CountPictures() const
-{
-       return fPictureList.CountItems();
+       return iterator->second;
 }
 
 
 ServerPicture*
-ServerApp::CreatePicture(const ServerPicture* original)
+ServerApp::_FindPicture(int32 token) const
 {
-       ServerPicture* picture;
-       if (original != NULL)
-               picture = new(std::nothrow) ServerPicture(*original);
-       else
-               picture = new(std::nothrow) ServerPicture();
+       ASSERT(fMapLock.IsLocked());
 
-       if (picture != NULL)
-               fPictureList.AddItem(picture);
+       PictureMap::const_iterator iterator = fPictureMap.find(token);
+       if (iterator == fPictureMap.end())
+               return NULL;
 
-       return picture;
+       return iterator->second;
 }
-
-
-ServerPicture*
-ServerApp::FindPicture(int32 token) const
-{
-       // TODO: we need to make sure the picture is ours?!
-       ServerPicture* picture;
-       if (gTokenSpace.GetToken(token, kPictureToken, (void**)&picture) == 
B_OK)
-               return picture;
-
-       return NULL;
-}
-
-
-bool
-ServerApp::DeletePicture(int32 token)
-{
-       ServerPicture* picture = FindPicture(token);
-       if (picture == NULL)
-               return false;
-
-       if (!fPictureList.RemoveItem(picture))
-               return false;
-
-       delete picture;
-
-       return true;
-}
-
-
-team_id
-ServerApp::ClientTeam() const
-{
-       return fClientTeam;
-}

Modified: haiku/trunk/src/servers/app/ServerApp.h
===================================================================
--- haiku/trunk/src/servers/app/ServerApp.h     2009-11-04 13:05:18 UTC (rev 
33875)
+++ haiku/trunk/src/servers/app/ServerApp.h     2009-11-04 13:28:32 UTC (rev 
33876)
@@ -64,7 +64,7 @@
                        void                            
SetCurrentCursor(ServerCursor* cursor);
                        ServerCursor*           CurrentCursor() const;
 
-                       team_id                         ClientTeam() const;
+                       team_id                         ClientTeam() const { 
return fClientTeam; }
 
                        const char*                     Signature() const
                                                                        { 
return fSignature.String(); }
@@ -78,14 +78,15 @@
                        int32                           InitialWorkspace() const
                                                                        { 
return fInitialWorkspace; }
 
-                       int32                           CountBitmaps() const;
-                       ServerBitmap*           FindBitmap(int32 token) const;
+                       ServerBitmap*           GetBitmap(int32 token) const;
+                       bool                            
BitmapAdded(ServerBitmap* bitmap);
+                       void                            
BitmapRemoved(ServerBitmap* bitmap);
 
-                       int32                           CountPictures() const;
                        ServerPicture*          CreatePicture(
                                                                        const 
ServerPicture* original = NULL);
-                       ServerPicture*          FindPicture(int32 token) const;
-                       bool                            DeletePicture(int32 
token);
+                       ServerPicture*          GetPicture(int32 token) const;
+                       bool                            
PictureAdded(ServerPicture* picture);
+                       void                            
PictureRemoved(ServerPicture* picture);
 
                        Desktop*                        GetDesktop() const { 
return fDesktop; }
 
@@ -94,17 +95,23 @@
                        BPrivate::BTokenSpace& ViewTokens() { return 
fViewTokens; }
 
 private:
+       virtual void                            _GetLooperName(char* name, 
size_t size);
        virtual void                            _DispatchMessage(int32 code,
                                                                        
BPrivate::LinkReceiver& link);
        virtual void                            _MessageLooper();
-       virtual void                            _GetLooperName(char* name, 
size_t size);
                        status_t                        _CreateWindow(int32 
code,
                                                                        
BPrivate::LinkReceiver& link,
                                                                        
port_id& clientReplyPort);
 
                        bool                            _HasWindowUnderMouse();
 
+                       ServerBitmap*           _FindBitmap(int32 token) const;
+                       ServerPicture*          _FindPicture(int32 token) const;
+
 private:
+       typedef std::map<int32, ServerBitmap*> BitmapMap;
+       typedef std::map<int32, ServerPicture*> PictureMap;
+
                        port_id                         fMessagePort;
                        port_id                         fClientReplyPort;
                                                                        // our 
BApplication's event port
@@ -133,8 +140,9 @@
                        // NOTE: Bitmaps and Pictures are stored globally, but 
ServerApps
                        // remember which ones they own so that they can 
destroy them when
                        // they quit.
-                       BList                           fBitmapList;
-                       BObjectList<ServerPicture> fPictureList;
+       mutable BLocker                         fMapLocker;
+                       BitmapMap                       fBitmapMap;
+                       PictureMap                      fPictureMap;
 
                        ServerCursor*           fAppCursor;
                        ServerCursor*           fViewCursor;

Modified: haiku/trunk/src/servers/app/ServerBitmap.cpp
===================================================================
--- haiku/trunk/src/servers/app/ServerBitmap.cpp        2009-11-04 13:05:18 UTC 
(rev 33875)
+++ haiku/trunk/src/servers/app/ServerBitmap.cpp        2009-11-04 13:28:32 UTC 
(rev 33876)
@@ -15,12 +15,15 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "BitmapManager.h"
 #include "ClientMemoryAllocator.h"
 #include "ColorConversion.h"
 #include "HWInterface.h"
 #include "InterfacePrivate.h"
 #include "Overlay.h"
+#include "ServerApp.h"
 
+
 using std::nothrow;
 using namespace BPrivate;
 
@@ -127,6 +130,13 @@
 }
 
 
+void
+ServerBitmap::Release()
+{
+       gBitmapManager->DeleteBitmap(this);
+}
+
+
 bool
 ServerBitmap::_Release()
 {
@@ -212,10 +222,18 @@
 }
 
 
-void
+bool
 ServerBitmap::SetOwner(ServerApp* owner)
 {
-       fOwner = owner;
+       if (fOwner != NULL)
+               fOwner->BitmapRemoved(this);
+
+       if (owner != NULL && owner->BitmapAdded(this)) {
+               fOwner = owner;
+               return true;
+       }
+
+       return false;
 }
 
 

Modified: haiku/trunk/src/servers/app/ServerBitmap.h
===================================================================
--- haiku/trunk/src/servers/app/ServerBitmap.h  2009-11-04 13:05:18 UTC (rev 
33875)
+++ haiku/trunk/src/servers/app/ServerBitmap.h  2009-11-04 13:28:32 UTC (rev 
33876)
@@ -29,11 +29,12 @@
        all cursors. Every BBitmap has a shadow ServerBitmap object.
 */
 class ServerBitmap {
- public:
+public:
        inline  bool                    IsValid() const
                                                                { return 
fBuffer != NULL; }
 
                        void                    Acquire();
+                       void                    Release();
 
        inline  uint8*                  Bits() const
                                                                { return 
fBuffer; }
@@ -68,7 +69,7 @@
                        void                    SetOverlay(::Overlay* overlay);
                        ::Overlay*              Overlay() const;
 
-                       void                    SetOwner(ServerApp* owner);
+                       bool                    SetOwner(ServerApp* owner);
                        ServerApp*              Owner() const;
 
        //! Does a shallow copy of the bitmap passed to it
@@ -113,7 +114,7 @@
 };
 
 class UtilityBitmap : public ServerBitmap {
- public:
+public:
                                                        UtilityBitmap(BRect 
rect, color_space space,
                                                                uint32 flags, 
int32 bytesperline = -1,
                                                                screen_id 
screen = B_MAIN_SCREEN_ID);

Modified: haiku/trunk/src/servers/app/ServerPicture.cpp
===================================================================
--- haiku/trunk/src/servers/app/ServerPicture.cpp       2009-11-04 13:05:18 UTC 
(rev 33875)
+++ haiku/trunk/src/servers/app/ServerPicture.cpp       2009-11-04 13:28:32 UTC 
(rev 33876)
@@ -460,12 +460,14 @@
 draw_picture(View* view, BPoint where, int32 token)
 {
        ServerPicture* picture
-               = view->Window()->ServerWindow()->App()->FindPicture(token);
+               = view->Window()->ServerWindow()->App()->GetPicture(token);
        if (picture != NULL) {
                view->SetDrawingOrigin(where);
                view->PushState();
                picture->Play(view);
                view->PopState();
+
+               picture->ReleaseReference();
        }
 }
 
@@ -781,7 +783,8 @@
        :
        fFile(NULL),
        fPictures(NULL),
-       fUsurped(NULL)
+       fUsurped(NULL),
+       fOwner(NULL)
 {
        fToken = gTokenSpace.NewToken(kPictureToken, this);
        fData = new(std::nothrow) BMallocIO();
@@ -795,7 +798,8 @@
        fFile(NULL),
        fData(NULL),
        fPictures(NULL),

[... truncated: 392 lines follow ...]

Other related posts: