[haiku-commits] haiku: hrev48657 - src/apps/haikudepot/ui

  • From: superstippi@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sat, 10 Jan 2015 23:39:54 +0100 (CET)

hrev48657 adds 3 changesets to branch 'master'
old head: d52ab7d045a9bedb40509bf7fd67d45c46a507fe
new head: 84316965edb8b5280b5ab8997cae7240ef3526e0
overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=8431696+%5Ed52ab7d

----------------------------------------------------------------------------

05bffa6: HaikuDepot: Check thread ids before waiting for threads.
  
  These threads are not created if creating a semaphore failed, so
  it's not fixing a bug which anyone has likely encountered.

09f8290: HaikuDepot: Always init the thread ids...
  
  ... also in case creating the semaphores fails.

8431696: HaikuDepot: Populate package contents asynchronously
  
  Also remove debugging output with O(n*n) runtime. The problem for which I
  write this is already understood, but it is not yet fixed.

                                      [ Stephan Aßmus <superstippi@xxxxxx> ]

----------------------------------------------------------------------------

4 files changed, 212 insertions(+), 57 deletions(-)
src/apps/haikudepot/ui/MainWindow.cpp          |  14 +-
src/apps/haikudepot/ui/PackageContentsView.cpp | 212 +++++++++++++++++----
src/apps/haikudepot/ui/PackageContentsView.h   |  23 ++-
src/apps/haikudepot/ui/PackageInfoView.cpp     |  20 +-

############################################################################

Commit:      05bffa62e63aa5c4fcbb3c69cf5d2a8017482289
URL:         http://cgit.haiku-os.org/haiku/commit/?id=05bffa6
Author:      Stephan Aßmus <superstippi@xxxxxx>
Date:        Sat Jan 10 22:08:52 2015 UTC

HaikuDepot: Check thread ids before waiting for threads.

These threads are not created if creating a semaphore failed, so
it's not fixing a bug which anyone has likely encountered.

----------------------------------------------------------------------------

diff --git a/src/apps/haikudepot/ui/MainWindow.cpp 
b/src/apps/haikudepot/ui/MainWindow.cpp
index 7549490..f2fa790 100644
--- a/src/apps/haikudepot/ui/MainWindow.cpp
+++ b/src/apps/haikudepot/ui/MainWindow.cpp
@@ -266,14 +266,16 @@ MainWindow::~MainWindow()
        BPackageRoster().StopWatching(this);
 
        fTerminating = true;
-       if (fModelWorker > 0)
+       if (fModelWorker >= 0)
                wait_for_thread(fModelWorker, NULL);
 
        delete_sem(fPendingActionsSem);
-       wait_for_thread(fPendingActionsWorker, NULL);
+       if (fPendingActionsWorker >= 0)
+               wait_for_thread(fPendingActionsWorker, NULL);
 
        delete_sem(fPackageToPopulateSem);
-       wait_for_thread(fPopulatePackageWorker, NULL);
+       if (fPopulatePackageWorker >= 0)
+               wait_for_thread(fPopulatePackageWorker, NULL);
 
        if (fScreenshotWindow != NULL && fScreenshotWindow->Lock())
                fScreenshotWindow->Quit();

############################################################################

Commit:      09f8290534c965883f44bb0917249b760b08baa6
URL:         http://cgit.haiku-os.org/haiku/commit/?id=09f8290
Author:      Stephan Aßmus <superstippi@xxxxxx>
Date:        Sat Jan 10 22:19:25 2015 UTC

HaikuDepot: Always init the thread ids...

... also in case creating the semaphores fails.

----------------------------------------------------------------------------

diff --git a/src/apps/haikudepot/ui/MainWindow.cpp 
b/src/apps/haikudepot/ui/MainWindow.cpp
index f2fa790..742348f 100644
--- a/src/apps/haikudepot/ui/MainWindow.cpp
+++ b/src/apps/haikudepot/ui/MainWindow.cpp
@@ -611,7 +611,8 @@ MainWindow::_InitWorkerThreads()
                        "Planet Express", B_NORMAL_PRIORITY, this);
                if (fPendingActionsWorker >= 0)
                        resume_thread(fPendingActionsWorker);
