[Haiku-commits] r21462 - haiku/trunk/src/kits/tracker

mmlr at BerliOS mmlr at mail.berlios.de
Tue Jun 19 11:33:30 CEST 2007


Author: mmlr
Date: 2007-06-19 11:33:29 +0200 (Tue, 19 Jun 2007)
New Revision: 21462
ViewCVS: http://svn.berlios.de/viewcvs/haiku?rev=21462&view=rev

Modified:
   haiku/trunk/src/kits/tracker/Pose.cpp
   haiku/trunk/src/kits/tracker/Pose.h
   haiku/trunk/src/kits/tracker/PoseList.cpp
   haiku/trunk/src/kits/tracker/PoseList.h
   haiku/trunk/src/kits/tracker/PoseView.cpp
   haiku/trunk/src/kits/tracker/PoseView.h
   haiku/trunk/src/kits/tracker/SettingsViews.cpp
   haiku/trunk/src/kits/tracker/Tracker.cpp
   haiku/trunk/src/kits/tracker/Utilities.cpp
   haiku/trunk/src/kits/tracker/Utilities.h
Log:
Reworked the handling of periodically updated poses (currently only ones with a volume space bar):

* Addad global list where poses that need periodic updates can be registered with a callback
* Use this mechanism for poses with a volume space bar
* Create only one BVolume when the BPose is created for a volume, instead of every time the free space is calculated
* On Pulse() the global list is used to update all of the registered periodic update poses
* As the poses know their volume, it is no longer necessary to use a BVolumeRoster to loop through each volume on each Pulse()
* Removed the now superfluous SendNotices() mechanism
* Removed corresponding watching / handling of these notices in BPoseView

The BPoseView did a linear search for each volume pose on each Pulse() before. What's more it did this once for each mounted volume as it did get one individual notice for each of them. To get these volumes a BVolumeRoster was used to loop through the volumes, but then the BPose did still create a new BVolume to actually calculate the free space! I'm surprised that it did not suck away more performance with this method...

Anyway, this should bring down BVolume construction and update overhead down to a minimum and hopefully fix ticket #1247.

Modified: haiku/trunk/src/kits/tracker/Pose.cpp
===================================================================
--- haiku/trunk/src/kits/tracker/Pose.cpp	2007-06-18 23:58:15 UTC (rev 21461)
+++ haiku/trunk/src/kits/tracker/Pose.cpp	2007-06-19 09:33:29 UTC (rev 21462)
@@ -49,32 +49,15 @@
 
 
 int32
-CalcFreeSpace(dev_t device)
+CalcFreeSpace(BVolume *volume)
 {
-	BVolume volume(device);
-	fs_info info;
-	if (volume.InitCheck() == B_OK && fs_stat_dev(device,&info) == B_OK) {
-		// Philosophy here:
-		// Bars go on all drives with read/write capabilities
-		// Exceptions: Not on CDDA, but on NTFS/Ext2
-		// Also note that some volumes may return 0 when
-		// BVolume::Capacity() is called (believe-me... That *DOES*
-		// happen) so we also check for that.
-		off_t capacity = volume.Capacity();
-		if (((!volume.IsReadOnly() && strcmp(info.fsh_name,"cdda"))
-			|| !strcmp(info.fsh_name,"ntfs")
-			|| !strcmp(info.fsh_name,"ext2"))
-			&& (capacity > 0)) {
-			int32 percent = static_cast<int32>(volume.FreeBytes() / (capacity / 100));
+	off_t capacity = volume->Capacity();
+	int32 percent = static_cast<int32>(volume->FreeBytes() / (capacity / 100));
 
-			// warn below 20 MB of free space (if this is less than 10% of free space)
-			if (volume.FreeBytes() < 20 * 1024 * 1024 && percent < 10)
-				return -2 - percent;
-
-			return percent;
-		}
-	}
-	return -1;
+	// warn below 20 MB of free space (if this is less than 10% of free space)
+	if (volume->FreeBytes() < 20 * 1024 * 1024 && percent < 10)
+		return -2 - percent;
+	return percent;
 }
 
 
@@ -98,9 +81,32 @@
 {
 	CreateWidgets(view);
 
-	if (model->IsVolume() && TrackerSettings().ShowVolumeSpaceBar()) {
+	if (model->IsVolume()) {
+		fs_info info;
 		dev_t device = model->NodeRef()->device;
-		fPercent = CalcFreeSpace(device);
+		BVolume *volume = new BVolume(device);
+		if (volume->InitCheck() == B_OK
+			&& fs_stat_dev(device, &info) == B_OK) {
+			// Philosophy here:
+			// Bars go on all drives with read/write capabilities
+			// Exceptions: Not on CDDA, but on NTFS/Ext2
+			// Also note that some volumes may return 0 when
+			// BVolume::Capacity() is called (believe-me... That *DOES*
+			// happen) so we also check for that.
+			off_t capacity = volume->Capacity();
+			if (((!volume->IsReadOnly() && strcmp(info.fsh_name,"cdda"))
+				|| !strcmp(info.fsh_name,"ntfs")
+				|| !strcmp(info.fsh_name,"ext2"))
+				&& capacity > 0) {
+				// The volume is ok and we want space bars on it
+				gPeriodicUpdatePoses.AddPose(this, view,
+					_PeriodicUpdateCallback, volume);
+				if (TrackerSettings().ShowVolumeSpaceBar())
+					fPercent = CalcFreeSpace(volume);
+			} else
+				delete volume;
+		} else
+			delete volume;
 	}
 
 	if ((fClipboardMode = FSClipboardFindNodeMode(model,true)) != 0
@@ -112,6 +118,13 @@
 
 BPose::~BPose()
 {
+	if (fModel->IsVolume()) {
+		// we might be registered for periodic updates
+		BVolume *volume = NULL;
+		if (gPeriodicUpdatePoses.RemovePose(this, (void **)&volume))
+			delete volume;
+	}
+
 	delete fModel;
 }
 
@@ -285,8 +298,16 @@
 
 
 bool
-BPose::UpdateVolumeSpaceBar(bool enabled)
+BPose::_PeriodicUpdateCallback(BPose *pose, void *cookie)
 {
+	return pose->UpdateVolumeSpaceBar((BVolume *)cookie);
+}
+
+
+bool
+BPose::UpdateVolumeSpaceBar(BVolume *volume)
+{
+	bool enabled = TrackerSettings().ShowVolumeSpaceBar();
 	if (!enabled) {
 		if (fPercent == -1)
 			return false;
@@ -295,9 +316,7 @@
 		return true;
 	}
 
-	dev_t device = TargetModel()->NodeRef()->device;
-	int32 percent = CalcFreeSpace(device);
-
+	int32 percent = CalcFreeSpace(volume);
 	if (fPercent != percent) {
 		if (percent > 100)
 			fPercent = 100;

Modified: haiku/trunk/src/kits/tracker/Pose.h
===================================================================
--- haiku/trunk/src/kits/tracker/Pose.h	2007-06-18 23:58:15 UTC (rev 21461)
+++ haiku/trunk/src/kits/tracker/Pose.h	2007-06-19 09:33:29 UTC (rev 21462)
@@ -96,7 +96,7 @@
 		void UpdateAllWidgets(int32 poseIndex, BPoint poseLoc, BPoseView *);
 		void UpdateWidgetAndModel(Model *resolvedModel, const char *attrName,
 				uint32 attrType, int32 poseIndex, BPoint poseLoc, BPoseView *view);
-		bool UpdateVolumeSpaceBar(bool enabled);
+		bool UpdateVolumeSpaceBar(BVolume *volume);
 		void UpdateIcon(BPoint poseLoc, BPoseView *);
 
 		//void UpdateFixedSymlink(BPoint poseLoc, BPoseView *);	
@@ -126,6 +126,7 @@
 #endif
 
 	private:
+		static bool _PeriodicUpdateCallback(BPose *pose, void *cookie);
 		void EditPreviousNextWidgetCommon(BPoseView *poseView, bool next);
 		void CreateWidgets(BPoseView *);
 		bool TestLargeIconPixel(BPoint) const;

Modified: haiku/trunk/src/kits/tracker/PoseList.cpp
===================================================================
--- haiku/trunk/src/kits/tracker/PoseList.cpp	2007-06-18 23:58:15 UTC (rev 21461)
+++ haiku/trunk/src/kits/tracker/PoseList.cpp	2007-06-19 09:33:29 UTC (rev 21462)
@@ -105,20 +105,3 @@
 
 	return NULL;
 }
-
-BPose *
-PoseList::FindVolumePose(const dev_t device, int32 *resultingIndex) const
-{
-	int32 count = CountItems();
-	for (int32 index = 0; index < count; index++) {
-		BPose *pose = ItemAt(index);
-		Model *model = pose->TargetModel();
-		ASSERT(model);
-		if (model->IsVolume() && model->NodeRef()->device == device) {
-			if (resultingIndex)
-				*resultingIndex = index;
-			return pose;
-		}
-	}
-	return NULL;
-}

Modified: haiku/trunk/src/kits/tracker/PoseList.h
===================================================================
--- haiku/trunk/src/kits/tracker/PoseList.h	2007-06-18 23:58:15 UTC (rev 21461)
+++ haiku/trunk/src/kits/tracker/PoseList.h	2007-06-19 09:33:29 UTC (rev 21462)
@@ -64,7 +64,6 @@
 	BPose *DeepFindPose(const node_ref *node, int32 *index = NULL) const;
 		// same as FindPose, node can be a target of the actual
 		// pose if the pose is a symlink
-	BPose *FindVolumePose(const dev_t device, int32 *index = NULL) const;
 };
 
 // iteration glue, add permutations as needed

Modified: haiku/trunk/src/kits/tracker/PoseView.cpp
===================================================================
--- haiku/trunk/src/kits/tracker/PoseView.cpp	2007-06-18 23:58:15 UTC (rev 21461)
+++ haiku/trunk/src/kits/tracker/PoseView.cpp	2007-06-19 09:33:29 UTC (rev 21462)
@@ -803,9 +803,6 @@
 		app->StopWatching(this, kShowSelectionWhenInactiveChanged);
 		app->StopWatching(this, kTransparentSelectionChanged);
 		app->StopWatching(this, kSortFolderNamesFirstChanged);
-		app->StopWatching(this, kShowVolumeSpaceBar);
-		app->StopWatching(this, kSpaceBarColorChanged);
-		app->StopWatching(this, kUpdateVolumeSpaceBar);
 		app->Unlock();
 	}
 
@@ -890,9 +887,6 @@
 		app->StartWatching(this, kShowSelectionWhenInactiveChanged);
 		app->StartWatching(this, kTransparentSelectionChanged);
 		app->StartWatching(this, kSortFolderNamesFirstChanged);
-		app->StartWatching(this, kShowVolumeSpaceBar);
-		app->StartWatching(this, kSpaceBarColorChanged);
-		app->StartWatching(this, kUpdateVolumeSpaceBar);
 		app->Unlock();
 	}
 
@@ -2331,20 +2325,6 @@
 							Invalidate();
 						}
 						break;
