adium 4061:396786e9e2b7: Wrap a number of our libpurple callback...

commits at adium.im commits at adium.im
Wed Jul 20 04:32:00 UTC 2011


details:	http://hg.adium.im/adium/rev/396786e9e2b7
revision:	4061:396786e9e2b7
branch:		(none)
author:		Stephen Holt <sholt at adium.im>
date:		Tue Jul 19 21:31:48 2011 -0700

Wrap a number of our libpurple callback functions with autorelease pools, to help keep our memory footprint managed.

diffs (truncated from 1053 to 1000 lines):

diff -r 506ba640919c -r 396786e9e2b7 Plugins/Purple Service/SLPurpleCocoaAdapter.m
--- a/Plugins/Purple Service/SLPurpleCocoaAdapter.m	Mon Jul 18 00:56:21 2011 +0200
+++ b/Plugins/Purple Service/SLPurpleCocoaAdapter.m	Tue Jul 19 21:31:48 2011 -0700
@@ -59,13 +59,6 @@
 - (BOOL)attemptPurpleCommandOnMessage:(NSString *)originalMessage fromAccount:(AIAccount *)sourceAccount inChat:(AIChat *)chat;
 @end
 
-/*
- * A pointer to the single instance of this class active in the application.
- * The purple callbacks need to be C functions with specific prototypes, so they
- * can't be ObjC methods. The ObjC callbacks do need to be ObjC methods. This
- * allows the C ones to call the ObjC ones.
- **/
-static SLPurpleCocoaAdapter	*sharedInstance = nil;
 
 static NSMutableArray		*libpurplePluginArray = nil;
 
@@ -75,14 +68,19 @@
  * @brief Return the shared instance
  */
 + (SLPurpleCocoaAdapter *)sharedInstance
-{	
-	@synchronized(self) {
-		if (!sharedInstance) {
-			sharedInstance = [[self alloc] init];
-		}
-	}
-
-	return sharedInstance;
+{
+    /*
+     * A pointer to the single instance of this class active in the application.
+     * The purple callbacks need to be C functions with specific prototypes, so they
+     * can't be ObjC methods. The ObjC callbacks do need to be ObjC methods. This
+     * allows the C ones to call the ObjC ones.
+     **/
+    static SLPurpleCocoaAdapter *_sharedInstance;
+    static dispatch_once_t sharedInstanceGuard;
+    dispatch_once(&sharedInstanceGuard, ^{
+        _sharedInstance = [[self alloc] init];
+    });
+    return _sharedInstance;
 }
 
 /*!
@@ -171,13 +169,17 @@
 
 void adium_glib_print(const char *string)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 	AILog(@"(GLib): %s", string);
+    [pool drain];
 }
 
 void adium_glib_log(const gchar *log_domain, GLogLevelFlags flags, const gchar *message, gpointer user_data)
 {
 	if (!AIDebugLoggingIsEnabled()) return;
 	
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    
 	NSString *level;
 	
 	if (!log_domain) log_domain = "general";
@@ -199,6 +201,7 @@
 
 	
 	AILog(@"(GLib : %s): %@: %s", log_domain, level, message);
+    [pool drain];
 }
 
 - (void)initLibPurple
@@ -318,7 +321,7 @@
 
 #pragma mark Lookup functions
 
-NSString* serviceClassForPurpleProtocolID(const char *protocolID)
+static NSString* serviceClassForPurpleProtocolID(const char *protocolID)
 {
 	NSString	*serviceClass = nil;
 	if (protocolID) {
diff -r 506ba640919c -r 396786e9e2b7 Plugins/Purple Service/adiumPurpleBlist.m
--- a/Plugins/Purple Service/adiumPurpleBlist.m	Mon Jul 18 00:56:21 2011 +0200
+++ b/Plugins/Purple Service/adiumPurpleBlist.m	Tue Jul 19 21:31:48 2011 -0700
@@ -36,6 +36,7 @@
 //A buddy was removed from the list
 static void adiumPurpleBlistRemove(PurpleBuddyList *list, PurpleBlistNode *node)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
     NSCAssert(node != nil, @"BlistRemove on null node");
     if (PURPLE_BLIST_NODE_IS_BUDDY(node)) {
 		PurpleBuddy	*buddy = (PurpleBuddy *)node;
@@ -45,6 +46,7 @@
 		//Clear the ui_data
 		[(id)buddy->node.ui_data release]; buddy->node.ui_data = NULL;
     }
+    [pool drain];
 }
 
 static void adiumPurpleBlistDestroy(PurpleBuddyList *list)
@@ -60,7 +62,9 @@
 
 static void adiumPurpleBlistRequestAddBuddy(PurpleAccount *account, const char *username, const char *group, const char *alias)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 	[accountLookup(account) requestAddContactWithUID:[NSString stringWithUTF8String:username]];
+    [pool drain];
 }
 
 static void adiumPurpleBlistRequestAddChat(PurpleAccount *account, PurpleGroup *group, const char *alias, const char *name)
diff -r 506ba640919c -r 396786e9e2b7 Plugins/Purple Service/adiumPurpleConnection.m
--- a/Plugins/Purple Service/adiumPurpleConnection.m	Mon Jul 18 00:56:21 2011 +0200
+++ b/Plugins/Purple Service/adiumPurpleConnection.m	Tue Jul 19 21:31:48 2011 -0700
@@ -20,6 +20,7 @@
 static void adiumPurpleConnConnectProgress(PurpleConnection *gc, const char *text, size_t step, size_t step_count)
 {
 	if (!PURPLE_CONNECTION_IS_VALID(gc)) return;
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 
     AILog(@"Connecting: gc=0x%x (%s) %i / %i", gc, text, step, step_count);
 
@@ -27,29 +28,36 @@
 	[accountLookup(purple_connection_get_account(gc)) mainPerformSelector:@selector(accountConnectionProgressStep:percentDone:)
 										 withObject:[NSNumber numberWithInteger:step]
 										 withObject:connectionProgressPrecent];
+    [pool drain];
 }
 
 static void adiumPurpleConnConnected(PurpleConnection *gc)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
     AILog(@"Connected: gc=%x", gc);
 	
 	[accountLookup(purple_connection_get_account(gc)) accountConnectionConnected];
+    [pool drain];
 }
 
 static void adiumPurpleConnDisconnected(PurpleConnection *gc)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
     AILog(@"Disconnected: gc=%x", gc);
 	//    if (_accountDict == nil) // if this has been destroyed, unloadPlugin has already been called
 	//        return;
     [accountLookup(purple_connection_get_account(gc)) accountConnectionDisconnected];
+    [pool drain];
 }
 
 static void adiumPurpleConnNotice(PurpleConnection *gc, const char *text)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
     AILog(@"Connection Notice: gc=%x (%s)", gc, text);
 	
 	NSString *connectionNotice = [NSString stringWithUTF8String:text];
 	[accountLookup(purple_connection_get_account(gc)) accountConnectionNotice:connectionNotice];
+    [pool drain];
 }
 
 /** Called when an error causes a connection to be disconnected.
@@ -62,14 +70,16 @@
  *  @param text  a localized message describing the disconnection
  *               in more detail to the user.
  */
-void adiumPurpleConnReportDisconnectReason(PurpleConnection *gc,
+static void adiumPurpleConnReportDisconnectReason(PurpleConnection *gc,
 										   PurpleConnectionError reason,
 										   const char *text)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 	AILog(@"Connection Disconnected: gc=%x (%s)", gc, text);
 	
 	NSString	*disconnectError = (text ? [NSString stringWithUTF8String:text] : @"");
     [accountLookup(purple_connection_get_account(gc)) accountConnectionReportDisconnect:disconnectError withReason:reason];
+    [pool drain];
 }
 
 static PurpleConnectionUiOps adiumPurpleConnectionOps = {
diff -r 506ba640919c -r 396786e9e2b7 Plugins/Purple Service/adiumPurpleConversation.m
--- a/Plugins/Purple Service/adiumPurpleConversation.m	Mon Jul 18 00:56:21 2011 +0200
+++ b/Plugins/Purple Service/adiumPurpleConversation.m	Tue Jul 19 21:31:48 2011 -0700
@@ -29,6 +29,8 @@
 #pragma mark Conversations
 static void adiumPurpleConvCreate(PurpleConversation *conv)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
 	//Pass chats along to the account
 	if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
 		
@@ -36,10 +38,13 @@
 		
 		[accountLookup(purple_conversation_get_account(conv)) addChat:chat];
 	}
+    [pool drain];
 }
 
 static void adiumPurpleConvDestroy(PurpleConversation *conv)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
 	/* Purple is telling us a conv was destroyed.  We've probably already cleaned up, but be sure in case purple calls this
 	 * when we don't ask it to (for example if we are summarily kicked from a chat room and purple closes the 'window').
 	 */
@@ -55,12 +60,14 @@
 		[chat release];
 		conv->ui_data = nil;
 	}
+    [pool drain];
 }
 
 static void adiumPurpleConvWriteChat(PurpleConversation *conv, const char *who,
 								   const char *message, PurpleMessageFlags flags,
 								   time_t mtime)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 
 		NSDictionary	*messageDict;
 		NSString		*messageString;
@@ -105,12 +112,15 @@
 
 			[accountLookup(purple_conversation_get_account(conv)) receivedMultiChatMessage:messageDict inChat:groupChatLookupFromConv(conv)];
 		}
+    [pool drain];
 }
 
 static void adiumPurpleConvWriteIm(PurpleConversation *conv, const char *who,
 								 const char *message, PurpleMessageFlags flags,
 								 time_t mtime)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
 	//We only care about this if it does not have the PURPLE_MESSAGE_SEND flag, which is set if Purple is sending a sent message back to us
 	if ((flags & PURPLE_MESSAGE_SEND) == 0) {
 		if (flags & PURPLE_MESSAGE_NOTIFY) {
@@ -154,16 +164,20 @@
 										 inChat:chat];
 		}
 	}
