The C based gRPC (C++, Python, Ruby, Objective-C, PHP, C#)
https://grpc.io/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
137 lines
4.0 KiB
137 lines
4.0 KiB
/* |
|
* |
|
* Copyright 2015 gRPC authors. |
|
* |
|
* Licensed 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. |
|
* |
|
*/ |
|
|
|
#import "GRXImmediateWriter.h" |
|
|
|
#import "NSEnumerator+GRXUtil.h" |
|
|
|
@implementation GRXImmediateWriter { |
|
NSEnumerator *_enumerator; |
|
NSError *_errorOrNil; |
|
id<GRXWriteable> _writeable; |
|
} |
|
|
|
@synthesize state = _state; |
|
|
|
- (instancetype) init { |
|
return [self initWithEnumerator:nil error:nil]; // results in an empty writer. |
|
} |
|
|
|
// Designated initializer |
|
- (instancetype)initWithEnumerator:(NSEnumerator *)enumerator error:(NSError *)errorOrNil { |
|
if (((self = [super init]))) { |
|
_enumerator = enumerator; |
|
_errorOrNil = errorOrNil; |
|
_state = GRXWriterStateNotStarted; |
|
} |
|
return self; |
|
} |
|
|
|
#pragma mark Convenience constructors |
|
|
|
+ (instancetype)writerWithEnumerator:(NSEnumerator *)enumerator error:(NSError *)errorOrNil { |
|
return [[self alloc] initWithEnumerator:enumerator error:errorOrNil]; |
|
} |
|
|
|
+ (GRXWriter *)writerWithEnumerator:(NSEnumerator *)enumerator { |
|
return [self writerWithEnumerator:enumerator error:nil]; |
|
} |
|
|
|
+ (GRXWriter *)writerWithValueSupplier:(id (^)(void))block { |
|
return [self writerWithEnumerator:[NSEnumerator grx_enumeratorWithValueSupplier:block]]; |
|
} |
|
|
|
+ (GRXWriter *)writerWithContainer:(id<NSFastEnumeration>)container { |
|
return [self writerWithEnumerator:[NSEnumerator grx_enumeratorWithContainer:container]];; |
|
} |
|
|
|
+ (GRXWriter *)writerWithValue:(id)value { |
|
return [self writerWithEnumerator:[NSEnumerator grx_enumeratorWithSingleValue:value]]; |
|
} |
|
|
|
+ (GRXWriter *)writerWithError:(NSError *)error { |
|
return [self writerWithEnumerator:nil error:error]; |
|
} |
|
|
|
+ (GRXWriter *)emptyWriter { |
|
return [self writerWithEnumerator:nil error:nil]; |
|
} |
|
|
|
#pragma mark Conformance with GRXWriter |
|
|
|
// Most of the complexity in this implementation is the result of supporting pause and resumption of |
|
// the GRXWriter. It's an important feature for instances of GRXWriter that are backed by a |
|
// container (which may be huge), or by a NSEnumerator (which may even be infinite). |
|
|
|
- (void)writeUntilPausedOrStopped { |
|
id value; |
|
while (value = [_enumerator nextObject]) { |
|
[_writeable writeValue:value]; |
|
// If the writeable has a reference to us, it might change our state to paused or finished. |
|
if (_state == GRXWriterStatePaused || _state == GRXWriterStateFinished) { |
|
return; |
|
} |
|
} |
|
[self finishWithError:_errorOrNil]; |
|
} |
|
|
|
- (void)startWithWriteable:(id<GRXWriteable>)writeable { |
|
_state = GRXWriterStateStarted; |
|
_writeable = writeable; |
|
[self writeUntilPausedOrStopped]; |
|
} |
|
|
|
- (void)finishWithError:(NSError *)errorOrNil { |
|
_state = GRXWriterStateFinished; |
|
_enumerator = nil; |
|
_errorOrNil = nil; |
|
id<GRXWriteable> writeable = _writeable; |
|
_writeable = nil; |
|
[writeable writesFinishedWithError:errorOrNil]; |
|
} |
|
|
|
- (void)setState:(GRXWriterState)newState { |
|
// Manual transitions are only allowed from the started or paused states. |
|
if (_state == GRXWriterStateNotStarted || _state == GRXWriterStateFinished) { |
|
return; |
|
} |
|
|
|
switch (newState) { |
|
case GRXWriterStateFinished: |
|
_state = newState; |
|
_enumerator = nil; |
|
_errorOrNil = nil; |
|
// Per GRXWriter's contract, setting the state to Finished manually |
|
// means one doesn't wish the writeable to be messaged anymore. |
|
_writeable = nil; |
|
return; |
|
case GRXWriterStatePaused: |
|
_state = newState; |
|
return; |
|
case GRXWriterStateStarted: |
|
if (_state == GRXWriterStatePaused) { |
|
_state = newState; |
|
[self writeUntilPausedOrStopped]; |
|
} |
|
return; |
|
case GRXWriterStateNotStarted: |
|
return; |
|
} |
|
} |
|
|
|
@end
|
|
|