| 
					
				 | 
			
			
				@@ -41,6 +41,13 @@ from grpc.framework.foundation import logging_pool 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 from grpc.framework.foundation import relay 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 from grpc.framework.interfaces.links import links 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+_STOP = _intermediary_low.Event.Kind.STOP 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+_WRITE = _intermediary_low.Event.Kind.WRITE_ACCEPTED 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+_COMPLETE = _intermediary_low.Event.Kind.COMPLETE_ACCEPTED 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+_READ = _intermediary_low.Event.Kind.READ_ACCEPTED 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+_METADATA = _intermediary_low.Event.Kind.METADATA_ACCEPTED 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+_FINISH = _intermediary_low.Event.Kind.FINISH 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 @enum.unique 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 class _Read(enum.Enum): 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -67,7 +74,7 @@ class _RPCState(object): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   def __init__( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       self, call, request_serializer, response_deserializer, sequence_number, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      read, allowance, high_write, low_write): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      read, allowance, high_write, low_write, due): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     self.call = call 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     self.request_serializer = request_serializer 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     self.response_deserializer = response_deserializer 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -76,6 +83,13 @@ class _RPCState(object): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     self.allowance = allowance 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     self.high_write = high_write 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     self.low_write = low_write 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    self.due = due 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+def _no_longer_due(kind, rpc_state, key, rpc_states): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  rpc_state.due.remove(kind) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if not rpc_state.due: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    del rpc_states[key] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 class _Kernel(object): 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -91,12 +105,14 @@ class _Kernel(object): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     self._relay = ticket_relay 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     self._completion_queue = None 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    self._rpc_states = None 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    self._rpc_states = {} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     self._pool = None 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   def _on_write_event(self, operation_id, unused_event, rpc_state): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if rpc_state.high_write is _HighWrite.CLOSED: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       rpc_state.call.complete(operation_id) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      rpc_state.due.add(_COMPLETE) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      rpc_state.due.remove(_WRITE) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       rpc_state.low_write = _LowWrite.CLOSED 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       ticket = links.Ticket( 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -105,16 +121,19 @@ class _Kernel(object): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       rpc_state.sequence_number += 1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       self._relay.add_value(ticket) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       rpc_state.low_write = _LowWrite.OPEN 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      _no_longer_due(_WRITE, rpc_state, operation_id, self._rpc_states) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   def _on_read_event(self, operation_id, event, rpc_state): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if event.bytes is None: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if event.bytes is None or _FINISH not in rpc_state.due: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       rpc_state.read = _Read.CLOSED 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      _no_longer_due(_READ, rpc_state, operation_id, self._rpc_states) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if 0 < rpc_state.allowance: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         rpc_state.allowance -= 1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         rpc_state.call.read(operation_id) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         rpc_state.read = _Read.AWAITING_ALLOWANCE 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        _no_longer_due(_READ, rpc_state, operation_id, self._rpc_states) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       ticket = links.Ticket( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           operation_id, rpc_state.sequence_number, None, None, None, None, None, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           None, rpc_state.response_deserializer(event.bytes), None, None, None, 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -123,18 +142,23 @@ class _Kernel(object): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       self._relay.add_value(ticket) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   def _on_metadata_event(self, operation_id, event, rpc_state): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    rpc_state.allowance -= 1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    rpc_state.call.read(operation_id) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    rpc_state.read = _Read.READING 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ticket = links.Ticket( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        operation_id, rpc_state.sequence_number, None, None, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        links.Ticket.Subscription.FULL, None, None, event.metadata, None, None, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        None, None, None, None) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    rpc_state.sequence_number += 1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    self._relay.add_value(ticket) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if _FINISH in rpc_state.due: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      rpc_state.allowance -= 1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      rpc_state.call.read(operation_id) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      rpc_state.read = _Read.READING 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      rpc_state.due.add(_READ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      rpc_state.due.remove(_METADATA) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      ticket = links.Ticket( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          operation_id, rpc_state.sequence_number, None, None, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          links.Ticket.Subscription.FULL, None, None, event.metadata, None, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          None, None, None, None, None) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      rpc_state.sequence_number += 1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      self._relay.add_value(ticket) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      _no_longer_due(_METADATA, rpc_state, operation_id, self._rpc_states) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   def _on_finish_event(self, operation_id, event, rpc_state): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    self._rpc_states.pop(operation_id, None) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    _no_longer_due(_FINISH, rpc_state, operation_id, self._rpc_states) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if event.status.code is _intermediary_low.Code.OK: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       termination = links.Ticket.Termination.COMPLETION 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     elif event.status.code is _intermediary_low.Code.CANCELLED: 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -155,26 +179,26 @@ class _Kernel(object): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   def _spin(self, completion_queue): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     while True: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       event = completion_queue.get(None) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      if event.kind is _intermediary_low.Event.Kind.STOP: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      operation_id = event.tag 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       with self._lock: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if self._completion_queue is None: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          continue 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        rpc_state = self._rpc_states.get(operation_id) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if rpc_state is not None: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          if event.kind is _intermediary_low.Event.Kind.WRITE_ACCEPTED: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            self._on_write_event(operation_id, event, rpc_state) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          elif event.kind is _intermediary_low.Event.Kind.METADATA_ACCEPTED: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            self._on_metadata_event(operation_id, event, rpc_state) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          elif event.kind is _intermediary_low.Event.Kind.READ_ACCEPTED: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            self._on_read_event(operation_id, event, rpc_state) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          elif event.kind is _intermediary_low.Event.Kind.FINISH: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            self._on_finish_event(operation_id, event, rpc_state) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          elif event.kind is _intermediary_low.Event.Kind.COMPLETE_ACCEPTED: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            pass 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            logging.error('Illegal RPC event! %s', (event,)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        rpc_state = self._rpc_states.get(event.tag, None) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if event.kind is _STOP: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          pass 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        elif event.kind is _WRITE: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          self._on_write_event(event.tag, event, rpc_state) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        elif event.kind is _METADATA: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          self._on_metadata_event(event.tag, event, rpc_state) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        elif event.kind is _READ: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          self._on_read_event(event.tag, event, rpc_state) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        elif event.kind is _FINISH: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          self._on_finish_event(event.tag, event, rpc_state) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        elif event.kind is _COMPLETE: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          _no_longer_due(_COMPLETE, rpc_state, event.tag, self._rpc_states) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          logging.error('Illegal RPC event! %s', (event,)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if self._completion_queue is None and not self._rpc_states: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          completion_queue.stop() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   def _invoke( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       self, operation_id, group, method, initial_metadata, payload, termination, 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -221,26 +245,31 @@ class _Kernel(object): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if high_write is _HighWrite.CLOSED: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         call.complete(operation_id) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         low_write = _LowWrite.CLOSED 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        due = set((_METADATA, _COMPLETE, _FINISH,)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         low_write = _LowWrite.OPEN 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        due = set((_METADATA, _FINISH,)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       call.write(request_serializer(payload), operation_id) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       low_write = _LowWrite.ACTIVE 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      due = set((_WRITE, _METADATA, _FINISH,)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     self._rpc_states[operation_id] = _RPCState( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         call, request_serializer, response_deserializer, 0, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         _Read.AWAITING_METADATA, 1 if allowance is None else (1 + allowance), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        high_write, low_write) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        high_write, low_write, due) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   def _advance(self, operation_id, rpc_state, payload, termination, allowance): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if payload is not None: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       rpc_state.call.write(rpc_state.request_serializer(payload), operation_id) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       rpc_state.low_write = _LowWrite.ACTIVE 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      rpc_state.due.add(_WRITE) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if allowance is not None: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if rpc_state.read is _Read.AWAITING_ALLOWANCE: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         rpc_state.allowance += allowance - 1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         rpc_state.call.read(operation_id) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         rpc_state.read = _Read.READING 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        rpc_state.due.add(_READ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         rpc_state.allowance += allowance 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -248,19 +277,21 @@ class _Kernel(object): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       rpc_state.high_write = _HighWrite.CLOSED 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if rpc_state.low_write is _LowWrite.OPEN: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         rpc_state.call.complete(operation_id) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        rpc_state.due.add(_COMPLETE) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         rpc_state.low_write = _LowWrite.CLOSED 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     elif termination is not None: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       rpc_state.call.cancel() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   def add_ticket(self, ticket): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     with self._lock: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      if self._completion_queue is None: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if ticket.sequence_number == 0: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self._invoke( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            ticket.operation_id, ticket.group, ticket.method, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            ticket.initial_metadata, ticket.payload, ticket.termination, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            ticket.timeout, ticket.allowance) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if self._completion_queue is None: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          logging.error('Received invocation ticket %s after stop!', ticket) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          self._invoke( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              ticket.operation_id, ticket.group, ticket.method, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              ticket.initial_metadata, ticket.payload, ticket.termination, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              ticket.timeout, ticket.allowance) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         rpc_state = self._rpc_states.get(ticket.operation_id) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if rpc_state is not None: 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -276,7 +307,6 @@ class _Kernel(object): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     """ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     with self._lock: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       self._completion_queue = _intermediary_low.CompletionQueue() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      self._rpc_states = {} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       self._pool = logging_pool.pool(1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       self._pool.submit(self._spin, self._completion_queue) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -288,11 +318,10 @@ class _Kernel(object): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     has been called. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     """ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     with self._lock: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      self._completion_queue.stop() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if not self._rpc_states: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self._completion_queue.stop() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       self._completion_queue = None 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       pool = self._pool 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      self._pool = None 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      self._rpc_states = None 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     pool.shutdown(wait=True) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 |