+    [pool drain];
 }
 
 static void adiumPurpleConvWriteConv(PurpleConversation *conv, const char *who, const char *alias,
 								   const char *message, PurpleMessageFlags flags,
 								   time_t mtime)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
 	AILog(@"adiumPurpleConvWriteConv: Received %s from %s [%i]",message,who,flags);
 	AIChat	*chat = chatLookupFromConv(conv);
 
 	if (!chat) {
+        [pool drain];
 		return;
 	}
 	
@@ -171,6 +185,7 @@
 	
 	if (!messageString) {
 		AILogWithSignature(@"Received write without message: %@ %d", chat, flags);
+        [pool drain];
 		return;
 	}
 	
@@ -178,6 +193,7 @@
 		if ([messageString rangeOfString:@"User information not available"].location != NSNotFound) {
 			//Ignore user information errors; they are irrelevent
 			//XXX The user info check only works in English; libpurple should be modified to be better about this useless information spamming
+            [pool drain];
 			return;
 		}
 		
@@ -271,6 +287,7 @@
 						  afterDelay:0];
 		}
 	}
+    [pool drain];
 }
 
 NSString *get_real_name_for_account_conv_buddy(PurpleAccount *account, PurpleConversation *conv, char *who)
@@ -307,6 +324,7 @@
 
 static void adiumPurpleConvChatAddUsers(PurpleConversation *conv, GList *cbuddies, gboolean new_arrivals)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 	if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
 		PurpleAccount *account = purple_conversation_get_account(conv);
 
@@ -329,11 +347,13 @@
 										   newlyAdded:new_arrivals];
 	} else
 		AILog(@"adiumPurpleConvChatAddUsers: IM");
+    [pool drain];
 }
 
 static void adiumPurpleConvChatRenameUser(PurpleConversation *conv, const char *oldName,
 										const char *newName, const char *newAlias)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 	AILog(@"adiumPurpleConvChatRenameUser: %s: oldName %s, newName %s, newAlias %s",
 			   purple_conversation_get_name(conv),
 			   oldName, newName, newAlias);
@@ -352,10 +372,12 @@
 																		  flags:cb->flags
 																		 inChat:groupChatLookupFromConv(conv)];
 	}
+    [pool drain];
 }
 
 static void adiumPurpleConvChatRemoveUsers(PurpleConversation *conv, GList *users)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 	if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
 		NSMutableArray	*usersArray = [NSMutableArray array];
 		PurpleAccount	*account = purple_conversation_get_account(conv);
@@ -372,10 +394,12 @@
 	} else {
 		AILog(@"adiumPurpleConvChatRemoveUser: IM");
 	}
+    [pool drain];
 }
 
 static void adiumPurpleConvUpdateUser(PurpleConversation *conv, const char *user)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 	PurpleAccount *account = purple_conversation_get_account(conv);
 	CBPurpleAccount *adiumAccount = accountLookup(account);
 	
@@ -400,6 +424,7 @@
 					   flags:cb->flags
 					   alias:name
 				  attributes:attributes];
+    [pool drain];
 }
 
 static void adiumPurpleConvPresent(PurpleConversation *conv)
@@ -415,6 +440,8 @@
 
 static void adiumPurpleConvUpdated(PurpleConversation *conv, PurpleConvUpdateType type)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
 	if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
 		PurpleConvChat  *chat = purple_conversation_get_chat_data(conv);
 		
@@ -503,43 +530,51 @@
 				break;
 		}
 	}
+    [pool drain];
 }
 
 #pragma mark Custom smileys
-gboolean adiumPurpleConvCustomSmileyAdd(PurpleConversation *conv, const char *smile, gboolean remote)
+static gboolean adiumPurpleConvCustomSmileyAdd(PurpleConversation *conv, const char *smile, gboolean remote)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 	AILog(@"%s: Added Custom Smiley %s",purple_conversation_get_name(conv),smile);
 	[accountLookup(purple_conversation_get_account(conv)) chat:chatLookupFromConv(conv)
 			 isWaitingOnCustomEmoticon:[NSString stringWithUTF8String:smile]];
+    [pool drain];
 
 	return TRUE;
 }
 
-void adiumPurpleConvCustomSmileyWrite(PurpleConversation *conv, const char *smile,
+static void adiumPurpleConvCustomSmileyWrite(PurpleConversation *conv, const char *smile,
 									const guchar *data, gsize size)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 	AILog(@"%s: Write Custom Smiley %s (%x %i)",purple_conversation_get_name(conv),smile,data,size);
 
 	[accountLookup(purple_conversation_get_account(conv)) chat:chatLookupFromConv(conv)
 					 setCustomEmoticon:[NSString stringWithUTF8String:smile]
 						 withImageData:[NSData dataWithBytes:data
 													  length:size]];
+    [pool drain];
 }
 
-void adiumPurpleConvCustomSmileyClose(PurpleConversation *conv, const char *smile)
+static void adiumPurpleConvCustomSmileyClose(PurpleConversation *conv, const char *smile)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 	AILog(@"%s: Close Custom Smiley %s",purple_conversation_get_name(conv),smile);
 
 	[accountLookup(purple_conversation_get_account(conv)) chat:chatLookupFromConv(conv)
 				  closedCustomEmoticon:[NSString stringWithUTF8String:smile]];