-
-					case kShowVolumeSpaceBar:
-						bool enabled;
-						if (message->FindBool("ShowVolumeSpaceBar", &enabled) == B_OK)
-							TrackerSettings().SetShowVolumeSpaceBar(enabled);
-						// supposed to fall through
-					case kSpaceBarColorChanged:
-						UpdateVolumeIcons();
-						break;
-					case kUpdateVolumeSpaceBar:
-						dev_t device;
-						message->FindInt32("device", (int32 *)&device);
-						UpdateVolumeIcon(device);	
-						break;
 				}
 			}
 			break;
@@ -5214,34 +5194,21 @@
 
 
 void 
-BPoseView::UpdateVolumeIcon(dev_t device, bool forceUpdate)
+BPoseView::UpdateIcon(BPose *pose)
 {
-	int32 index;
-	BPose *pose = fPoseList->FindVolumePose(device,&index);
-	if (pose == NULL)
-		return;
-
-	if (pose->UpdateVolumeSpaceBar(TrackerSettings().ShowVolumeSpaceBar()) || forceUpdate) {
-		BPoint loc(0, index * fListElemHeight);
-		pose->UpdateIcon(loc, this);
+	BPoint location;
+	if (ViewMode() == kListMode) {
+		// need to find the index of the pose in the pose list
+		int32 count = fPoseList->CountItems();
+		for (int32 index = 0; index < count; index++) {
+			if (fPoseList->ItemAt(index) == pose) {
+				location.Set(0, index * fListElemHeight);
+				break;
+			}
+		}
 	}
-}
 
-
-void 
-BPoseView::UpdateVolumeIcons()
-{
-	BVolumeRoster roster;
-
-	BVolume volume;
-	while(roster.GetNextVolume(&volume) == B_NO_ERROR) {
-		BDirectory dir;
-		volume.GetRootDirectory(&dir);
-		node_ref nodeRef;
-		dir.GetNodeRef(&nodeRef);
-
-		UpdateVolumeIcon(nodeRef.device, true);
-	}
+	pose->UpdateIcon(location, this);
 }
 
 

Modified: haiku/trunk/src/kits/tracker/PoseView.h
===================================================================
--- haiku/trunk/src/kits/tracker/PoseView.h	2007-06-18 23:58:15 UTC (rev 21461)
+++ haiku/trunk/src/kits/tracker/PoseView.h	2007-06-19 09:33:29 UTC (rev 21462)
@@ -159,8 +159,7 @@
 		void SetAutoScroll(bool);
 		void SetPoseEditing(bool);
 
-		void UpdateVolumeIcon(dev_t device, bool forceUpdate = false);
-		void UpdateVolumeIcons();
+		void UpdateIcon(BPose *pose);
 
 		// file change notification handler
 		virtual bool FSNotification(const BMessage *);

Modified: haiku/trunk/src/kits/tracker/SettingsViews.cpp
===================================================================
--- haiku/trunk/src/kits/tracker/SettingsViews.cpp	2007-06-18 23:58:15 UTC (rev 21461)
+++ haiku/trunk/src/kits/tracker/SettingsViews.cpp	2007-06-19 09:33:29 UTC (rev 21462)
@@ -1072,9 +1072,7 @@
 		{
 			settings.SetShowVolumeSpaceBar(fSpaceBarShowCheckBox->Value() == 1);
 			Window()->PostMessage(kSettingsContentsModified);
-			BMessage notificationMessage;
-			notificationMessage.AddBool("ShowVolumeSpaceBar", settings.ShowVolumeSpaceBar());
-			tracker->SendNotices(kShowVolumeSpaceBar, &notificationMessage);
+			tracker->PostMessage(kShowVolumeSpaceBar);
 			break;
 		}
 
@@ -1094,6 +1092,7 @@
 			}
 			break;
 		}
+
 		case kSpaceBarColorChanged:
 		{
 			switch (fCurrentColor) {
@@ -1109,8 +1108,7 @@
 			}
 
 			Window()->PostMessage(kSettingsContentsModified);
-			BMessage notificationMessage;
-			tracker->SendNotices(kSpaceBarColorChanged, &notificationMessage);
+			tracker->PostMessage(kSpaceBarColorChanged);
 			break;
 		}
 

Modified: haiku/trunk/src/kits/tracker/Tracker.cpp
===================================================================
--- haiku/trunk/src/kits/tracker/Tracker.cpp	2007-06-18 23:58:15 UTC (rev 21461)
+++ haiku/trunk/src/kits/tracker/Tracker.cpp	2007-06-19 09:33:29 UTC (rev 21462)
@@ -483,6 +483,12 @@
 			break;
 		}
 
+		case kShowVolumeSpaceBar:
+		case kSpaceBarColorChanged: {
+			gPeriodicUpdatePoses.DoPeriodicUpdate(true);
+			break;
+		}
+
 		default:
 			_inherited::MessageReceived(message);
 			break;
@@ -497,20 +503,7 @@
 		return;
 
 	// update the volume icon's free space bars
-	BVolumeRoster roster;
-
- 	BVolume volume;
-	while (roster.GetNextVolume(&volume) == B_OK) {
-		BDirectory dir;
-		volume.GetRootDirectory(&dir);
-		node_ref nodeRef;
-		dir.GetNodeRef(&nodeRef);
-
-		BMessage notificationMessage;
-		notificationMessage.AddInt32("device", *(int32 *)&nodeRef.device);
-
-		SendNotices(kUpdateVolumeSpaceBar, &notificationMessage);
-	}
+	gPeriodicUpdatePoses.DoPeriodicUpdate(false);
 }
 
 

Modified: haiku/trunk/src/kits/tracker/Utilities.cpp
===================================================================
--- haiku/trunk/src/kits/tracker/Utilities.cpp	2007-06-18 23:58:15 UTC (rev 21461)
+++ haiku/trunk/src/kits/tracker/Utilities.cpp	2007-06-19 09:33:29 UTC (rev 21462)
@@ -35,6 +35,7 @@
 #include "Attributes.h"
 #include "MimeTypes.h"
 #include "Model.h"
+#include "PoseView.h"
 #include "Utilities.h"
 #include "ContainerWindow.h"
 
