Thrift-1340: Add support of ARC to Objective-C
Client: Objective-c
Patch: Hirano Satoshi

Adds -objc-arc flag to compiler and if used removes the retain/release/autorelease from generated code



git-svn-id: https://svn.apache.org/repos/asf/thrift/trunk@1210732 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/cocoa/src/TApplicationException.m b/lib/cocoa/src/TApplicationException.m
index 7068753..66c2f2b 100644
--- a/lib/cocoa/src/TApplicationException.m
+++ b/lib/cocoa/src/TApplicationException.m
@@ -19,6 +19,7 @@
 
 #import "TApplicationException.h"
 #import "TProtocolUtil.h"
+#import "TObjective-C.h"
 
 @implementation TApplicationException
 
@@ -124,7 +125,7 @@
                                       reason: (NSString *) reason
 {
   return [[[TApplicationException alloc] initWithType: type
-                                         reason: reason] autorelease];
+                                         reason: reason] autorelease_stub];
 }
 
 @end
diff --git a/lib/cocoa/src/TException.m b/lib/cocoa/src/TException.m
index 7c84199..0160e3b 100644
--- a/lib/cocoa/src/TException.m
+++ b/lib/cocoa/src/TException.m
@@ -18,6 +18,7 @@
  */
 
 #import "TException.h"
+#import "TObjective-C.h"
 
 @implementation TException
 
diff --git a/lib/cocoa/src/TObjective-C.h b/lib/cocoa/src/TObjective-C.h
new file mode 100644
index 0000000..9c0831d
--- /dev/null
+++ b/lib/cocoa/src/TObjective-C.h
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*
+ * TObjective-C.h is for supporting coexistence of both the ARC (Automatic 
+ * Reference Counting) mode and the Non-ARC mode of Objective-C 
+ * in the same source code.
+ *
+ *                  2011/11/14  HIRANO Satoshi (AIST, Japan)
+ *
+ * Before:
+ *
+ *    var = [aObject retain];
+ *    [aObject release];
+ *    [aObject autorelease];
+ *    [super dealloc];
+ *    CFFunction(obj);
+ *
+ * ARC and Non-ARC compatible:
+ *
+ *    #import "TObjective-C.h"
+ *    var = [aObject retain_stub];
+ *    [aObject release_stub];
+ *    [aObject autorelease_stub];
+ *    [super dealloc_stub];
+ *    CFFunction(bridge_stub obj);
+ *
+ *    Don't use retain_stub for @property(retain).
+ *    Use NSAutoreleasePool like this:
+ *        #if __has_feature(objc_arc)
+ *          @autoreleasepool {
+ *              // code 
+ *          }
+ *        #else
+ *          NSAutoReleasePool *pool = [[NSAutoReleasePool alloc] init...
+ *          // code
+ *          [pool release];
+ *        #endif
+ */
+
+
+#if !defined(retain_stub)
+#if __has_feature(objc_arc)
+#define retain_stub self
+#define autorelease_stub self
+#define release_stub self
+#define dealloc_stub self
+#define bridge_stub __bridge
+#else
+#define retain_stub retain
+#define autorelease_stub autorelease
+#define release_stub release
+#define dealloc_stub dealloc
+#define bridge_stub
+#endif
+#endif
diff --git a/lib/cocoa/src/TSharedProcessorFactory.m b/lib/cocoa/src/TSharedProcessorFactory.m
index b38e73a..a0007c0 100644
--- a/lib/cocoa/src/TSharedProcessorFactory.m
+++ b/lib/cocoa/src/TSharedProcessorFactory.m
@@ -19,6 +19,7 @@
 
 
 #import "TSharedProcessorFactory.h"
+#import "TObjective-C.h"
 
 
 @implementation TSharedProcessorFactory
@@ -31,21 +32,21 @@
     return nil;
   }
   
-  mSharedProcessor = [sharedProcessor retain];
+  mSharedProcessor = [sharedProcessor retain_stub];
   return self;
 }
 
 
 - (void) dealloc
 {
-  [mSharedProcessor release];
-  [super dealloc];
+  [mSharedProcessor release_stub];
+  [super dealloc_stub];
 }
 
 
 - (id<TProcessor>) processorForTransport: (id<TTransport>) transport
 {
-  return [[mSharedProcessor retain] autorelease];
+  return [[mSharedProcessor retain_stub] autorelease_stub];
 }
 
 @end
diff --git a/lib/cocoa/src/protocol/TBinaryProtocol.m b/lib/cocoa/src/protocol/TBinaryProtocol.m
index b272716..f269aaa 100644
--- a/lib/cocoa/src/protocol/TBinaryProtocol.m
+++ b/lib/cocoa/src/protocol/TBinaryProtocol.m
@@ -19,6 +19,7 @@
 
 #import "TBinaryProtocol.h"
 #import "TProtocolException.h"