+    [pool drain];
 }
 
 static gboolean adiumPurpleConvJoin(PurpleConversation *conv, const char *name,
 									PurpleConvChatBuddyFlags flags,
 									GHashTable *users)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 	AIChat *chat = groupChatLookupFromConv(conv);
-
+    [pool drain];
 	// We return TRUE if we want to hide it.
 	return !chat.showJoinLeave;
 }
@@ -547,7 +582,9 @@
 static gboolean adiumPurpleConvLeave(PurpleConversation *conv, const char *name,
 									 const char *reason, GHashTable *users)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 	AIChat *chat = groupChatLookupFromConv(conv);
+    [pool drain];
 	
 	// We return TRUE if we want to hide it.
 	return !chat.showJoinLeave;	
diff -r 506ba640919c -r 396786e9e2b7 Plugins/Purple Service/adiumPurpleCore.m
--- a/Plugins/Purple Service/adiumPurpleCore.m	Mon Jul 18 00:56:21 2011 +0200
+++ b/Plugins/Purple Service/adiumPurpleCore.m	Tue Jul 19 21:31:48 2011 -0700
@@ -48,8 +48,10 @@
 static void adiumPurpleDebugPrint(PurpleDebugLevel level, const char *category, const char *debug_msg)
 {
 	//Log error
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 	if (!category) category = "general"; //Category can be nil
 	AILog(@"(Libpurple: %s) %s",category, debug_msg);
+    [pool drain];
 }
 
 static int adiumPurpleDebugIsEnabled(PurpleDebugLevel level, const char *category)
@@ -95,7 +97,9 @@
 	//Load each plugin
 	for (id <AILibpurplePlugin>	plugin in [SLPurpleCocoaAdapter libpurplePluginArray]) {
 		if ([plugin respondsToSelector:@selector(installLibpurplePlugin)]) {
+            NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 			[plugin installLibpurplePlugin];
+            [pool drain];
 		}
 	}
 #ifdef HAVE_CDSA
@@ -114,7 +118,9 @@
 	//Load each plugin	
 	for (id <AILibpurplePlugin>	plugin in [SLPurpleCocoaAdapter libpurplePluginArray]) {
 		if ([plugin respondsToSelector:@selector(loadLibpurplePlugin)]) {
+            NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 			[plugin loadLibpurplePlugin];
+            [pool drain];
 		}
 	}	
 }
@@ -173,6 +179,8 @@
 /* The core is ready... finish configuring libpurple and its plugins */
 static void adiumPurpleCoreUiInit(void)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
 	bindtextdomain("pidgin", [[[NSBundle bundleWithIdentifier:@"im.pidgin.libpurple"] resourcePath] fileSystemRepresentation]);
 	bind_textdomain_codeset("pidgin", "UTF-8");
 	textdomain("pidgin");
@@ -241,6 +249,7 @@
 	
 	[[NSNotificationCenter defaultCenter] postNotificationName:AILibpurpleDidInitialize
 														object:nil];
+    [pool drain];
 }
 
 static void adiumPurpleCoreQuit(void)
diff -r 506ba640919c -r 396786e9e2b7 Plugins/Purple Service/adiumPurpleEventloop.m
--- a/Plugins/Purple Service/adiumPurpleEventloop.m	Mon Jul 18 00:56:21 2011 +0200
+++ b/Plugins/Purple Service/adiumPurpleEventloop.m	Tue Jul 19 21:31:48 2011 -0700
@@ -31,42 +31,60 @@
 static guint				sourceId = 0;		//The next source key; continuously incrementing
 
 /*
- * The sources, keyed by integer key id (wrapped in an NSNumber), holding
- * NSVaue*'s with pointers to dispatch_source_ts. (The tags are guints (32 bits),
- * so too small to hold an NSValue* or dispatch_source_t on x86.
+ * glib, unfortunately, identifies all sources and timers via unsigned 32 bit tags. We would like to map them to dispatch_source_t objects.
+ * So: we make a CFDictionary with all null callbacks (hash on the value of the integer, cast to a void*, and don't retain/release anything).
+ * That gives us a guint->dispatch_source_t map, but it's a little gross, so three inline wrapper functions are provided to make things nice:
+ * sourceForTag, setSourceForTag, and removeSourceForTag. The names should be self-explanatory. No retains or releases are done by them.
  */
-static NSMutableDictionary	*sourceInfoDict = nil;
+static inline CFMutableDictionaryRef sourceInfoDict() {
+    static CFMutableDictionaryRef _sourceInfoDict;
+    static dispatch_once_t sourceInfoDictToken;
+    dispatch_once(&sourceInfoDictToken, ^{
+        static const CFDictionaryKeyCallBacks keyCallbacks = {0, NULL, NULL, NULL, NULL, NULL};
+        static const CFDictionaryValueCallBacks valueCallbacks = {0, NULL, NULL, NULL, NULL};
+        _sourceInfoDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &keyCallbacks, &valueCallbacks);
+    });
+    return _sourceInfoDict;
+}
 
-gboolean adium_source_remove(guint tag) {
-	
-	NSValue *srcPointer = [sourceInfoDict objectForKey:[NSNumber numberWithUnsignedInt:tag]];
-	
-    if (!srcPointer) {
-		AILogWithSignature(@"Source info for %i not found in %@", tag, sourceInfoDict);
+static inline dispatch_source_t sourceForTag(guint tag) {
+    return (dispatch_source_t)CFDictionaryGetValue(sourceInfoDict(), (void *)tag);
+}
+static inline void setSourceForTag(dispatch_source_t source, guint tag) {
+    CFDictionarySetValue(sourceInfoDict(), (void *)tag, source);
+}
+static inline void removeSourceForTag(guint tag) {
+    CFDictionaryRemoveValue(sourceInfoDict(), (void *)tag);
+}
+
+static gboolean adium_source_remove(guint tag) {
+	dispatch_source_t src = sourceForTag(tag);
+    
+    if (!src) {
+		AILogWithSignature(@"Source info for %i not found");
 		return FALSE;
 	}
 	
-	dispatch_source_t src = (dispatch_source_t)[srcPointer pointerValue];
     dispatch_source_cancel(src);
     
 	BOOL success = (dispatch_source_testcancel(src) != 0);
 	
+    removeSourceForTag(tag);
+
 	dispatch_release(src);
 	
-    [sourceInfoDict removeObjectForKey:[NSNumber numberWithUnsignedInt:tag]];
-
 	return success;
 }
 
 //Like g_source_remove, return TRUE if successful, FALSE if not
-gboolean adium_timeout_remove(guint tag) {
+static gboolean adium_timeout_remove(guint tag) {
     return adium_source_remove(tag);
 }
 
 /* Extra function to generalize adium_timeout_add and adium_timeout_add_seconds,
  * making the permitted leeway explicit.
  */
-guint addTimer(uint64_t interval, uint64_t leeway, GSourceFunc function, gpointer data)
+static guint addTimer(uint64_t interval, uint64_t leeway, GSourceFunc function, gpointer data)
 {
 	dispatch_source_t src;
 	guint tag;
@@ -77,18 +95,20 @@
 	
     dispatch_source_set_timer(src, dispatch_time(DISPATCH_TIME_NOW, interval), interval, leeway);
 	
-    [sourceInfoDict setObject:[NSValue valueWithPointer:src]
-                       forKey:[NSNumber numberWithUnsignedInt:tag]];
+    setSourceForTag(src, tag);
 	
     dispatch_source_set_event_handler(src, ^{
-		
-		if (![sourceInfoDict objectForKey:[NSNumber numberWithUnsignedInt:tag]]) {
+        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+		if (sourceForTag(tag)) {
+            if (!function || !function(data)) {
+                adium_timeout_remove(tag);
+            }
+        } else {
 			AILogWithSignature(@"Timer with tag %i was already canceled!", tag);
-			return;
 		}
-		
-        if (!function || !function(data))
-			adium_timeout_remove(tag);
+  
+        [pool drain];
     });
 	
     dispatch_resume(src);
@@ -97,18 +117,18 @@
 }
 
 // Add a timer in miliseconds
-guint adium_timeout_add(guint interval, GSourceFunc function, gpointer data)
+static guint adium_timeout_add(guint interval, GSourceFunc function, gpointer data)
 {
 	return addTimer(((uint64_t)interval) * NSEC_PER_MSEC, NSEC_PER_USEC, function, data);
 }
 
 // Add a timer in seconds (allowing more leeway, therefore allowing the OS to group events and save power)
-guint adium_timeout_add_seconds(guint interval, GSourceFunc function, gpointer data)
+static guint adium_timeout_add_seconds(guint interval, GSourceFunc function, gpointer data)
 {
 	return addTimer(((uint64_t)interval) * NSEC_PER_SEC, NSEC_PER_SEC, function, data);
 }
 
-guint adium_input_add(gint fd, PurpleInputCondition condition,
+static guint adium_input_add(gint fd, PurpleInputCondition condition,
 					  PurpleInputFunction func, gpointer user_data)
 {	
 	if (fd < 0) {
@@ -131,18 +151,19 @@
     src = dispatch_source_create(type, fd, 0, dispatch_get_main_queue());
 	
     dispatch_source_set_event_handler(src, ^{
+        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
         if (func) func(user_data, fd, condition);
+        [pool drain];
     });
 		
-    [sourceInfoDict setObject:[NSValue valueWithPointer:src]
-                       forKey:[NSNumber numberWithUnsignedInt:tag]];
+    setSourceForTag(src, tag);
 
 	dispatch_resume(src);
 	
     return tag;
 }
 
-int adium_input_get_error(int fd, int *error)
+static int adium_input_get_error(int fd, int *error)
 {
 	int		  ret;
 	socklen_t len;
@@ -203,7 +224,5 @@
 
 PurpleEventLoopUiOps *adium_purple_eventloop_get_ui_ops(void)
 {
-	if (!sourceInfoDict) sourceInfoDict = [[NSMutableDictionary alloc] init];
-
 	return &adiumEventLoopUiOps;
 }
diff -r 506ba640919c -r 396786e9e2b7 Plugins/Purple Service/adiumPurpleFt.m
--- a/Plugins/Purple Service/adiumPurpleFt.m	Mon Jul 18 00:56:21 2011 +0200
+++ b/Plugins/Purple Service/adiumPurpleFt.m	Tue Jul 19 21:31:48 2011 -0700
@@ -24,10 +24,12 @@
 
 static void adiumPurpleDestroy(PurpleXfer *xfer)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 	ESFileTransfer *fileTransfer = (ESFileTransfer *)xfer->ui_data;
 	[accountLookup(xfer->account) destroyFileTransfer:fileTransfer];
 	
 	xfer->ui_data = nil;
+    [pool drain];
 }
 
 static void adiumPurpleAddXfer(PurpleXfer *xfer)
@@ -37,6 +39,7 @@
 
 static void adiumPurpleUpdateProgress(PurpleXfer *xfer, double percent)
 {	
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 	ESFileTransfer *fileTransfer = (ESFileTransfer *)xfer->ui_data;
 	
 	if (fileTransfer) {
@@ -44,20 +47,25 @@
 															percent:[NSNumber numberWithDouble:percent]
 														  bytesSent:[NSNumber numberWithUnsignedLong:xfer->bytes_sent]];
 	}
+    [pool drain];
 }
 
 static void adiumPurpleCancelLocal(PurpleXfer *xfer)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 	AILog(@"adiumPurpleCancelLocal");
 	ESFileTransfer *fileTransfer = (ESFileTransfer *)xfer->ui_data;
     [accountLookup(xfer->account) fileTransferCancelledLocally:fileTransfer];
+    [pool drain];
 }
 
 static void adiumPurpleCancelRemote(PurpleXfer *xfer)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 	AILog(@"adiumPurpleCancelRemote");
 	ESFileTransfer *fileTransfer = (ESFileTransfer *)xfer->ui_data;
     [accountLookup(xfer->account) fileTransferCancelledRemotely:fileTransfer];
+    [pool drain];
 }
 
 static PurpleXferUiOps adiumPurpleFileTransferOps = {
diff -r 506ba640919c -r 396786e9e2b7 Plugins/Purple Service/adiumPurpleNotify.m
--- a/Plugins/Purple Service/adiumPurpleNotify.m	Mon Jul 18 00:56:21 2011 +0200
+++ b/Plugins/Purple Service/adiumPurpleNotify.m	Tue Jul 19 21:31:48 2011 -0700
@@ -22,16 +22,20 @@
 
 static void *adiumPurpleNotifyMessage(PurpleNotifyMsgType type, const char *title, const char *primary, const char *secondary)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
 	AILog(@"adiumPurpleNotifyMessage: type: %i\n%s\n%s\n%s ",
 			   type,
 			   (title ? title : ""),
 			   (primary ? primary : ""),
 			   (secondary ? secondary : ""));
 
-	return ([[SLPurpleCocoaAdapter sharedInstance] handleNotifyMessageOfType:type
-																 withTitle:title
-																   primary:primary
-																 secondary:secondary]);
+	void *res = ([[SLPurpleCocoaAdapter sharedInstance] handleNotifyMessageOfType:type
+                                                                        withTitle:title
+                                                                          primary:primary
+                                                                        secondary:secondary]);
+    [pool drain];
+    return res;
 }
 
 static void *adiumPurpleNotifyEmails(PurpleConnection *gc, size_t count, gboolean detailed, const char **subjects, const char **froms, const char **tos, const char **urls)
@@ -39,19 +43,22 @@
 	// Don't notify that 0 emails are present.
 	if (!count)
 		return NULL;
-	
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
     //Values passed can be null
 	AIAccount	*account = (PURPLE_CONNECTION_IS_VALID(gc) ?
 							accountLookup(purple_connection_get_account(gc)) :
 							nil);
 
-    return [ESPurpleNotifyEmailController handleNotifyEmailsForAccount:account
+    void *res = [ESPurpleNotifyEmailController handleNotifyEmailsForAccount:account
 															   count:count 
 															detailed:detailed
 															subjects:subjects
 															   froms:froms
 																 tos:tos
 																urls:urls];
+    [pool drain];
+    return res;
 }
 
 static void *adiumPurpleNotifyEmail(PurpleConnection *gc, const char *subject, const char *from, const char *to, const char *url)
@@ -67,44 +74,55 @@
 
 static void *adiumPurpleNotifyFormatted(const char *title, const char *primary, const char *secondary, const char *text)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
 	AILog(@"adiumPurpleNotifyFormatted: %s\n%s\n%s\n%s ",
 			   (title ? title : ""),
 			   (primary ? primary : ""),
 			   (secondary ? secondary : ""),
 			   (text ? text : ""));
 
-	return ([[SLPurpleCocoaAdapter sharedInstance] handleNotifyFormattedWithTitle:title
-																		primary:primary
-																	  secondary:secondary
-																		   text:text]);	
+	void * res = ([[SLPurpleCocoaAdapter sharedInstance] handleNotifyFormattedWithTitle:title
+                                                                                primary:primary
+                                                                              secondary:secondary
+                                                                                   text:text]);	
+    [pool drain];
+    return res;
 }
 
 static void *adiumPurpleNotifySearchResults(PurpleConnection *gc, const char *title,
 										  const char *primary, const char *secondary,
 										  PurpleNotifySearchResults *results, gpointer user_data)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 	AILog(@"**** returning search results");
 	//This will be released in adiumPurpleNotifyClose()
-	return [[AMPurpleSearchResultsController alloc] initWithPurpleConnection:gc
+	void *res = [[AMPurpleSearchResultsController alloc] initWithPurpleConnection:gc
 																	   title:(title ? [NSString stringWithUTF8String:title] : nil)
 																 primaryText:(primary ? [NSString stringWithUTF8String:primary] : nil)
 															   secondaryText:(secondary ? [NSString stringWithUTF8String:secondary] : nil)
 															   searchResults:results
 																	userData:user_data];
+    [pool drain];
+    return res;
 }
 
 static void adiumPurpleNotifySearchResultsNewRows(PurpleConnection *gc,
 												 PurpleNotifySearchResults *results,
 												 void *data)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 	if([(id)data isKindOfClass:[AMPurpleSearchResultsController class]]) {
 		[(AMPurpleSearchResultsController*)data addResults:results];
 	}
+    [pool drain];
 }
 
 static void *adiumPurpleNotifyUserinfo(PurpleConnection *gc, const char *who,
 									 PurpleNotifyUserInfo *user_info)
 {	
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
 	if (PURPLE_CONNECTION_IS_VALID(gc)) {
 		PurpleAccount		*account = purple_connection_get_account(gc);
 		PurpleBuddy		*buddy = purple_find_buddy(account, who);
@@ -121,12 +139,16 @@
 		[adiumAccount updateUserInfo:contact
 							withData:user_info];
 	}
+    
+    [pool drain];
 	
     return NULL;
 }
 
 static void *adiumPurpleNotifyUri(const char *uri)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
 	AILogWithSignature(@"Opening URI %s",uri);
 
 	if (uri) {
@@ -169,12 +191,16 @@
 			[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:passedURI]];
 		}
 	}