-       }
+       } else
+               fPendingActionsWorker = -1;
 
        fPackageToPopulateSem = create_sem(0, "PopulatePackage");
        if (fPackageToPopulateSem >= 0) {
@@ -619,7 +620,8 @@ MainWindow::_InitWorkerThreads()
                        "Package Populator", B_NORMAL_PRIORITY, this);
                if (fPopulatePackageWorker >= 0)
                        resume_thread(fPopulatePackageWorker);
-       }
+       } else
+               fPopulatePackageWorker = -1;
 }
 
 

############################################################################

Revision:    hrev48657
Commit:      84316965edb8b5280b5ab8997cae7240ef3526e0
URL:         http://cgit.haiku-os.org/haiku/commit/?id=8431696
Author:      Stephan Aßmus <superstippi@xxxxxx>
Date:        Sat Jan 10 22:37:19 2015 UTC

HaikuDepot: Populate package contents asynchronously

Also remove debugging output with O(n*n) runtime. The problem for which I
write this is already understood, but it is not yet fixed.

----------------------------------------------------------------------------

diff --git a/src/apps/haikudepot/ui/PackageContentsView.cpp 
b/src/apps/haikudepot/ui/PackageContentsView.cpp
index e508df3..ebd8949 100644
--- a/src/apps/haikudepot/ui/PackageContentsView.cpp
+++ b/src/apps/haikudepot/ui/PackageContentsView.cpp
@@ -10,21 +10,23 @@
 
 #include <Autolock.h>
 #include <Catalog.h>
+#include <FindDirectory.h>
 #include <MessageFormat.h>
-#include <ScrollBar.h>
-#include <Window.h>
 #include <LayoutBuilder.h>
 #include <LayoutUtils.h>
 #include <OutlineListView.h>
 #include <Path.h>
+#include <ScrollBar.h>
 #include <ScrollView.h>
+#include <StringItem.h>
 
-#include <package/hpkg/PackageReader.h>
+#include <package/PackageDefs.h>
 #include <package/hpkg/NoErrorOutput.h>
 #include <package/hpkg/PackageContentHandler.h>
 #include <package/hpkg/PackageEntry.h>
-#include "MainWindow.h"
-#include "PackageAction.h"
+#include <package/hpkg/PackageReader.h>
+
+using namespace BPackageKit;
 
 using BPackageKit::BHPKG::BNoErrorOutput;
 using BPackageKit::BHPKG::BPackageContentHandler;
@@ -81,6 +83,7 @@ public:
                BStringItem(entry->Name()),
                fEntry(entry)
        {
+               printf("PackageEntryItem(%s)\n", entry->Name());
        }
        
        inline const BPackageEntry* PackageEntry() const
@@ -96,45 +99,70 @@ private:
 // #pragma mark - PackageContentOutliner
 
 
