Revision: 27856 http://sourceforge.net/p/bibdesk/svn/27856 Author: hofman Date: 2022-09-06 21:25:50 +0000 (Tue, 06 Sep 2022) Log Message: ----------- Don't use DO server to run async thread. Instead run the background thread, pass messages through performSelector:onThread:withObject:waitUntilDone: and pass messages to main thread using GCD. Rename classes and ivars, as the object is not a DO server anymore.
Modified Paths: -------------- trunk/bibdesk/BDSKAsynchronousDOServer.h trunk/bibdesk/BDSKAsynchronousDOServer.m trunk/bibdesk/BDSKSharingClient.h trunk/bibdesk/BDSKSharingClient.m trunk/bibdesk/BDSKSharingServer.h trunk/bibdesk/BDSKSharingServer.m trunk/bibdesk/BDSKZoomGroupServer.h trunk/bibdesk/BDSKZoomGroupServer.m Modified: trunk/bibdesk/BDSKAsynchronousDOServer.h =================================================================== --- trunk/bibdesk/BDSKAsynchronousDOServer.h 2022-09-05 18:23:38 UTC (rev 27855) +++ trunk/bibdesk/BDSKAsynchronousDOServer.h 2022-09-06 21:25:50 UTC (rev 27856) @@ -1,5 +1,5 @@ // -// BDSKAsynchronousDOServer.h +// BDSKAsyncObject.h // Bibdesk // // Created by Adam Maxwell on 04/24/06. @@ -37,20 +37,13 @@ */ #import <Cocoa/Cocoa.h> -#import <libkern/OSAtomic.h> -// protocols for the server proxies, should be included in protocols used by subclasses -@protocol BDSKAsyncDOServerThread, BDSKAsyncDOServerMainThread; -@interface BDSKAsynchronousDOServer : NSObject { +@interface BDSKAsyncObject : NSObject { @private - id serverOnMainThread; // proxy for the main thread - id serverOnServerThread; // proxy for the local server thread - NSConnection *mainThreadConnection; // so the local server thread can talk to the main thread - NSConnection *localThreadConnection; // so the main thread can talk to the local server thread - NSThread *serverThread; // mainly for debugging + NSThread *localThread; // mainly for debugging BOOL stopRunning; // set to signal to stop running the run loop for the local server thread - struct BDSKDOServerFlags *serverFlags; // state variables + struct BDSKAsyncObjectFlags *aoFlags; // state variables } /* @@ -57,31 +50,21 @@ If you override -init (designated initializer), call -startDOServerSync or -startDOServerAsync as the last step of initialization or after all necessary ivars are set. If -init isn't overriden, call one of the start methods after initializing the object. */ -// detaches the server thread and returns when proxies are set up -- (void)startDOServerSync; +// detaches the server thread and returns immediately +- (void)start; -// detaches the server thread and returns immediately; proxies may not be usable on return -- (void)startDOServerAsync; - // override for custom cleanup on the main thread; call super afterwards -- (void)stopDOServer; +- (void)stop; // override for custom setup after the server has been setup; called on the server thread; default does nothing -- (void)serverDidSetup; +- (void)didSetup; // override for custom cleanup on the server thread; default does nothing -- (void)serverDidFinish; +- (void)didFinish; // run loop flag; thread safe @property (nonatomic, readonly) BOOL shouldKeepRunning; -// use these proxies to message the server object; do not override; only use them from the other thread -@property (nonatomic, readonly) id serverOnMainThread; -@property (nonatomic, readonly) id serverOnServerThread; +- (void)performSelectorOnLocalThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait; -// override to add additional methods adopted by serverOn...Thread objects; they should always adopt our protocols -@property (nonatomic, readonly) Protocol *protocolForServerThread; // protocol must adopt <BDSKAsyncDOServerThread> -@property (nonatomic, readonly) Protocol *protocolForMainThread; // protocol must adopt <BDSKAsyncDOServerMainThread> - - @end Modified: trunk/bibdesk/BDSKAsynchronousDOServer.m =================================================================== --- trunk/bibdesk/BDSKAsynchronousDOServer.m 2022-09-05 18:23:38 UTC (rev 27855) +++ trunk/bibdesk/BDSKAsynchronousDOServer.m 2022-09-06 21:25:50 UTC (rev 27856) @@ -1,5 +1,5 @@ // -// BDSKAsynchronousDOServer.m +// BDSKAsyncObject.m // Bibdesk // // Created by Adam Maxwell on 04/24/06. @@ -36,40 +36,30 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#import "BDSKAsynchronousDOServer.h" +#import "BDSKAsyncObject.h" #import <objc/runtime.h> +#import <libkern/OSAtomic.h> -struct BDSKDOServerFlags { +struct BDSKAsyncObjectFlags { volatile int32_t shouldKeepRunning; - volatile int32_t serverDidSetup; #ifdef DEBUG - volatile int32_t serverDidStart; + volatile int32_t didStart; #endif }; -// protocols for the server thread proxies, must be included in protocols used by subclasses -@protocol BDSKAsyncDOServerThread -- (oneway void)stopRunning; +@interface BDSKAsyncObject (Private) +- (void)runLocalThread; +- (void)stopRunning; @end -@protocol BDSKAsyncDOServerMainThread -- (void)setLocalServer:(byref id)anObject; -@end +@implementation BDSKAsyncObject +@dynamic shouldKeepRunning; -@interface BDSKAsynchronousDOServer (Private) -// avoid categories in the implementation, since categories and formal protocols don't mix -- (void)runDOServerForPorts:(NSArray *)ports; -@end - -@implementation BDSKAsynchronousDOServer - -@dynamic shouldKeepRunning, serverOnMainThread, serverOnServerThread, protocolForMainThread, protocolForServerThread; - #ifdef DEBUG - (void)checkStartup:(NSTimer *)ignored { - if (0 == serverFlags->serverDidStart) + if (0 == aoFlags->didStart) NSLog(@"*** Warning *** %@ has not been started after 1 second", self); } #endif @@ -79,20 +69,15 @@ self = [super init]; if (self) { // set up flags - serverFlags = NSZoneCalloc(NSDefaultMallocZone(), 1, sizeof(struct BDSKDOServerFlags)); - serverFlags->shouldKeepRunning = 1; - serverFlags->serverDidSetup = 0; + aoFlags = NSZoneCalloc(NSDefaultMallocZone(), 1, sizeof(struct BDSKAsyncObjectFlags)); + aoFlags->shouldKeepRunning = 1; #ifdef DEBUG - serverFlags->serverDidStart = 0; + aoFlags->didStart = 0; - // check for absentminded developers; there's no actual requirement that startDOServer be called immediately + // check for absentminded developers; there's no actual requirement that start be called immediately [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(checkStartup:) userInfo:nil repeats:NO]; #endif - // these will be set when the background thread sets up - localThreadConnection = nil; - serverOnMainThread = nil; - serverOnServerThread = nil; stopRunning = NO; } return self; @@ -100,117 +85,51 @@ - (void)dealloc { - BDSKZONEDESTROY(serverFlags); + BDSKZONEDESTROY(aoFlags); [super dealloc]; } -#pragma mark Proxies - -- (Protocol *)protocolForServerThread; -{ - return @protocol(BDSKAsyncDOServerThread); -} - -- (Protocol *)protocolForMainThread; -{ - return @protocol(BDSKAsyncDOServerMainThread); -} - -// Access to these objects is limited to the creating threads (we assume that it's initially created on the main thread). If you want to communicate with the server from yet another thread, that thread needs to create its own connection and proxy object(s), which would also require access to the server's connection ivars. Possibly using -enableMultipleThreads on both connections would work, but the documentation is too vague to be useful. - -- (id)serverOnMainThread { - BDSKASSERT([[NSThread currentThread] isEqual:serverThread]); - return serverOnMainThread; -} - -- (id)serverOnServerThread { - BDSKASSERT([NSThread isMainThread]); - return serverOnServerThread; -} - #pragma mark Main Thread -- (void)setLocalServer:(byref id)anObject; +- (void)start; { - BDSKASSERT([NSThread isMainThread]); - BDSKASSERT(protocol_conformsToProtocol([self protocolForServerThread], @protocol(BDSKAsyncDOServerThread))); - [anObject setProtocolForProxy:[self protocolForServerThread]]; - serverOnServerThread = [anObject retain]; -} - -- (void)startDOServer; -{ #ifdef DEBUG - serverFlags->serverDidStart = 1; + aoFlags->didStart = 1; #endif - // set up a connection to communicate with the local background thread - NSPort *port1 = [NSPort port]; - NSPort *port2 = [NSPort port]; - - mainThreadConnection = [[NSConnection alloc] initWithReceivePort:port1 sendPort:port2]; - [mainThreadConnection setRootObject:self]; - - // enable explicitly; we don't want this, but it's set by default on 10.5 and we need to be uniform for debugging - [mainThreadConnection enableMultipleThreads]; - - // run a background thread to connect to the remote server - // this will connect back to the connection we just set up - [NSThread detachNewThreadSelector:@selector(runDOServerForPorts:) toTarget:self withObject:[NSArray arrayWithObjects:port2, port1, nil]]; - - // It would be really nice if we could just wait on a condition lock here, but - // then this thread's runloop can't pick up the -setLocalServer message since - // it's blocking (the runloop can't service the ports). + // run a background thread + localThread = [[NSThread alloc] initWithTarget:self selector:@selector(runLocalThread) object:nil]; + [localThread start]; +} - do { - SInt32 result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, TRUE); - if (kCFRunLoopRunFinished == result || kCFRunLoopRunStopped == result) - OSAtomicCompareAndSwap32Barrier(1, 0, &serverFlags->shouldKeepRunning); - else - OSMemoryBarrier(); - } while (serverFlags->serverDidSetup == 0 && serverFlags->shouldKeepRunning == 1); +- (void)performSelectorOnLocalThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait { + if (localThread) + [self performSelector:aSelector onThread:localThread withObject:arg waitUntilDone:wait]; } -#pragma mark Server Thread +#pragma mark Local Thread -- (oneway void)stopRunning { - BDSKASSERT([[NSThread currentThread] isEqual:serverThread]); +- (void)stopRunning { + BDSKASSERT([NSThread isMainThread] == NO); // signal to stop running the run loop stopRunning = YES; } -- (void)runDOServerForPorts:(NSArray *)ports; +- (void)runLocalThread; { // detach a new thread to run this - NSAssert([NSThread isMainThread] == NO, @"do not run the server in the main thread"); - NSAssert(localThreadConnection == nil, @"server is already running"); + NSAssert([NSThread isMainThread] == NO, @"do not run in the main thread"); NSAutoreleasePool *pool = [NSAutoreleasePool new]; + NSRunLoop *runLoop = [NSRunLoop currentRunLoop]; + NSPort *dummyPort = [[NSMachPort alloc] init]; @try { + // a run loop needs at least one source to run + [runLoop addPort:dummyPort forMode:NSDefaultRunLoopMode]; - // this thread retains the server object - serverThread = [NSThread currentThread]; - - // we'll use this to communicate between threads on the localhost - localThreadConnection = [[NSConnection alloc] initWithReceivePort:[ports objectAtIndex:0] sendPort:[ports objectAtIndex:1]]; - if(localThreadConnection == nil) - @throw @"Unable to create localThreadConnection"; - [localThreadConnection setRootObject:self]; - - // enable explicitly; we don't need this, but it's set by default on 10.5 and we need to be uniform for debugging - [localThreadConnection enableMultipleThreads]; - - serverOnMainThread = [[localThreadConnection rootProxy] retain]; - BDSKASSERT(protocol_conformsToProtocol([self protocolForMainThread], @protocol(BDSKAsyncDOServerMainThread))); - [serverOnMainThread setProtocolForProxy:[self protocolForMainThread]]; - // handshake, this sets the proxy at the other side - [serverOnMainThread setLocalServer:self]; - // allow subclasses to do some custom setup - [self serverDidSetup]; - OSAtomicCompareAndSwap32Barrier(0, 1, &serverFlags->serverDidSetup); + [self didSetup]; - NSRunLoop *rl = [NSRunLoop currentRunLoop]; NSDate *distantFuture = [[NSDate distantFuture] retain]; BOOL didRun; @@ -218,7 +137,7 @@ do { [pool release]; pool = [NSAutoreleasePool new]; - didRun = [rl runMode:NSDefaultRunLoopMode beforeDate:distantFuture]; + didRun = [runLoop runMode:NSDefaultRunLoopMode beforeDate:distantFuture]; } while (stopRunning == NO && didRun); [distantFuture release]; @@ -225,65 +144,33 @@ } @catch(id exception) { NSLog(@"Exception \"%@\" raised in object %@", exception, self); - // allow the main thread to continue, anyway - OSAtomicCompareAndSwap32Barrier(0, 1, &serverFlags->serverDidSetup); } @finally { // allow subclasses to do some custom cleanup - [self serverDidFinish]; + [self didFinish]; - // clean up the connection in the server thread - [localThreadConnection setRootObject:nil]; + [runLoop removePort:dummyPort forMode:NSDefaultRunLoopMode]; + BDSKDESTROY(dummyPort); - // this frees up the CFMachPorts created in -init - [[localThreadConnection receivePort] invalidate]; - [[localThreadConnection sendPort] invalidate]; - [localThreadConnection invalidate]; - BDSKDESTROY(localThreadConnection); - BDSKDESTROY(serverOnMainThread); - serverThread = nil; - [pool release]; } } -- (void)serverDidSetup{} -- (void)serverDidFinish{} +- (void)didSetup{} +- (void)didFinish{} #pragma mark API #pragma mark Main Thread -- (void)startDOServerSync; +- (void)stop; { - BDSKASSERT([NSThread isMainThread]); - // no need for memory barrier functions here since there's no thread yet - serverFlags->serverDidSetup = 0; - [self startDOServer]; -} - -- (void)startDOServerAsync; -{ - BDSKASSERT([NSThread isMainThread]); - // no need for memory barrier functions here since there's no thread yet - // set serverDidSetup to 1 so we don't wait in startDOServer - serverFlags->serverDidSetup = 1; - [self startDOServer]; -} - -- (void)stopDOServer; -{ BDSKASSERT([NSThread isMainThread]); // set the stop flag, so any long process (possibly with loops) knows it can return - OSAtomicCompareAndSwap32Barrier(1, 0, &serverFlags->shouldKeepRunning); - // this is mainly to tickle the runloop on the server thread so it will finish - [serverOnServerThread stopRunning]; - - // clean up the connection in the main thread; don't invalidate the ports, since they're still in use - [mainThreadConnection setRootObject:nil]; - [mainThreadConnection invalidate]; - BDSKDESTROY(mainThreadConnection); - BDSKDESTROY(serverOnServerThread); + OSAtomicCompareAndSwap32Barrier(1, 0, &aoFlags->shouldKeepRunning); + // this is mainly to tickle the runloop on the local thread so it will finish + [self performSelectorOnLocalThread:@selector(stopRunning) withObject:nil waitUntilDone:NO]; + BDSKDESTROY(localThread); } #pragma mark Thread Safe @@ -290,7 +177,7 @@ - (BOOL)shouldKeepRunning { OSMemoryBarrier(); - return serverFlags->shouldKeepRunning == 1; + return aoFlags->shouldKeepRunning == 1; } @end Modified: trunk/bibdesk/BDSKSharingClient.h =================================================================== --- trunk/bibdesk/BDSKSharingClient.h 2022-09-05 18:23:38 UTC (rev 27855) +++ trunk/bibdesk/BDSKSharingClient.h 2022-09-06 21:25:50 UTC (rev 27856) @@ -40,7 +40,7 @@ extern NSString *BDSKSharingClientFailedKey; -@class BDSKSharingClientServer; +@class BDSKAsyncSharingClient; @interface BDSKSharingClient : NSObject { NSData *archivedPublications; @@ -47,7 +47,7 @@ NSData *archivedMacros; BOOL needsUpdate; NSString *name; - BDSKSharingClientServer *server; + BDSKAsyncSharingClient *asyncClient; } - (id)initWithService:(NSNetService *)aService; Modified: trunk/bibdesk/BDSKSharingClient.m =================================================================== --- trunk/bibdesk/BDSKSharingClient.m 2022-09-05 18:23:38 UTC (rev 27855) +++ trunk/bibdesk/BDSKSharingClient.m 2022-09-06 21:25:50 UTC (rev 27856) @@ -37,11 +37,12 @@ */ #import "BDSKSharingClient.h" -#import "BDSKAsynchronousDOServer.h" +#import "BDSKAsyncObject.h" #import "BDSKSharingServer.h" #import "BDSKPasswordController.h" #import "NSData_BDSKExtensions.h" #import "CFString_BDSKExtensions.h" +#import <libkern/OSAtomic.h> static NSString *BDSKClientServiceNameForKeychain = @"BibDesk Sharing Access"; @@ -53,25 +54,8 @@ volatile int32_t failedDownload; } BDSKSharingClientFlags; -// private protocols for inter-thread messaging -@protocol BDSKSharingClientServerLocalThread <BDSKAsyncDOServerThread> - -- (oneway void)retrievePublications; - -@end - -@protocol BDSKSharingClientServerMainThread <BDSKAsyncDOServerMainThread> - -- (void)setArchivedPublicationsAndMacros:(bycopy NSDictionary *)dictionary; -- (NSInteger)runAuthenticationFailedAlert; -- (bycopy NSString *)passwordFromPanel; - -@end - -#pragma mark - - -// private class for DO server. We have it as a separate object so we don't get a retain loop, we remove it from the thread runloop in the client's dealloc -@interface BDSKSharingClientServer : BDSKAsynchronousDOServer <NSNetServiceDelegate, NSConnectionDelegate> { +// private class for async object. We have it as a separate object so we don't get a retain loop, we remove it from the thread runloop in the client's dealloc +@interface BDSKAsyncSharingClient : BDSKAsyncObject <NSNetServiceDelegate, NSConnectionDelegate> { NSNetService *service; // service with information about the remote server (BDSKSharingServer) BDSKSharingClient *client; // the owner of the local server (BDSKSharingClient) id remoteServer; // proxy for the remote sharing server to which we connect @@ -90,7 +74,7 @@ @property (readonly) BOOL failedDownload; @property (copy) NSString *errorMessage; -- (void)retrievePublicationsInBackground; +- (void)retrievePublications; @end @@ -110,13 +94,13 @@ archivedPublications = nil; archivedMacros = nil; needsUpdate = YES; - server = [[BDSKSharingClientServer alloc] initWithClient:self andService:aService]; + asyncClient = [[BDSKAsyncSharingClient alloc] initWithClient:self andService:aService]; } return self; } - (void)dealloc { - if (server) + if (asyncClient) BDSKENSURE_MAIN_THREAD( [self terminate]; ); BDSKDESTROY(archivedPublications); BDSKDESTROY(archivedMacros); @@ -129,12 +113,12 @@ } - (void)terminate { - [server stopDOServer]; - BDSKDESTROY(server); + [asyncClient stop]; + BDSKDESTROY(asyncClient); } - (void)retrievePublications { - [server retrievePublicationsInBackground]; + [asyncClient performSelectorOnLocalThread:@selector(retrievePublications) withObject:nil waitUntilDone:NO]; } - (void)setArchivedPublicationsAndMacros:(NSDictionary *)dictionary { @@ -153,29 +137,29 @@ [self setNeedsUpdate:NO]; // we need to do this after setting the archivedPublications but before sending the notification - [server setRetrieving:NO]; + [asyncClient setRetrieving:NO]; [[NSNotificationCenter defaultCenter] postNotificationName:BDSKSharingClientUpdatedNotification object:self]; } - (BOOL)isRetrieving { - return (BOOL)[server isRetrieving]; + return (BOOL)[asyncClient isRetrieving]; } - (BOOL)failedDownload { - return [server failedDownload]; + return [asyncClient failedDownload]; } - (BOOL)needsAuthentication { - return [server needsAuthentication]; + return [asyncClient needsAuthentication]; } - (BOOL)authenticationFailed { - return [server authenticationFailed]; + return [asyncClient authenticationFailed]; } - (NSString *)errorMessage { - return [server errorMessage]; + return [asyncClient errorMessage]; } @end @@ -182,7 +166,7 @@ #pragma mark - -@implementation BDSKSharingClientServer +@implementation BDSKAsyncSharingClient @synthesize errorMessage; @dynamic retrieving, needsAuthentication, authenticationFailed, failedDownload; @@ -216,7 +200,7 @@ errorMessage = nil; - [self startDOServerAsync]; + [self start]; } return self; } @@ -304,7 +288,7 @@ return YES; } while ([self shouldKeepRunning] && uniqueIdentifier != nil) { - NSString *password = nil; + __block NSString *password = nil; BOOL fromPanel = NO; OSAtomicCompareAndSwap32Barrier(1, 0, &flags.canceledAuthentication); @@ -318,7 +302,9 @@ if (password == nil) { // run the prompt on the main thread - password = [[self serverOnMainThread] passwordFromPanel]; + dispatch_sync(dispatch_get_main_queue(), ^{ + password = [self passwordFromPanel]; + }); if (password == nil) { // cancceled by user @@ -341,7 +327,9 @@ OSAtomicCompareAndSwap32Barrier(0, 1, &flags.authenticationFailed); // don't show the alert when we couldn't authenticate when cleaning up if ([self shouldKeepRunning]) { - [[self serverOnMainThread] runAuthenticationFailedAlert]; + dispatch_sync(dispatch_get_main_queue(), ^{ + [self runAuthenticationFailedAlert]; + }); } return NO; } @@ -366,7 +354,7 @@ if (flags.needsAuthentication == 3) { // legacy server of version 0 expect authentication through this method - NSString *password = nil; + __block NSString *password = nil; OSAtomicCompareAndSwap32Barrier(1, 0, &flags.canceledAuthentication); @@ -377,7 +365,13 @@ if(password == nil && [self shouldKeepRunning]){ // run the prompt on the main thread - password = [([NSThread isMainThread] ? self : [self serverOnMainThread]) passwordFromPanel]; + if ([NSThread isMainThread]) { + password = [self passwordFromPanel]; + } else { + dispatch_sync(dispatch_get_main_queue(), ^{ + password = [self passwordFromPanel]; + }); + } // retry from the keychain if (password){ @@ -461,7 +455,9 @@ OSAtomicCompareAndSwap32Barrier(0, 1, &flags.authenticationFailed); // don't show the alert when we couldn't authenticate when cleaning up if([self shouldKeepRunning]){ - [[self serverOnMainThread] runAuthenticationFailedAlert]; + dispatch_sync(dispatch_get_main_queue(), ^{ + [self runAuthenticationFailedAlert]; + }); } } @@ -486,7 +482,7 @@ uniqueIdentifier = (id)BDCreateUniqueString(); @try { NSProtocolChecker *checker = [NSProtocolChecker protocolCheckerWithTarget:self protocol:@protocol(BDSKSharingClient)]; - [proxy registerClient:checker forIdentifier:uniqueIdentifier version:[BDSKSharingClientServer supportedProtocolVersion]]; + [proxy registerClient:checker forIdentifier:uniqueIdentifier version:[BDSKAsyncSharingClient supportedProtocolVersion]]; // mark as not yet authenticated isNew = YES; } @@ -509,16 +505,6 @@ #pragma mark ServerThread -- (Protocol *)protocolForServerThread { return @protocol(BDSKSharingClientServerLocalThread); } -- (Protocol *)protocolForMainThread { return @protocol(BDSKSharingClientServerMainThread); } - -- (void)setArchivedPublicationsAndMacros:(bycopy NSDictionary *)setArchivedPublicationsAndMacros; -{ - [client setArchivedPublicationsAndMacros:setArchivedPublicationsAndMacros]; -} - -- (void)retrievePublicationsInBackground{ [[self serverOnServerThread] retrievePublications]; } - - (oneway void)retrievePublications; { // set so we don't try calling this multiple times @@ -542,7 +528,9 @@ } } // use the main thread; this avoids an extra (un)archiving between threads and it ends up posting notifications for UI updates - [[self serverOnMainThread] setArchivedPublicationsAndMacros:archive]; + dispatch_sync(dispatch_get_main_queue(), ^{ + [client setArchivedPublicationsAndMacros:archive]; + }); // the client will reset the isRetriving flag when the data is set } @catch(id exception){ @@ -561,7 +549,7 @@ } } -- (void)serverDidFinish; +- (void)didFinish; { // clean up our remote end if (uniqueIdentifier != nil){ Modified: trunk/bibdesk/BDSKSharingServer.h =================================================================== --- trunk/bibdesk/BDSKSharingServer.h 2022-09-05 18:23:38 UTC (rev 27855) +++ trunk/bibdesk/BDSKSharingServer.h 2022-09-06 21:25:50 UTC (rev 27856) @@ -73,9 +73,11 @@ BDSKSharingStatusSharing }; +@class BDSKAsyncSharingServer; + @interface BDSKSharingServer : NSObject <NSNetServiceDelegate> { NSNetService *netService; - id server; + BDSKAsyncSharingServer *asyncServer; NSString *sharingName; int socketDescriptor; BDSKSharingStatus status; Modified: trunk/bibdesk/BDSKSharingServer.m =================================================================== --- trunk/bibdesk/BDSKSharingServer.m 2022-09-05 18:23:38 UTC (rev 27855) +++ trunk/bibdesk/BDSKSharingServer.m 2022-09-06 21:25:50 UTC (rev 27856) @@ -45,8 +45,7 @@ #import "NSData_BDSKExtensions.h" #import "BibItem.h" #import "BibDocument.h" -#import <libkern/OSAtomic.h> -#import "BDSKAsynchronousDOServer.h" +#import "BDSKAsyncObject.h" #import "BDSKReadWriteLock.h" #import "BDSKPublicationsArray.h" #import "BDSKMacroResolver.h" @@ -120,19 +119,7 @@ #pragma mark - -// private protocols for inter-thread messaging - -@protocol BDSKSharingServerLocalThread <BDSKAsyncDOServerThread> -- (oneway void)notifyClientsOfChange; -@end - -@protocol BDSKSharingServerMainThread <BDSKAsyncDOServerMainThread> -- (oneway void)localThreadServerDidSetup:(BOOL)success withPort:(int)port; -@end - -#pragma mark - - -@interface BDSKSharingDOServer : BDSKAsynchronousDOServer <NSConnectionDelegate> { +@interface BDSKAsyncSharingServer : BDSKAsyncObject <NSConnectionDelegate> { BDSKSharingServer *sharingServer; NSString *sharingName; NSConnection *connection; @@ -148,6 +135,8 @@ @property NSUInteger numberOfConnections; +- (void)notifyClientsOfChange; + @end #pragma mark - @@ -253,7 +242,7 @@ - (NSUInteger)numberOfConnections { // minor thread-safety issue here; this may be off by one - return [server numberOfConnections]; + return [asyncServer numberOfConnections]; } - (void)handleQueuedDataChanged; @@ -260,8 +249,8 @@ { // not the default connection here; we want to call our background thread, but only if it's running // add a hidden pref in case this traffic turns us into a bad network citizen; manual updates will still work - if([server shouldKeepRunning] && [[NSUserDefaults standardUserDefaults] boolForKey:BDSKDisableRemoteChangeNotificationsKey] == 0){ - [[server serverOnServerThread] notifyClientsOfChange]; + if([asyncServer shouldKeepRunning] && [[NSUserDefaults standardUserDefaults] boolForKey:BDSKDisableRemoteChangeNotificationsKey] == 0){ + [asyncServer performSelectorOnLocalThread:@selector(notifyClientsOfChange) withObject:nil waitUntilDone:NO]; } } @@ -345,7 +334,7 @@ [self setSharingName:[NSString stringWithFormat:@"%@-%ld", [BDSKSharingServer sharingName], (long)tryCount]]; ++tryCount; - server = [[BDSKSharingDOServer alloc] initForSharingServer:self]; + asyncServer = [[BDSKAsyncSharingServer alloc] initForSharingServer:self]; // the netService is created in the callback [self setStatus:BDSKSharingStatusStarting]; @@ -380,8 +369,8 @@ close(socketDescriptor); socketDescriptor = -1; - [server stopDOServer]; - BDSKDESTROY(server); + [asyncServer stop]; + BDSKDESTROY(asyncServer); // unregister for notifications NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; @@ -410,8 +399,8 @@ } } -- (void)server:(BDSKSharingDOServer *)aServer didSetup:(BOOL)success withPort:(int)port { - BDSKASSERT(aServer == server || server == nil); +- (void)server:(BDSKAsyncSharingServer *)aServer didSetup:(BOOL)success withPort:(int)port { + BDSKASSERT(aServer == asyncServer || asyncServer == nil); if (success) { // the service was able to register the port @@ -479,11 +468,11 @@ // the service was not able to register the port // shouldn't happen - if (server != aServer) - [aServer stopDOServer]; + if (asyncServer != aServer) + [aServer stop]; - [server stopDOServer]; - BDSKDESTROY(server); + [asyncServer stop]; + BDSKDESTROY(asyncServer); [self setStatus:BDSKSharingStatusOff]; @@ -583,7 +572,7 @@ #pragma mark - -@implementation BDSKSharingDOServer +@implementation BDSKAsyncSharingServer @dynamic numberOfConnections; @@ -601,7 +590,7 @@ registeredClients = [[NSMutableDictionary alloc] init]; numberOfConnections = 0; rwLock = [[BDSKReadWriteLock alloc] init]; - [self startDOServerAsync]; + [self start]; } return self; } @@ -633,26 +622,17 @@ #pragma mark Main Thread -- (void)stopDOServer { +- (void)stop { // make sure we don't message our sharingServer sharingServer = nil; - [super stopDOServer]; + [super stop]; } -- (oneway void)localThreadServerDidSetup:(BOOL)success withPort:(int)port -{ - [sharingServer server:(BDSKSharingDOServer *)self didSetup:success withPort:port]; -} +#pragma mark Local Thread -#pragma mark Server Thread +#pragma mark | Async Object -#pragma mark | DO Server - -- (Protocol *)protocolForServerThread { return @protocol(BDSKSharingServerLocalThread); } - -- (Protocol *)protocolForMainThread { return @protocol(BDSKSharingServerMainThread); } - -- (void)serverDidSetup +- (void)didSetup { // setup our DO server that will handle requests for publications and passwords BOOL success = YES; @@ -682,11 +662,13 @@ // the callback from the delegate should stop the DO server, and may try again with a different name } @finally { - [[self serverOnMainThread] localThreadServerDidSetup:success withPort:port]; + dispatch_async(dispatch_get_main_queue(), ^{ + [sharingServer server:self didSetup:success withPort:port]; + }); } } -- (void)serverDidFinish +- (void)didFinish { if (connection == nil) return; @@ -763,7 +745,7 @@ [client setProxy:clientObject]; [client invalidate]; [client release]; - }else if([version numericCompare:[BDSKSharingDOServer requiredProtocolVersion]] == NSOrderedAscending){ + }else if([version numericCompare:[BDSKAsyncSharingServer requiredProtocolVersion]] == NSOrderedAscending){ [client invalidate]; [connectedClients removeObject:client]; }else{ @@ -804,7 +786,7 @@ }); } -- (oneway void)notifyClientsOfChange; +- (void)notifyClientsOfChange; { // here is where we notify other hosts that something changed for (NSString *key in [registeredClients allKeys]) { Modified: trunk/bibdesk/BDSKZoomGroupServer.h =================================================================== --- trunk/bibdesk/BDSKZoomGroupServer.h 2022-09-05 18:23:38 UTC (rev 27855) +++ trunk/bibdesk/BDSKZoomGroupServer.h 2022-09-06 21:25:50 UTC (rev 27856) @@ -39,7 +39,7 @@ #import <Cocoa/Cocoa.h> #import <yaz/ZOOMObjC.h> #import "BDSKSearchGroup.h" -#import "BDSKAsynchronousDOServer.h" +#import "BDSKAsyncObject.h" typedef struct _BDSKZoomGroupFlags { @@ -51,7 +51,7 @@ @class BDSKServerInfo, BDSKReadWriteLock; -@interface BDSKZoomGroupServer : BDSKAsynchronousDOServer <BDSKSearchGroupServer> +@interface BDSKZoomGroupServer : BDSKAsyncObject <BDSKSearchGroupServer> { id<BDSKSearchGroup> group; ZOOMConnection *connection; Modified: trunk/bibdesk/BDSKZoomGroupServer.m =================================================================== --- trunk/bibdesk/BDSKZoomGroupServer.m 2022-09-05 18:23:38 UTC (rev 27855) +++ trunk/bibdesk/BDSKZoomGroupServer.m 2022-09-06 21:25:50 UTC (rev 27856) @@ -44,6 +44,7 @@ #import "CFString_BDSKExtensions.h" #import <SystemConfiguration/SystemConfiguration.h> #import "BDSKReadWriteLock.h" +#import <libkern/OSAtomic.h> #define MAX_RESULTS 100 @@ -54,16 +55,11 @@ #define DCXML_STRING @"DC XML" #define MODS_STRING @"MODS" -// private protocols for inter-thread messaging -@protocol BDSKZoomGroupServerMainThread <BDSKAsyncDOServerMainThread> -- (void)addPublicationsFromResults:(bycopy NSArray *)results; +@interface BDSKZoomGroupServer (Private) +- (void)downloadWithSearchTerm:(NSString *)searchTerm; +- (void)terminateConnection; @end -@protocol BDSKZoomGroupServerLocalThread <BDSKAsyncDOServerThread> -- (oneway void)downloadWithSearchTerm:(NSString *)searchTerm; -- (oneway void)terminateConnection; -@end - @implementation BDSKZoomGroupServer @dynamic errorMessage; @@ -97,14 +93,14 @@ if (self) { group = aGroup; serverInfo = [info copy]; - flags.failedDownload = 0; - flags.isRetrieving = 0; - flags.needsReset = 1; + flags.failedDownload = NO; + flags.isRetrieving = NO; + flags.needsReset = NO; availableResults = 0; fetchedResults = 0; errorMessage = nil; infoLock = [[BDSKReadWriteLock alloc] init]; - [self startDOServerSync]; + [self start]; } return self; } @@ -119,9 +115,6 @@ [super dealloc]; } -- (Protocol *)protocolForMainThread { return @protocol(BDSKZoomGroupServerMainThread); } -- (Protocol *)protocolForServerThread { return @protocol(BDSKZoomGroupServerLocalThread); } - #pragma mark BDSKSearchGroupServer protocol // these are called on the main thread @@ -131,7 +124,7 @@ - (void)reset { if ([self isRetrieving]) { - [[self serverOnServerThread] terminateConnection]; + [self performSelectorOnLocalThread:@selector(terminateConnection) withObject:nil waitUntilDone:NO]; OSAtomicCompareAndSwap32Barrier(1, 0, &flags.isRetrieving); } OSAtomicCompareAndSwap32Barrier(availableResults, 0, &availableResults); @@ -140,7 +133,7 @@ - (void)terminate { - [self stopDOServer]; + [self stop]; OSAtomicCompareAndSwap32Barrier(1, 0, &flags.isRetrieving); } @@ -149,7 +142,7 @@ OSAtomicCompareAndSwap32Barrier(1, 0, &flags.failedDownload); OSAtomicCompareAndSwap32Barrier(0, 1, &flags.isRetrieving); - [[self serverOnServerThread] downloadWithSearchTerm:aSearchTerm]; + [self performSelectorOnLocalThread:@selector(downloadWithSearchTerm:) withObject:aSearchTerm waitUntilDone:NO]; } - (void)setServerInfo:(BDSKServerInfo *)info; @@ -230,7 +223,7 @@ return stringType; } -- (void)addPublicationsFromResults:(bycopy NSArray *)results; +- (void)addPublicationsFromResults:(NSArray *)results; { BDSKASSERT([NSThread isMainThread]); @@ -292,7 +285,7 @@ OSAtomicCompareAndSwap32Barrier(fetchedResults, 0, &fetchedResults); } -- (oneway void)terminateConnection; +- (void)terminateConnection; { BDSKDESTROY(connection); OSAtomicCompareAndSwap32Barrier(0, 1, &flags.needsReset); @@ -299,7 +292,7 @@ OSAtomicCompareAndSwap32Barrier(1, 0, &flags.isRetrieving); } -- (oneway void)downloadWithSearchTerm:(NSString *)searchTerm; +- (void)downloadWithSearchTerm:(NSString *)searchTerm; { // only reset the connection when we're actually going to use it, since a mixed host/database/port won't work OSMemoryBarrier(); @@ -355,10 +348,12 @@ } - [[self serverOnMainThread] addPublicationsFromResults:results]; + dispatch_sync(dispatch_get_main_queue(), ^{ + [self addPublicationsFromResults:results]; + }); } -- (void)serverDidFinish{ +- (void)didFinish{ [self terminateConnection]; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. _______________________________________________ Bibdesk-commit mailing list Bibdesk-commit@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/bibdesk-commit