+    
+    [pool drain];
 	
     return NULL;
 }
 
 static void adiumPurpleNotifyClose(PurpleNotifyType type,void *uiHandle)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
 	id ourHandle = uiHandle;
 	AILogWithSignature(@"Closing %p (%i)",ourHandle,type);
 
@@ -185,6 +211,8 @@
 		[ourHandle performSelector:@selector(closeWindow:)
 						withObject:nil];
 	}
+    
+    [pool drain];
 }
 
 static PurpleNotifyUiOps adiumPurpleNotifyOps = {
diff -r 506ba640919c -r 396786e9e2b7 Plugins/Purple Service/adiumPurplePrivacy.m
--- a/Plugins/Purple Service/adiumPurplePrivacy.m	Mon Jul 18 00:56:21 2011 +0200
+++ b/Plugins/Purple Service/adiumPurplePrivacy.m	Tue Jul 19 21:31:48 2011 -0700
@@ -19,19 +19,27 @@
 
 static void adiumPurplePermitAdded(PurpleAccount *account, const char *name)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 	[accountLookup(account)	privacyPermitListAdded:[NSString stringWithUTF8String:purple_normalize(account, name)]];
+    [pool drain];
 }
 static void adiumPurplePermitRemoved(PurpleAccount *account, const char *name)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 	[accountLookup(account)	privacyPermitListRemoved:[NSString stringWithUTF8String:purple_normalize(account, name)]];
