adium-1.4 3161:c959997fcffb: Delay list object notifications as ...
commits at adium.im
commits at adium.im
Sat Oct 30 04:47:31 UTC 2010
details: http://hg.adium.im/adium-1.4/rev/c959997fcffb
revision: 3161:c959997fcffb
author: Evan Schoenberg
date: Fri Oct 29 23:44:34 2010 -0500
Delay list object notifications as libpurple initializes; it can be expensive in terms of adding contacts from the permit and deny lists. Also, include a delayListObjectNotificationsUntilInactivity call as a few behaviors occur on the next runloop
Subject: adium-1.4 3162:cbd40f45797a: Several fixes related to listObjectAttributesChanged:
details: http://hg.adium.im/adium-1.4/rev/cbd40f45797a
revision: 3162:cbd40f45797a
author: Evan Schoenberg
date: Fri Oct 29 23:47:23 2010 -0500
Several fixes related to listObjectAttributesChanged:
* Fix an abysmal bug in which we were deliberately calling _performDelayedUpdates: when shouldDelayUpdates was YES instead of when it was NO
* Add a ListObject_AttributeChangesComplete notification to let us distinguish a change for a particular object (which always notifies for that object) from a group of changes which should trigger a display update.
* Add a grace period for delayListObjectNotificationsUntilInactivity; previously a 1 second delay was enough to make all delays stop, which was bad if we had a network halt during a connection as subsequent contacts would appear to sign on one-by-one, with all the costs that entails. The grace period is 3 seconds.
diffs (247 lines):
diff -r a3fcb0d5b61e -r cbd40f45797a Frameworks/Adium Framework/Source/AIAbstractListController.h
--- a/Frameworks/Adium Framework/Source/AIAbstractListController.h Fri Oct 29 22:36:16 2010 -0500
+++ b/Frameworks/Adium Framework/Source/AIAbstractListController.h Fri Oct 29 23:47:23 2010 -0500
@@ -218,7 +218,7 @@
- (void)updateLayoutFromPrefDict:(NSDictionary *)prefDict andThemeFromPrefDict:(NSDictionary *)themeDict;
- (void)updateCellRelatedThemePreferencesFromDict:(NSDictionary *)prefDict;
-- (void)listObjectAttributesChanged:(NSNotification *)notification;
+- (void)listObjectAttributeChangesComplete:(NSNotification *)notification;
- (void)contactListDesiredSizeChanged;
- (void)updateTransparency;
- (BOOL)useAliasesInContactListAsRequested;
diff -r a3fcb0d5b61e -r cbd40f45797a Frameworks/Adium Framework/Source/AIAbstractListController.m
--- a/Frameworks/Adium Framework/Source/AIAbstractListController.m Fri Oct 29 22:36:16 2010 -0500
+++ b/Frameworks/Adium Framework/Source/AIAbstractListController.m Fri Oct 29 23:47:23 2010 -0500
@@ -96,8 +96,8 @@
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(listObjectAttributesChanged:)
- name:ListObject_AttributesChanged
+ selector:@selector(listObjectAttributeChangesComplete:)
+ name:ListObject_AttributeChangesComplete
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
@@ -577,12 +577,12 @@
*
* Redisplay the object in question
*/
-- (void)listObjectAttributesChanged:(NSNotification *)notification
+- (void)listObjectAttributeChangesComplete:(NSNotification *)notification
{
AIListObject *object = [notification object];
static int listObjectAttributesChangedNum = 0;
- NSLog(@"listObjectAttributesChanged #%i: %@ [%@]",
+ NSLog(@"listObjectAttributeChangesComplete #%i: %@ [%@]",
++listObjectAttributesChangedNum,
object, [[notification userInfo] objectForKey:@"Keys"]);
diff -r a3fcb0d5b61e -r cbd40f45797a Frameworks/Adium Framework/Source/AIContactControllerProtocol.h
--- a/Frameworks/Adium Framework/Source/AIContactControllerProtocol.h Fri Oct 29 22:36:16 2010 -0500
+++ b/Frameworks/Adium Framework/Source/AIContactControllerProtocol.h Fri Oct 29 23:47:23 2010 -0500
@@ -11,7 +11,13 @@
@class AIListObject, AIListContact, AIChat;
@protocol AIContainingObject;
+/* Posted for a single object whose attributes changed */
#define ListObject_AttributesChanged @"ListObject_AttributesChanged"
+
+/* Called when one or more ListObject_AttributesChanged notifications are done and all delays have cleared.
+ * We're ready to update the display at this point. */
+#define ListObject_AttributeChangesComplete @"ListObject_AttributeChangesComplete"
+
#define ListObject_StatusChanged @"ListObject_StatusChanged"
#define Contact_OrderChanged @"Contact_OrderChanged"
#define Contact_ListChanged @"Contact_ListChanged"
diff -r a3fcb0d5b61e -r cbd40f45797a Frameworks/Adium Framework/Source/AIContactObserverManager.h
--- a/Frameworks/Adium Framework/Source/AIContactObserverManager.h Fri Oct 29 22:36:16 2010 -0500
+++ b/Frameworks/Adium Framework/Source/AIContactObserverManager.h Fri Oct 29 23:47:23 2010 -0500
@@ -26,6 +26,9 @@
NSMutableSet *contactObservers;
NSMutableSet *removedContactObservers;
NSTimer *delayedUpdateTimer;
+ NSInteger quietDelayedUpdatePeriodsRemaining;
+
+
NSInteger delayedStatusChanges;
NSMutableSet *delayedModifiedStatusKeys;
NSInteger delayedAttributeChanges;
diff -r a3fcb0d5b61e -r cbd40f45797a Frameworks/Adium Framework/Source/AIContactObserverManager.m
--- a/Frameworks/Adium Framework/Source/AIContactObserverManager.m Fri Oct 29 22:36:16 2010 -0500
+++ b/Frameworks/Adium Framework/Source/AIContactObserverManager.m Fri Oct 29 23:47:23 2010 -0500
@@ -119,7 +119,7 @@
{
if (delayedUpdateRequests > 0) {
delayedUpdateRequests--;
- if ([self shouldDelayUpdates])
+ if (![self shouldDelayUpdates])
[self _performDelayedUpdates:nil];
}
}
@@ -146,6 +146,9 @@
BOOL restoreDelayUntilInactivity = (self.delayedUpdateTimer != nil);
[self.delayedUpdateTimer invalidate]; self.delayedUpdateTimer = nil;
+
+ NSLog(@"endListObjectNotificationsDelaysImmediately");
+
[self _performDelayedUpdates:nil];
/* After immediately performing updates as requested, go back to delaying until inactivity if that was the
@@ -156,10 +159,13 @@
}
}
+#define QUIET_DELAYED_UPDATE_PERIODS 3
+
//Delay all list object notifications until a period of inactivity occurs. This is useful for accounts that do not
//know when they have finished connecting but still want to mute events.
- (void)delayListObjectNotificationsUntilInactivity
{
+ NSLog(@"*** Begin grouping delay ***");
if (!delayedUpdateTimer) {
updatesAreDelayedUntilInactivity = YES;
self.delayedUpdateTimer = [NSTimer scheduledTimerWithTimeInterval:UPDATE_CLUMP_INTERVAL
@@ -167,9 +173,12 @@
selector:@selector(_performDelayedUpdates:)
userInfo:nil
repeats:YES];
+ quietDelayedUpdatePeriodsRemaining = QUIET_DELAYED_UPDATE_PERIODS;
+
} else {
//Reset the timer
[delayedUpdateTimer setFireDate:[NSDate dateWithTimeIntervalSinceNow:UPDATE_CLUMP_INTERVAL]];
+ quietDelayedUpdatePeriodsRemaining = QUIET_DELAYED_UPDATE_PERIODS;
}
}
@@ -226,7 +235,8 @@
//(When modifying display attributes in response to a status change, this is not necessary)
- (void)listObjectAttributesChanged:(AIListObject *)inObject modifiedKeys:(NSSet *)inModifiedKeys
{
- if ([self shouldDelayUpdates]) {
+ BOOL shouldDelay = [self shouldDelayUpdates];
+ if (shouldDelay) {
delayedAttributeChanges++;
[delayedModifiedAttributeKeys unionSet:inModifiedKeys];
} else {
@@ -238,11 +248,20 @@
//Post an attributes changed message
[[NSNotificationCenter defaultCenter] postNotificationName:ListObject_AttributesChanged
- object:inObject
- userInfo:(inModifiedKeys ?
- [NSDictionary dictionaryWithObject:inModifiedKeys
- forKey:@"Keys"] :
- nil)];
+ object:inObject
+ userInfo:(inModifiedKeys ?
+ [NSDictionary dictionaryWithObject:inModifiedKeys
+ forKey:@"Keys"] :
+ nil)];
+
+ if (!shouldDelay) {
+ NSLog(@"Immediate ListObject_AttributeChangesComplete for %@", inObject);
+ /* Note that we completed 1 or more delayed attribute changes */
+ [[NSNotificationCenter defaultCenter] postNotificationName:ListObject_AttributeChangesComplete
+ object:inObject
+ userInfo:[NSDictionary dictionaryWithObject:inModifiedKeys
+ forKey:@"Keys"]];
+ }
}
//Performs any delayed list object/handle updates
@@ -251,7 +270,8 @@
BOOL updatesOccured = (delayedStatusChanges || delayedAttributeChanges || delayedContactChanges);
static int updatesDone = 0;
-
+ NSLog(@"_performDelayedUpdates %p: %i", timer, ++updatesDone);
+
//Send out global attribute & status changed notifications (to cover any delayed updates)
if (updatesOccured) {
BOOL shouldSort = NO;
@@ -274,6 +294,13 @@
[[AISortController activeSortController] shouldSortForModifiedAttributeKeys:delayedModifiedAttributeKeys]) {
shouldSort = YES;
}
+
+ /* Note that we completed 1 or more delayed attribute changes; the precise object isn't known */
+ [[NSNotificationCenter defaultCenter] postNotificationName:ListObject_AttributeChangesComplete
+ object:nil
+ userInfo:[NSDictionary dictionaryWithObject:delayedModifiedAttributeKeys
+ forKey:@"Keys"]];
+
[delayedModifiedAttributeKeys removeAllObjects];
delayedAttributeChanges = 0;
}
@@ -287,10 +314,12 @@
//If no more updates are left to process, disable the update timer
//If there are no delayed update requests, remove the hold
if (!delayedUpdateTimer || !updatesOccured) {
- if (delayedUpdateTimer) {
+ if (delayedUpdateTimer && (quietDelayedUpdatePeriodsRemaining-- <= 0)) {
[delayedUpdateTimer invalidate];
self.delayedUpdateTimer = nil;
updatesAreDelayedUntilInactivity = NO;
+
+ NSLog(@"The delayedUpdateTimer has EXPIRED");
}
}
diff -r a3fcb0d5b61e -r cbd40f45797a Plugins/Purple Service/SLPurpleCocoaAdapter.m
--- a/Plugins/Purple Service/SLPurpleCocoaAdapter.m Fri Oct 29 22:36:16 2010 -0500
+++ b/Plugins/Purple Service/SLPurpleCocoaAdapter.m Fri Oct 29 23:47:23 2010 -0500
@@ -31,6 +31,7 @@
#import <Adium/AIContentTyping.h>
#import <Adium/AIHTMLDecoder.h>
#import <Adium/AIListContact.h>
+#import <Adium/AIContactObserverManager.h>
#import <Adium/AIUserIcons.h>
#import <AIUtilities/AIImageAdditions.h>
@@ -163,6 +164,11 @@
- (void)initLibPurple
{
+ /* Initializing libpurple may result in loading a ton of buddies if our permit and deny lists are large; that, in
+ * turn, would create and update a ton of contacts.
+ */
+ [[AIContactObserverManager sharedManager] delayListObjectNotifications];
+
//Set the gaim user directory to be within this user's directory
if (![[NSUserDefaults standardUserDefaults] boolForKey:@"Adium 1.0.3 moved to libpurple"]) {
//Remove old icons cache
@@ -219,6 +225,14 @@
selector:@selector(networkDidChange:)
name:AINetworkDidChangeNotification
object:nil];
+
+ /* For any behaviors which occur on the next run loop, provide a buffer time of continued expectation of
+ * heavy activity.
+ */
+ [[AIContactObserverManager sharedManager] delayListObjectNotificationsUntilInactivity];
+
+ [[AIContactObserverManager sharedManager] endListObjectNotificationsDelay];
+
}
#pragma mark Lookup functions
diff -r a3fcb0d5b61e -r cbd40f45797a Source/AIListController.m
--- a/Source/AIListController.m Fri Oct 29 22:36:16 2010 -0500
+++ b/Source/AIListController.m Fri Oct 29 23:47:23 2010 -0500
@@ -433,9 +433,9 @@
*
* Resize horizontally if desired and the display name changed
*/
-- (void)listObjectAttributesChanged:(NSNotification *)notification
+- (void)listObjectAttributeChangesComplete:(NSNotification *)notification
{
- [super listObjectAttributesChanged:notification];
+ [super listObjectAttributeChangesComplete:notification];
if (((AIListObject *)notification.object).isStranger)
return;
More information about the commits
mailing list