THRIFT-2905 Cocoa compiler should have option to produce "modern" Objective-C
Client: Cocoa (ObjectiveC & Swift)
Author: Kevin Wooten <kevin@wooten.com>
This closes #539
diff --git a/lib/cocoa/src/server/TSocketServer.m b/lib/cocoa/src/server/TSocketServer.m
index 07bc829..ccbbba1 100644
--- a/lib/cocoa/src/server/TSocketServer.m
+++ b/lib/cocoa/src/server/TSocketServer.m
@@ -21,37 +21,51 @@
#import "TSocketServer.h"
#import "TNSFileHandleTransport.h"
#import "TProtocol.h"
-#import "TTransportException.h"
-#import "TObjective-C.h"
+#import "TTransportError.h"
+
#import <sys/socket.h>
#include <netinet/in.h>
-NSString * const kTSocketServer_ClientConnectionFinishedForProcessorNotification = @"TSocketServer_ClientConnectionFinishedForProcessorNotification";
-NSString * const kTSocketServer_ProcessorKey = @"TSocketServer_Processor";
-NSString * const kTSockerServer_TransportKey = @"TSockerServer_Transport";
+NSString *const TSocketServerClientConnectionFinished = @"TSocketServerClientConnectionFinished";
+NSString *const TSocketServerProcessorKey = @"TSocketServerProcessor";
+NSString *const TSockerServerTransportKey = @"TSockerServerTransport";
+
+
+@interface TSocketServer ()
+
+@property(strong, nonatomic) id<TProtocolFactory> inputProtocolFactory;
+@property(strong, nonatomic) id<TProtocolFactory> outputProtocolFactory;
+@property(strong, nonatomic) id<TProcessorFactory> processorFactory;
+@property(strong, nonatomic) NSFileHandle *socketFileHandle;
+@property(strong, nonatomic) dispatch_queue_t processingQueue;
+
+@end
@implementation TSocketServer
-- (id) initWithPort: (int) port
- protocolFactory: (id <TProtocolFactory>) protocolFactory
- processorFactory: (id <TProcessorFactory>) processorFactory
+-(instancetype) initWithPort:(int)port
+ protocolFactory:(id <TProtocolFactory>)protocolFactory
+ processorFactory:(id <TProcessorFactory>)processorFactory;
{
self = [super init];
- mInputProtocolFactory = [protocolFactory retain_stub];
- mOutputProtocolFactory = [protocolFactory retain_stub];
- mProcessorFactory = [processorFactory retain_stub];
+ _inputProtocolFactory = protocolFactory;
+ _outputProtocolFactory = protocolFactory;
+ _processorFactory = processorFactory;
+
+ dispatch_queue_attr_t processingQueueAttr =
+ dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_CONCURRENT, QOS_CLASS_BACKGROUND, 0);
+
+ _processingQueue = dispatch_queue_create("TSocketServer.processing", processingQueueAttr);
// create a socket.
int fd = -1;
CFSocketRef socket = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, 0, NULL, NULL);
if (socket) {
- CFOptionFlags flagsToClear = kCFSocketCloseOnInvalidate;
- CFSocketSetSocketFlags(socket, CFSocketGetSocketFlags(socket) & ~flagsToClear);
-
+ CFSocketSetSocketFlags(socket, CFSocketGetSocketFlags(socket) & ~kCFSocketCloseOnInvalidate);
fd = CFSocketGetNative(socket);
int yes = 1;
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(yes));
@@ -63,135 +77,88 @@
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
NSData *address = [NSData dataWithBytes:&addr length:sizeof(addr)];
- if (CFSocketSetAddress(socket, (bridge_stub CFDataRef)address) != kCFSocketSuccess) {
+ if (CFSocketSetAddress(socket, (__bridge CFDataRef)address) != kCFSocketSuccess) {
CFSocketInvalidate(socket);
CFRelease(socket);
- NSLog(@"*** Could not bind to address");
+ NSLog(@"TSocketServer: Could not bind to address");
return nil;
}
- } else {
- NSLog(@"*** No server socket");
+ }
+ else {
+ NSLog(@"TSocketServer: No server socket");
return nil;
}
-
+
// wrap it in a file handle so we can get messages from it
- mSocketFileHandle = [[NSFileHandle alloc] initWithFileDescriptor: fd
- closeOnDealloc: YES];
-
+ _socketFileHandle = [[NSFileHandle alloc] initWithFileDescriptor:fd
+ closeOnDealloc:YES];
+
// throw away our socket
CFSocketInvalidate(socket);
CFRelease(socket);
-
- // register for notifications of accepted incoming connections
- [[NSNotificationCenter defaultCenter] addObserver: self
- selector: @selector(connectionAccepted:)
- name: NSFileHandleConnectionAcceptedNotification
- object: mSocketFileHandle];
-
+
+ // register for notifications of accepted incoming connections
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(connectionAccepted:)
+ name:NSFileHandleConnectionAcceptedNotification
+ object:_socketFileHandle];
+
// tell socket to listen
- [mSocketFileHandle acceptConnectionInBackgroundAndNotify];
-
- NSLog(@"Listening on TCP port %d", port);
-
+ [_socketFileHandle acceptConnectionInBackgroundAndNotify];
+
+ NSLog(@"TSocketServer: Listening on TCP port %d", port);
+
return self;
}
-- (void) dealloc {
+-(void) dealloc
+{
[[NSNotificationCenter defaultCenter] removeObserver:self];
- [mInputProtocolFactory release_stub];
- [mOutputProtocolFactory release_stub];
- [mProcessorFactory release_stub];
- [mSocketFileHandle release_stub];
- [super dealloc_stub];
}
-- (void) connectionAccepted: (NSNotification *) aNotification
+-(void) connectionAccepted:(NSNotification *)notification
{
- NSFileHandle * socket = [[aNotification userInfo] objectForKey: NSFileHandleNotificationFileHandleItem];
+ NSFileHandle *socket = [notification.userInfo objectForKey:NSFileHandleNotificationFileHandleItem];
- // now that we have a client connected, spin off a thread to handle activity
- [NSThread detachNewThreadSelector: @selector(handleClientConnection:)
- toTarget: self
- withObject: socket];
+ // Now that we have a client connected, handle request on queue
+ dispatch_async(_processingQueue, ^{
- [[aNotification object] acceptConnectionInBackgroundAndNotify];
+ [self handleClientConnection:socket];
+
+ });
+
+ // Continue accepting connections
+ [_socketFileHandle acceptConnectionInBackgroundAndNotify];
}
-- (void) handleClientConnection: (NSFileHandle *) clientSocket
+-(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) {
- (void)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];
-
+ @autoreleasepool {
+
+ TNSFileHandleTransport *transport = [[TNSFileHandleTransport alloc] initWithFileHandle:clientSocket];
+ id<TProcessor> processor = [_processorFactory processorForTransport:transport];
+
+ id <TProtocol> inProtocol = [_inputProtocolFactory newProtocolOnTransport:transport];
+ id <TProtocol> outProtocol = [_outputProtocolFactory newProtocolOnTransport:transport];
+
+ NSError *error;
+ if (![processor processOnInputProtocol:inProtocol outputProtocol:outProtocol error:&error]) {
+ // Handle error
+ NSLog(@"Error processing request: %@", error);
}
-#else
- NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
-
- TNSFileHandleTransport * transport = [[TNSFileHandleTransport alloc] initWithFileHandle: clientSocket];
- id<TProcessor> processor = [mProcessorFactory processorForTransport: transport];
-
- id <TProtocol> inProtocol = [[mInputProtocolFactory newProtocolOnTransport: transport] autorelease];
- id <TProtocol> outProtocol = [[mOutputProtocolFactory newProtocolOnTransport: transport] autorelease];
- @try {
- BOOL result = NO;
- do {
- NSAutoreleasePool * myPool = [[NSAutoreleasePool alloc] init];
- result = [processor processOnInputProtocol: inProtocol outputProtocol: outProtocol];
- [myPool release];
- } while (result);
- }
- @catch (TTransportException * te) {
- //NSLog(@"Caught transport exception, abandoning client connection: %@", te);
- }
+ dispatch_async(dispatch_get_main_queue(), ^{
- 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];
-
- [pool release];
-#endif
+ [NSNotificationCenter.defaultCenter postNotificationName:TSocketServerClientConnectionFinished
+ object:self
+ userInfo:@{TSocketServerProcessorKey: processor,
+ TSockerServerTransportKey: transport}];
+ });
+
+ }
}
-
-
@end
-
-
-