+    [pool drain];
 }
 static void adiumPurpleDenyAdded(PurpleAccount *account, const char *name)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 	[accountLookup(account)	privacyDenyListAdded:[NSString stringWithUTF8String:purple_normalize(account, name)]];
+    [pool drain];
 }
 static void adiumPurpleDenyRemoved(PurpleAccount *account, const char *name)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 	[accountLookup(account)	privacyDenyListRemoved:[NSString stringWithUTF8String:purple_normalize(account, name)]];
+    [pool drain];
 }
 
 static PurplePrivacyUiOps adiumPurplePrivacyOps = {
diff -r 506ba640919c -r 396786e9e2b7 Plugins/Purple Service/adiumPurpleRequest.m
--- a/Plugins/Purple Service/adiumPurpleRequest.m	Mon Jul 18 00:56:21 2011 +0200
+++ b/Plugins/Purple Service/adiumPurpleRequest.m	Tue Jul 19 21:31:48 2011 -0700
@@ -90,6 +90,8 @@
 								   PurpleAccount *account, const char *who, PurpleConversation *conv,
 								   void *userData)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
 	/*
 	 Multiline should be a paragraph-sized box; otherwise, a single line will suffice.
 	 Masked means we want to use an NSSecureTextField sort of thing.
@@ -124,6 +126,8 @@
 	
 	requestController = [ESPurpleRequestWindowController showInputWindowWithDict:infoDict];
 	
+    [pool drain];
+    
 	return requestController;
 }
 
@@ -150,6 +154,8 @@
 											   void *userData,
 											   size_t actionCount, va_list actions)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
     NSString			*titleString = (title ? [NSString stringWithUTF8String:title] : @"");
 	NSString			*primaryString = (primary ? [NSString stringWithUTF8String:primary] : nil);
 	id					requestController = nil;
@@ -250,6 +256,8 @@
 
 		requestController = [ESPurpleRequestActionController showActionWindowWithDict:infoDict];
 	}
+    
+    [pool drain];
 
 	return requestController;
 }
@@ -279,6 +287,8 @@
 									PurpleAccount *account, const char *who, PurpleConversation *conv,
 									void *userData)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
 	id requestController = nil;
 
     if (title && (strcmp(title, _("Register New XMPP Account")) == 0)) {
@@ -325,6 +335,7 @@
                                                                       conversation:conv
                                                                           userData:userData];
 	}
+    [pool drain];
 
 	return requestController;
 }
@@ -335,6 +346,8 @@
 									PurpleAccount *account, const char *who, PurpleConversation *conv,
 									void *user_data)
 {	
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
 	if (title) {
 		NSString *titleString = (title ? [NSString stringWithUTF8String:title] : nil);
 		if (savedialog) {
@@ -382,6 +395,7 @@
 			}
 		}
 	}
+    [pool drain];
 	
 	return NULL;
 }
@@ -397,6 +411,7 @@
  */
 static void adiumPurpleRequestClose(PurpleRequestType type, void *uiHandle)
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 	id	ourHandle = (id)uiHandle;
 	AILogWithSignature(@"%@ (%i)",uiHandle,[ourHandle respondsToSelector:@selector(purpleRequestClose)]);
 	if ([ourHandle respondsToSelector:@selector(purpleRequestClose)]) {
@@ -405,6 +420,7 @@
 	} else if ([ourHandle respondsToSelector:@selector(closeWindow:)]) {
 		[ourHandle closeWindow:nil];
 	}
+    [pool drain];
 }
 
 static void *adiumPurpleRequestFolder(const char *title, const char *dirname, GCallback ok_cb, GCallback cancel_cb,
diff -r 506ba640919c -r 396786e9e2b7 Source/AIAdium.m
--- a/Source/AIAdium.m	Mon Jul 18 00:56:21 2011 +0200
+++ b/Source/AIAdium.m	Tue Jul 19 21:31:48 2011 -0700
@@ -82,7 +82,6 @@
 
 - (void)handleURLEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent;
 - (void)systemTimeZoneDidChange:(NSNotification *)inNotification;
-- (void)kickRunLoop:(NSTimer *)dummy;
 - (void)confirmQuitQuestion:(NSNumber *)number userInfo:(id)info suppression:(NSNumber *)suppressed;
 - (void)fileTransferQuitQuestion:(NSNumber *)number userInfo:(id)info suppression:(NSNumber *)suppressed;
 - (void)openChatQuitQuestion:(NSNumber *)number userInfo:(id)info suppression:(NSNumber *)suppressed;
@@ -276,9 +275,6 @@
 	[[AIContactObserverManager sharedManager] endListObjectNotificationsDelay];
 
 	[pool release];
-	
-	//When no events are coming in (i.e. the user is away from their computer), the runloop doesn't iterate, and we accumulate autoreleased objects
-	[[NSTimer scheduledTimerWithTimeInterval:60.0f target:self selector:@selector(kickRunLoop:) userInfo:nil repeats:YES] retain];
 }
 
 - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
@@ -1005,21 +1001,6 @@
 	return [NSApplication sharedApplication];
 }
 
-- (void) kickRunLoop:(NSTimer *)dummy
-{
-	// Send a fake event to wake the loop up.
-	[NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined
-										location:NSMakePoint(0,0)
-								   modifierFlags:0
-									   timestamp:0
-									windowNumber:0
-										 context:NULL
-										 subtype:0
-										   data1:0
-										   data2:0]
-			 atStart:NO];
-}
-
 #pragma mark Scripting
 - (BOOL)application:(NSApplication *)sender delegateHandlesKey:(NSString *)key {
 	BOOL handleKey = NO;
diff -r 506ba640919c -r 396786e9e2b7 Source/AdiumPasswords.m
--- a/Source/AdiumPasswords.m	Mon Jul 18 00:56:21 2011 +0200
+++ b/Source/AdiumPasswords.m	Tue Jul 19 21:31:48 2011 -0700
@@ -34,7 +34,7 @@
 #define KEY_PERFORMED_ACCOUNT_PASSWORD_UPGRADE @"Adium 1.3: Account Passwords Upgraded"
 
 @interface AdiumPasswords ()
-+ (NSOperationQueue *)operationQueue;
++ (dispatch_queue_t)queue;
 - (NSString *)_oldStyleAccountNameForAccount:(AIAccount *)inAccount;




More information about the commits mailing list