-class PackageContentsView::PackageContentOutliner
-       : public BPackageContentHandler {
-
+class PackageContentOutliner : public BPackageContentHandler {
 public:
-       PackageContentOutliner(BOutlineListView* listView)
+       PackageContentOutliner(BOutlineListView* listView,
+                       const PackageInfo* packageInfo,
+                       BLocker& packageLock, PackageInfoRef& packageInfoRef)
                :
                fListView(listView),
                fLastParentEntry(NULL),
                fLastParentItem(NULL),
                fLastEntry(NULL),
-               fLastItem(NULL)
+               fLastItem(NULL),
+
+               fPackageInfoToPopulate(packageInfo),
+               fPackageLock(packageLock),
+               fPackageInfoRef(packageInfoRef)
        {
        }
 
        virtual status_t HandleEntry(BPackageEntry* entry)
        {
+               printf("HandleEntry(%s/%s)\n",
+                       entry->Parent() != NULL ? entry->Parent()->Name() : 
"NULL",
+                       entry->Name());
+
+               {
+                       // Check if we are still supposed to popuplate the list
+                       BAutolock lock(&fPackageLock);
+                       if (fPackageInfoRef.Get() != fPackageInfoToPopulate)
+                               return B_ERROR;
+               }
+
+               if (!fListView->LockLooper())
+                       return B_ERROR;
+
                PackageEntryItem* item = new PackageEntryItem(entry);
 
                if (entry->Parent() == NULL) {
+                       printf("  adding root entry\n");
                        fListView->AddItem(item);
+                       fLastParentEntry = NULL;
+                       fLastParentItem = NULL;
                } else if (entry->Parent() == fLastEntry) {
+                       printf("  adding to last entry %s\n", 
fLastEntry->Name());
                        fListView->AddUnder(item, fLastItem);
                        fLastParentEntry = fLastEntry;
                        fLastParentItem = fLastItem;
                } else if (entry->Parent() == fLastParentEntry) {
+                       printf("  adding to last parent %s\n", 
fLastParentEntry->Name());
                        fListView->AddUnder(item, fLastParentItem);
                } else {
                        // Not the last parent entry, need to search for the 
parent
                        // among the already added list items.
                        bool foundParent = false;
-                       for (int32 i = 0; i < fListView->CountItems(); i++) {
+                       for (int32 i = 0; i < fListView->FullListCountItems(); 
i++) {
                                PackageEntryItem* listItem
-                                       = 
dynamic_cast<PackageEntryItem*>(fListView->ItemAt(i));
+                                       = dynamic_cast<PackageEntryItem*>(
+                                               fListView->FullListItemAt(i));
                                if (listItem == NULL)
                                        continue;
                                if (listItem->PackageEntry() == 
entry->Parent()) {
                                        fLastParentEntry = 
listItem->PackageEntry();
                                        fLastParentItem = listItem;
-                                       fListView->AddUnder(item, 
fLastParentItem);
+                                       printf("  found parent %s\n", 
listItem->Text());
+                                       fListView->AddUnder(item, listItem);
                                        foundParent = true;
                                        break;
                                }
@@ -145,12 +173,16 @@ public:
                                printf("Did not find parent entry for %s 
(%s)!\n",
                                        entry->Name(), entry->Parent()->Name());
                                fListView->AddItem(item);
+                               fLastParentEntry = NULL;
+                               fLastParentItem = NULL;
                        }
                }
 
                fLastEntry = entry;
                fLastItem = item;
 
+               fListView->UnlockLooper();
+
                return B_OK;
        }
 
@@ -183,6 +215,10 @@ private:
 
        const BPackageEntry*    fLastEntry;
        PackageEntryItem*               fLastItem;
+
+       const PackageInfo*              fPackageInfoToPopulate;
+       BLocker&                                fPackageLock;
+       PackageInfoRef&                 fPackageInfoRef;
 };
 
 
@@ -192,7 +228,7 @@ private:
 PackageContentsView::PackageContentsView(const char* name)
        :
        BView("package_contents_view", B_WILL_DRAW),
-       fLayout(new BGroupLayout(B_HORIZONTAL))
+       fPackageLock("package contents populator lock")
 {
        fContentListView = new BOutlineListView("content list view", 
                B_SINGLE_SELECTION_LIST);
@@ -204,12 +240,18 @@ PackageContentsView::PackageContentsView(const char* name)
                .Add(scrollView, 1.0f)
                .SetInsets(0.0f, -1.0f, -1.0f, -1.0f)
        ;
+
+       _InitContentPopulator();
 }
 
 
 PackageContentsView::~PackageContentsView()
 {
        Clear();
+
+       delete_sem(fContentPopulatorSem);
+       if (fContentPopulator >= 0)
+               wait_for_thread(fContentPopulator, NULL);
 }
 
 
@@ -228,39 +270,135 @@ PackageContentsView::AllAttached()
 
 
 void
-PackageContentsView::SetPackage(const PackageInfo& package)
+PackageContentsView::SetPackage(const PackageInfoRef& package)
 {
+       if (fPackage == package)
+               return;
+
+       printf("PackageContentsView::SetPackage(%s)\n",
+               package.Get() != NULL ? package->Title().String() : "NULL");
+
        Clear();
 
-       if (package.IsLocalFile() ) {
+       {
+               BAutolock lock(&fPackageLock);
+               fPackage = package;
+       }
+       release_sem_etc(fContentPopulatorSem, 1, 0);
+}
+
+
+void 
+PackageContentsView::Clear()
+{
+       {
+               BAutolock lock(&fPackageLock);
+               fPackage.Unset();
+       }
+
+       fContentListView->MakeEmpty();
+}
+
+
+// #pragma mark - private
+
+
+void
+PackageContentsView::_InitContentPopulator()
+{
+       fContentPopulatorSem = create_sem(0, "PopulatePackageContents");
+       if (fContentPopulatorSem >= 0) {
+               fContentPopulator = spawn_thread(&_ContentPopulatorThread,
+                       "Package Contents Populator", B_NORMAL_PRIORITY, this);
+               if (fContentPopulator >= 0)
+                       resume_thread(fContentPopulator);
+       } else
+               fContentPopulator = -1;
+}
+
+
+/*static*/ int32
+PackageContentsView::_ContentPopulatorThread(void* arg)
+{
+       PackageContentsView* view = reinterpret_cast<PackageContentsView*>(arg);
+
+       while (acquire_sem(view->fContentPopulatorSem) == B_OK) {
+               PackageInfoRef package;
+               {
+                       BAutolock lock(&view->fPackageLock);
+                       package = view->fPackage;
+               }
+
+               if (package.Get() != NULL)
+                       view->_PopuplatePackageContens(*package.Get());
+       }
+
+       return 0;
+}
+
+
+void
+PackageContentsView::_PopuplatePackageContens(const PackageInfo& package)
+{
+       BPath packagePath;
+
+       // Obtain path to the package file
+       if (package.IsLocalFile()) {
                BString pathString = package.LocalFilePath();
-               BPath packagePath;
                packagePath.SetTo(pathString.String());
-       
-               BNoErrorOutput errorOutput;
-               BPackageReader reader(&errorOutput);
-       
-               status_t status = reader.Init(packagePath.Path());
-               if (status != B_OK) {
-                       printf("PackageContentsView::SetPackage(): failed to 
init "
-                               "BPackageReader(%s): %s\n",
-                               packagePath.Path(), strerror(status));
+       } else {
+               int32 installLocation = _InstallLocation(package);
+               if (installLocation == B_PACKAGE_INSTALLATION_LOCATION_SYSTEM) {
+                       if (find_directory(B_SYSTEM_PACKAGES_DIRECTORY, 
&packagePath)
+                               != B_OK) {
+                               return;
+                       }
+               } else if (installLocation == 
B_PACKAGE_INSTALLATION_LOCATION_HOME) {
+                       if (find_directory(B_USER_PACKAGES_DIRECTORY, 
&packagePath)
+                               != B_OK) {
+                               return;
+                       }
+               } else {
+                       
printf("PackageContentsView::_PopuplatePackageContens(): "
+                               "unknown install location");
                        return;
                }
-       
-               // Scan package contents and populate list
-               PackageContentOutliner contentHandler(fContentListView);
-               status = reader.ParseContent(&contentHandler);
-               if (status != B_OK) {
-                       printf("PackageContentsView::SetPackage(): "
-                               "failed parse package contents: %s\n", 
strerror(status));
-               }
+
+               packagePath.Append(package.FileName());
+       }
+
+       // Setup a BPackageReader
+       BNoErrorOutput errorOutput;
+       BPackageReader reader(&errorOutput);
+
+       status_t status = reader.Init(packagePath.Path());
+       if (status != B_OK) {
+               printf("PackageContentsView::_PopuplatePackageContens(): "
+                       "failed to init BPackageReader(%s): %s\n",
+                       packagePath.Path(), strerror(status));
+               return;
+       }
+
+       // Scan package contents and populate list
+       PackageContentOutliner contentHandler(fContentListView, &package,
+               fPackageLock, fPackage);
+       status = reader.ParseContent(&contentHandler);
+       if (status != B_OK) {
+               printf("PackageContentsView::SetPackage(): "
+                       "failed parse package contents: %s\n", 
strerror(status));
        }
 }
 
 
-void 
-PackageContentsView::Clear()
+int32
+PackageContentsView::_InstallLocation(const PackageInfo& package) const
 {
-       fContentListView->MakeEmpty();
+       const PackageInstallationLocationSet& locations
+               = package.InstallationLocations();
+
+       // If the package is already installed, return its first installed 
location
+       if (locations.size() != 0)
+               return *locations.begin();
+
+       return B_PACKAGE_INSTALLATION_LOCATION_SYSTEM;
 }
diff --git a/src/apps/haikudepot/ui/PackageContentsView.h 
b/src/apps/haikudepot/ui/PackageContentsView.h
index d311c2a..b80fe71 100644
--- a/src/apps/haikudepot/ui/PackageContentsView.h
+++ b/src/apps/haikudepot/ui/PackageContentsView.h
@@ -5,10 +5,13 @@
 #ifndef PACKAGE_CONTENTS_VIEW_H
 #define PACKAGE_CONTENTS_VIEW_H
 
-#include <OutlineListView.h>
+#include <Locker.h>
 #include <View.h>
+
 #include "PackageInfo.h"
-#include "ScrollableGroupView.h"
+
+class BOutlineListView;
+
 
 class PackageContentsView : public BView {
 public:
@@ -18,14 +21,24 @@ public:
        virtual void                            AttachedToWindow();
        virtual void                            AllAttached();
 
-                       void                            SetPackage(const 
PackageInfo& package);
+                       void                            SetPackage(const 
PackageInfoRef& package);
                        void                            Clear();
 
 private:
-                       class PackageContentOutliner;
+                       void                            _InitContentPopulator();
+       static  int32                           _ContentPopulatorThread(void* 
arg);
+                       void                            
_PopuplatePackageContens(
+                                                                       const 
PackageInfo& package);
+                       int32                           _InstallLocation(
+                                                                       const 
PackageInfo& package) const;
 
-                       BGroupLayout*           fLayout;
+private:
                        BOutlineListView*       fContentListView;
+
+                       thread_id                       fContentPopulator;
+                       sem_id                          fContentPopulatorSem;
+                       BLocker                         fPackageLock;
+                       PackageInfoRef          fPackage;
 };
 
 #endif // PACKAGE_CONTENTS_VIEW_H
diff --git a/src/apps/haikudepot/ui/PackageInfoView.cpp 
b/src/apps/haikudepot/ui/PackageInfoView.cpp
index 95e615b..821406a 100644
--- a/src/apps/haikudepot/ui/PackageInfoView.cpp
+++ b/src/apps/haikudepot/ui/PackageInfoView.cpp
@@ -1191,7 +1191,7 @@ public:
        {
        }
 
-       void SetPackage(const PackageInfo& package)
+       void SetPackage(const PackageInfoRef& package)
        {
                fPackageContents->SetPackage(package);
        }
@@ -1294,13 +1294,13 @@ public:
                Clear();
        }
 
-       void SetPackage(const PackageInfo& package, bool switchToDefaultTab)
+       void SetPackage(const PackageInfoRef& package, bool switchToDefaultTab)
        {
                if (switchToDefaultTab)
                        Select(0);
-               fAboutView->SetPackage(package);
-               fUserRatingsView->SetPackage(package);
-               fChangelogView->SetPackage(package);
+               fAboutView->SetPackage(*package.Get());
+               fUserRatingsView->SetPackage(*package.Get());
+               fChangelogView->SetPackage(*package.Get());
                fContentsView->SetPackage(package);
        }
 
@@ -1404,8 +1404,8 @@ PackageInfoView::MessageReceived(BMessage* message)
                                break;
                        }
 
-                       const PackageInfo& package = 
*fPackageListener->Package().Get();
-                       if (package.Title() != title)
+                       const PackageInfoRef& package = 
fPackageListener->Package();
+                       if (package->Title() != title)
                                break;
 
                        BAutolock _(fModelLock);
@@ -1417,11 +1417,11 @@ PackageInfoView::MessageReceived(BMessage* message)
 
                        if ((changes & PKG_CHANGED_RATINGS) != 0) {
                                fPagesView->SetPackage(package, false);
-                               fTitleView->SetPackage(package);
+                               fTitleView->SetPackage(*package.Get());
                        }
 
                        if ((changes & PKG_CHANGED_STATE) != 0) {
-                               fPackageActionView->SetPackage(package);
+                               fPackageActionView->SetPackage(*package.Get());
                        }
 
                        break;
@@ -1445,7 +1445,7 @@ PackageInfoView::SetPackage(const PackageInfoRef& 
packageRef)
 
        fTitleView->SetPackage(package);
        fPackageActionView->SetPackage(package);
-       fPagesView->SetPackage(package, switchToDefaultTab);
+       fPagesView->SetPackage(packageRef, switchToDefaultTab);
 
        fCardLayout->SetVisibleItem(1);
 


Other related posts:

  • » [haiku-commits] haiku: hrev48657 - src/apps/haikudepot/ui - superstippi