@@ -158,7 +159,81 @@
 	textView->DisallowChar(B_PAGE_DOWN);
 	textView->DisallowChar(B_FUNCTION_KEY);
 }
- 
+
+
+PeriodicUpdatePoses::PeriodicUpdatePoses()
+	:	fPoseList(20, true)
+{
+	fLock = new Benaphore("PeriodicUpdatePoses");
+}
+
+
+PeriodicUpdatePoses::~PeriodicUpdatePoses()
+{
+	fLock->Lock();
+	fPoseList.MakeEmpty();
+	delete fLock;
+}
+
+
+void
+PeriodicUpdatePoses::AddPose(BPose *pose, BPoseView *poseView,
+	PeriodicUpdateCallback callback, void *cookie)
+{
+	periodic_pose *periodic = new periodic_pose;
+	periodic->pose = pose;
+	periodic->pose_view = poseView;
+	periodic->callback = callback;
+	periodic->cookie = cookie;
+	fPoseList.AddItem(periodic);
+}
+
+
+bool
+PeriodicUpdatePoses::RemovePose(BPose *pose, void **cookie)
+{
+	int32 count = fPoseList.CountItems();
+	for (int32 index = 0; index < count; index++) {
+		if (fPoseList.ItemAt(index)->pose == pose) {
+			if (!fLock->Lock())
+				return false;
+
+			periodic_pose *periodic = fPoseList.RemoveItemAt(index);
+			if (cookie)
+				*cookie = periodic->cookie;
+			delete periodic;
+			fLock->Unlock();
+			return true;
+		}
+	}
+
+	return false;
+}
+
+
+void
+PeriodicUpdatePoses::DoPeriodicUpdate(bool forceRedraw)
+{
+	if (!fLock->Lock())
+		return;
+
+	int32 count = fPoseList.CountItems();
+	for (int32 index = 0; index < count; index++) {
+		periodic_pose *periodic = fPoseList.ItemAt(index);
+		if (periodic->callback(periodic->pose, periodic->cookie)
+			|| forceRedraw) {
+			periodic->pose_view->LockLooper();
+			periodic->pose_view->UpdateIcon(periodic->pose);
+			periodic->pose_view->UnlockLooper();
+		}
+	}
+
+	fLock->Unlock();
+}
+
+
+static PeriodicUpdatePoses gPeriodicUpdatePoses;
+
 }	// namespace BPrivate
 
 

Modified: haiku/trunk/src/kits/tracker/Utilities.h
===================================================================
--- haiku/trunk/src/kits/tracker/Utilities.h	2007-06-18 23:58:15 UTC (rev 21461)
+++ haiku/trunk/src/kits/tracker/Utilities.h	2007-06-19 09:33:29 UTC (rev 21462)
@@ -46,6 +46,7 @@
 #include <MenuItem.h>
 #include <MessageFilter.h>
 #include <Mime.h>
+#include <ObjectList.h>
 #include <Point.h>
 #include <Path.h>
 #include <String.h>
@@ -62,6 +63,8 @@
 namespace BPrivate {
 
 class Benaphore;
+class BPose;
+class BPoseView;
 
 // global variables
 extern const rgb_color kBlack;
@@ -83,6 +86,38 @@
 
 // misc typedefs, constants and structs
 
+// Periodically updated poses (ones with a volume space bar) register
+// themselfs in this global list. This way they can be iterated over instead
+// of sending around update messages.
+
+class PeriodicUpdatePoses {
+	public:
+		PeriodicUpdatePoses();
+		~PeriodicUpdatePoses();
+
+		typedef bool (*PeriodicUpdateCallback)(BPose *pose, void *cookie);
+
+		void AddPose(BPose *pose, BPoseView *poseView,
+			PeriodicUpdateCallback callback, void *cookie);
+		bool RemovePose(BPose *pose, void **cookie);
+
+		void DoPeriodicUpdate(bool forceRedraw);
+
+	private:
+		struct periodic_pose {
+			BPose					*pose;
+			BPoseView				*pose_view;
+			PeriodicUpdateCallback	callback;
+			void					*cookie;
+		};
+
+		Benaphore *fLock;
+		BObjectList<periodic_pose> fPoseList;
+};
+
+extern PeriodicUpdatePoses gPeriodicUpdatePoses;
+
+
 // PoseInfo is the structure that gets saved as attributes for every node on
 // disk, defining the node's position and visibility
 class PoseInfo {




More information about the Haiku-commits mailing list