+#import "TObjective-C.h"
 
 int32_t VERSION_1 = 0x80010000;
 int32_t VERSION_MASK = 0xffff0000;
@@ -56,7 +57,7 @@
              strictWrite: (BOOL) strictWrite
 {
   self = [super init];
-  mTransport = [transport retain];
+  mTransport = [transport retain_stub];
   mStrictRead = strictRead;
   mStrictWrite = strictWrite;
   return self;
@@ -77,8 +78,8 @@
 
 - (void) dealloc
 {
-  [mTransport release];
-  [super dealloc];
+  [mTransport release_stub];
+  [super dealloc_stub];
 }
 
 
diff --git a/lib/cocoa/src/server/TSocketServer.m b/lib/cocoa/src/server/TSocketServer.m
index 5f7fa3c..057f41f 100644
--- a/lib/cocoa/src/server/TSocketServer.m
+++ b/lib/cocoa/src/server/TSocketServer.m
@@ -22,6 +22,7 @@
 #import "TNSFileHandleTransport.h"
 #import "TProtocol.h"
 #import "TTransportException.h"
+#import "TObjective-C.h"
 #import <sys/socket.h>
 #include <netinet/in.h>
 
@@ -40,9 +41,9 @@
 {
   self = [super init];
 
-  mInputProtocolFactory = [protocolFactory retain];
-  mOutputProtocolFactory = [protocolFactory retain];
-  mProcessorFactory = [processorFactory retain];
+  mInputProtocolFactory = [protocolFactory retain_stub];
+  mOutputProtocolFactory = [protocolFactory retain_stub];
+  mProcessorFactory = [processorFactory retain_stub];
 
   // create a socket.
   int fd = -1;
@@ -60,7 +61,7 @@
     addr.sin_port = htons(port);
     addr.sin_addr.s_addr = htonl(INADDR_ANY);
     NSData *address = [NSData dataWithBytes:&addr length:sizeof(addr)];
-    if (CFSocketSetAddress(socket, (CFDataRef)address) != kCFSocketSuccess) {
+    if (CFSocketSetAddress(socket, (bridge_stub CFDataRef)address) != kCFSocketSuccess) {
       CFSocketInvalidate(socket);
       CFRelease(socket);
       NSLog(@"*** Could not bind to address");
@@ -96,11 +97,11 @@
 
 - (void) dealloc {
   [[NSNotificationCenter defaultCenter] removeObject: self];
-  [mInputProtocolFactory release];
-  [mOutputProtocolFactory release];
-  [mProcessorFactory release];
-  [mSocketFileHandle release];
-  [super dealloc];
+  [mInputProtocolFactory release_stub];
+  [mOutputProtocolFactory release_stub];
+  [mProcessorFactory release_stub];
+  [mSocketFileHandle release_stub];
+  [super dealloc_stub];
 }
 
 
@@ -119,6 +120,38 @@
 
 - (void) handleClientConnection: (NSFileHandle *) clientSocket
 {
+#if __has_feature(objc_arc)
+    @autoreleasepool {
+        TNSFileHandleTransport * transport = [[TNSFileHandleTransport alloc] initWithFileHandle: clientSocket];
+        id<TProcessor> processor = [mProcessorFactory processorForTransport: transport];
+        
+        id <TProtocol> inProtocol = [mInputProtocolFactory newProtocolOnTransport: transport];
+        id <TProtocol> outProtocol = [mOutputProtocolFactory newProtocolOnTransport: transport];
+        
+        @try {
+            BOOL result = NO;
+            do {
+                @autoreleasepool {
+                    result = [processor processOnInputProtocol: inProtocol outputProtocol: outProtocol];
+                }
+            } while (result);
+        }
+        @catch (TTransportException * te) {
+            //NSLog(@"Caught transport exception, abandoning client connection: %@", te);
+        }
+        
+        NSNotification * n = [NSNotification notificationWithName: kTSocketServer_ClientConnectionFinishedForProcessorNotification
+                                                           object: self
+                                                         userInfo: [NSDictionary dictionaryWithObjectsAndKeys: 
+                                                                    processor,
+                                                                    kTSocketServer_ProcessorKey,
+                                                                    transport,
+                                                                    kTSockerServer_TransportKey,
+                                                                    nil]];
+        [[NSNotificationCenter defaultCenter] performSelectorOnMainThread: @selector(postNotification:) withObject: n waitUntilDone: YES];
+        
+    }
+#else
   NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
   
   TNSFileHandleTransport * transport = [[TNSFileHandleTransport alloc] initWithFileHandle: clientSocket];
@@ -150,6 +183,7 @@
   [[NSNotificationCenter defaultCenter] performSelectorOnMainThread: @selector(postNotification:) withObject: n waitUntilDone: YES];
   
   [pool release];
+#endif
 }
 
 
diff --git a/lib/cocoa/src/transport/THTTPClient.m b/lib/cocoa/src/transport/THTTPClient.m
index 1eaa859..5617d45 100644
--- a/lib/cocoa/src/transport/THTTPClient.m
+++ b/lib/cocoa/src/transport/THTTPClient.m
@@ -19,6 +19,7 @@
 
 #import "THTTPClient.h"
 #import "TTransportException.h"
+#import "TObjective-C.h"
 
 @implementation THTTPClient
 
@@ -26,7 +27,7 @@
 - (void) setupRequest
 {
   if (mRequest != nil) {
-    [mRequest release];
+    [mRequest release_stub];
   }
 
   // set up our request object that we'll use for each request
@@ -67,9 +68,9 @@
 
   mTimeout = timeout;
   if (userAgent) {
-    mUserAgent = [userAgent retain];
+    mUserAgent = [userAgent retain_stub];
   }
-  mURL = [aURL retain];
+  mURL = [aURL retain_stub];
 
   [self setupRequest];
 
@@ -82,8 +83,8 @@
 
 - (void) setURL: (NSURL *) aURL
 {
-  [aURL retain];
-  [mURL release];
+  [aURL retain_stub];
+  [mURL release_stub];
   mURL = aURL;
 
   [self setupRequest];
@@ -92,12 +93,12 @@
 
 - (void) dealloc
 {
-  [mURL release];
-  [mUserAgent release];
-  [mRequest release];
-  [mRequestData release];
-  [mResponseData release];
-  [super dealloc];
+  [mURL release_stub];
+  [mUserAgent release_stub];
+  [mRequest release_stub];
+  [mRequestData release_stub];
+  [mResponseData release_stub];
+  [super dealloc_stub];
 }
 
 
@@ -151,8 +152,8 @@
   }
 
   // phew!
-  [mResponseData release];
-  mResponseData = [responseData retain];
+  [mResponseData release_stub];
+  mResponseData = [responseData retain_stub];
   mResponseDataOffset = 0;
 }
 
diff --git a/lib/cocoa/src/transport/TMemoryBuffer.m b/lib/cocoa/src/transport/TMemoryBuffer.m
index 869010a..c3801c7 100644
--- a/lib/cocoa/src/transport/TMemoryBuffer.m
+++ b/lib/cocoa/src/transport/TMemoryBuffer.m
@@ -19,6 +19,7 @@
 
 #import "TMemoryBuffer.h"
 #import "TTransportException.h"
+#import "TObjective-C.h"
 
 #define GARBAGE_BUFFER_SIZE 4096 // 4KiB
 
@@ -61,11 +62,11 @@
 }
 
 - (NSData *)getBuffer {
-	return [[mBuffer copy] autorelease];
+	return [[mBuffer copy] autorelease_stub];
 }
 
 - (void)dealloc {
-	[mBuffer release];
-	[super dealloc];
+	[mBuffer release_stub];
+	[super dealloc_stub];
 }
 @end
diff --git a/lib/cocoa/src/transport/TNSFileHandleTransport.m b/lib/cocoa/src/transport/TNSFileHandleTransport.m
index b218218..0ff200b 100644
--- a/lib/cocoa/src/transport/TNSFileHandleTransport.m
+++ b/lib/cocoa/src/transport/TNSFileHandleTransport.m
@@ -20,6 +20,7 @@
 
 #import "TNSFileHandleTransport.h"
 #import "TTransportException.h"
+#import "TObjective-C.h"
 
 
 @implementation TNSFileHandleTransport
@@ -36,17 +37,17 @@
 {
   self = [super init];
 
-  mInputFileHandle = [inputFileHandle retain];
-  mOutputFileHandle = [outputFileHandle retain];
+  mInputFileHandle = [inputFileHandle retain_stub];
+  mOutputFileHandle = [outputFileHandle retain_stub];
 
   return self;
 }
 
 
 - (void) dealloc {
-  [mInputFileHandle release];
-  [mOutputFileHandle release];
-  [super dealloc];
+  [mInputFileHandle release_stub];
+  [mOutputFileHandle release_stub];
+  [super dealloc_stub];
 }
 
 
@@ -66,9 +67,10 @@
 }
 
 
-- (void) write: (uint8_t *) data offset: (unsigned int) offset length: (unsigned int) length
+- (void) write: (const uint8_t *) data offset: (unsigned int) offset length: (unsigned int) length
 {
-  NSData * dataObject = [[NSData alloc] initWithBytesNoCopy: data+offset
+  void *pos = (void *) data + offset;
+  NSData * dataObject = [[NSData alloc] initWithBytesNoCopy: pos // data+offset
                                                      length: length
                                                freeWhenDone: NO];
 
@@ -79,7 +81,7 @@
                                            reason: [NSString stringWithFormat: @"%s: Unable to write data: %@", __PRETTY_FUNCTION__, e]];
   }
 
-  [dataObject release];
+  [dataObject release_stub];
 }
 
 
diff --git a/lib/cocoa/src/transport/TNSStreamTransport.m b/lib/cocoa/src/transport/TNSStreamTransport.m
index 1d4cfee..265e0ba 100644
--- a/lib/cocoa/src/transport/TNSStreamTransport.m
+++ b/lib/cocoa/src/transport/TNSStreamTransport.m
@@ -19,6 +19,7 @@
 
 #import "TNSStreamTransport.h"
 #import "TTransportException.h"
+#import "TObjective-C.h"
 
 
 @implementation TNSStreamTransport
@@ -26,9 +27,9 @@
 - (id) initWithInputStream: (NSInputStream *) input
               outputStream: (NSOutputStream *) output
 {
-  [super init];
-  mInput = [input retain];
-  mOutput = [output retain];
+  self = [super init];
+  mInput = [input retain_stub];
+  mOutput = [output retain_stub];
   return self;
 }
 
@@ -44,9 +45,9 @@
 
 - (void) dealloc
 {
-  [mInput release];
-  [mOutput release];
-  [super dealloc];
+  [mInput release_stub];
+  [mOutput release_stub];
+  [super dealloc_stub];
 }
 
 
@@ -65,7 +66,7 @@
 }
 
 
-- (void) write: (uint8_t *) data offset: (unsigned int) offset length: (unsigned int) length
+- (void) write: (const uint8_t *) data offset: (unsigned int) offset length: (unsigned int) length
 {
   int got = 0;
   int result = 0;
diff --git a/lib/cocoa/src/transport/TSocketClient.h b/lib/cocoa/src/transport/TSocketClient.h
index 0ea957d..372850f 100644
--- a/lib/cocoa/src/transport/TSocketClient.h
+++ b/lib/cocoa/src/transport/TSocketClient.h
@@ -20,7 +20,11 @@
 #import <Foundation/Foundation.h>
 #import "TNSStreamTransport.h"
 
-@interface TSocketClient : TNSStreamTransport {
+@interface TSocketClient : TNSStreamTransport 
+#if TARGET_OS_IPHONE || (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6)
+<NSStreamDelegate>
+#endif
+{
 }
 
 - (id) initWithHostname: (NSString *) hostname
diff --git a/lib/cocoa/src/transport/TSocketClient.m b/lib/cocoa/src/transport/TSocketClient.m
index 74d4af9..256ecf3 100644
--- a/lib/cocoa/src/transport/TSocketClient.m
+++ b/lib/cocoa/src/transport/TSocketClient.m
@@ -17,6 +17,7 @@
  * under the License.
  */
 #import "TSocketClient.h"
+#import "TObjective-C.h"
 
 #if !TARGET_OS_IPHONE
 #import <CoreServices/CoreServices.h>
@@ -33,22 +34,24 @@
 	NSOutputStream * outputStream = NULL;
 	CFReadStreamRef readStream = NULL;
 	CFWriteStreamRef writeStream = NULL;
-	CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, (CFStringRef)hostname, port, &readStream, &writeStream);
+	CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, (bridge_stub CFStringRef)hostname, port, &readStream, &writeStream);
 	if (readStream && writeStream) {
 		CFReadStreamSetProperty(readStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
 		CFWriteStreamSetProperty(writeStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
 		
-		inputStream = (NSInputStream *)readStream;
-		[inputStream retain];
+		inputStream = (bridge_stub NSInputStream *)readStream;
+		[inputStream retain_stub];
 		[inputStream setDelegate:self];
 		[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
 		[inputStream open];
 		
-		outputStream = (NSOutputStream *)writeStream;
-		[outputStream retain];
+		outputStream = (bridge_stub NSOutputStream *)writeStream;
+		[outputStream retain_stub];
 		[outputStream setDelegate:self];
 		[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
 		[outputStream open];
+        CFRelease(readStream);
+        CFRelease(writeStream);
 	}
 	
 	self = [super initWithInputStream: inputStream outputStream: outputStream];
diff --git a/lib/cocoa/src/transport/TTransportException.m b/lib/cocoa/src/transport/TTransportException.m
index aa67149..43cdfbd 100644
--- a/lib/cocoa/src/transport/TTransportException.m
+++ b/lib/cocoa/src/transport/TTransportException.m
@@ -18,6 +18,7 @@
  */
 
 #import "TTransportException.h"
+#import "TObjective-C.h"
 
 @implementation TTransportException