Skip to content
Snippets Groups Projects
Commit 8b414f18 authored by Jorge Canizales's avatar Jorge Canizales
Browse files

Clean up ownership of the connection loss handler

parent 07a2a70b
No related branches found
No related tags found
No related merge requests found
......@@ -68,7 +68,7 @@
@property(nonatomic, strong, null_resettable) dispatch_queue_t queue;
/**
* Calls handler the next time the connectivity to this instance's host is lost. If this instance is
* Calls handler every time the connectivity to this instance's host is lost. If this instance is
* released before that happens, the handler won't be called.
* Only one handler is active at a time, so if this method is called again before the previous
* handler has been called, it might never be called at all (or yes, if it has already been queued).
......
......@@ -106,13 +106,16 @@
#pragma mark Connectivity Monitor
// Assumes the third argument is a block that accepts SCNetworkReachabilityFlags, and passes the
// Assumes the third argument is a block that accepts a GRPCReachabilityFlags object, and passes the
// received ones to it.
static void PassFlagsToContextInfoBlock(SCNetworkReachabilityRef target,
SCNetworkReachabilityFlags flags,
void *info) {
#pragma unused (target)
((__bridge void (^)(SCNetworkReachabilityFlags))info)(flags);
// This can be called many times with the same info. The info is retained by SCNetworkReachability
// while this function is being executed.
void (^handler)(GRPCReachabilityFlags *) = (__bridge void (^)(GRPCReachabilityFlags *))info;
handler([[GRPCReachabilityFlags alloc] initWithFlags:flags]);
}
@implementation GRPCConnectivityMonitor {
......@@ -147,29 +150,30 @@ static void PassFlagsToContextInfoBlock(SCNetworkReachabilityRef target,
}
- (void)handleLossWithHandler:(void (^)())handler {
__weak typeof(self) weakSelf = self;
[self startListeningWithHandler:^(GRPCReachabilityFlags *flags) {
if (!flags.isHostReachable) {
[weakSelf stopListening];
handler();
}
}];
}
- (void)startListeningWithHandler:(void (^)(GRPCReachabilityFlags *))handler {
// Copy to ensure the handler block is in the heap (and so can't be deallocated when this method
// returns).
void (^copiedHandler)(GRPCReachabilityFlags *) = [handler copy];
SCNetworkReachabilityContext context = {
.version = 0,
.info = (__bridge_retained void *)^(SCNetworkReachabilityFlags flags){
// Pass the flags as as Objective-C wrapper.
handler([[GRPCReachabilityFlags alloc] initWithFlags:flags]);
},
.release = CFRelease
.info = (__bridge void *)copiedHandler,
.retain = CFRetain,
.release = CFRelease,
};
// The following will retain context.info, and release it when the callback is set to NULL.
SCNetworkReachabilitySetCallback(_reachabilityRef, PassFlagsToContextInfoBlock, &context);
SCNetworkReachabilitySetDispatchQueue(_reachabilityRef, _queue);
}
- (void)stopListening {
// This releases the block on context.info.
SCNetworkReachabilitySetCallback(_reachabilityRef, NULL, NULL);
SCNetworkReachabilitySetDispatchQueue(_reachabilityRef, NULL);
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment