| 
					
				 | 
			
			
				@@ -36,17 +36,17 @@ namespace { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 internal::GrpcLibraryInitializer g_gli_initializer; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 gpr_once g_once_init_callback_alternative = GPR_ONCE_INIT; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-grpc_core::ManualConstructor<grpc_core::Mutex> g_callback_alternative_mu; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+grpc_core::Mutex* g_callback_alternative_mu; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // Implement a ref-counted callback CQ for global use in the alternative 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // implementation so that its threads are only created once. Do this using 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // explicit ref-counts and raw pointers rather than a shared-ptr since that 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // has a non-trivial destructor and thus can't be used for global variables. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 struct CallbackAlternativeCQ { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  int refs = 0;         // GUARDED_BY(g_callback_alternative_mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  CompletionQueue* cq;  // GUARDED_BY(g_callback_alternative_mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  std::vector<grpc_core::Thread>* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      nexting_threads;  // GUARDED_BY(g_callback_alternative_mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int refs ABSL_GUARDED_BY(g_callback_alternative_mu) = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  CompletionQueue* cq ABSL_GUARDED_BY(g_callback_alternative_mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  std::vector<grpc_core::Thread>* nexting_threads 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      ABSL_GUARDED_BY(g_callback_alternative_mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   CompletionQueue* Ref() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     grpc_core::MutexLock lock(&*g_callback_alternative_mu); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -104,7 +104,7 @@ struct CallbackAlternativeCQ { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   void Unref() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    grpc_core::MutexLock lock(&*g_callback_alternative_mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_core::MutexLock lock(g_callback_alternative_mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     refs--; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (refs == 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       cq->Shutdown(); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -191,12 +191,15 @@ bool CompletionQueue::CompletionQueueTLSCache::Flush(void** tag, bool* ok) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 CompletionQueue* CompletionQueue::CallbackAlternativeCQ() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   gpr_once_init(&g_once_init_callback_alternative, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                [] { g_callback_alternative_mu.Init(); }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                [] { g_callback_alternative_mu = new grpc_core::Mutex(); }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return g_callback_alternative_cq.Ref(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void CompletionQueue::ReleaseCallbackAlternativeCQ(CompletionQueue* cq) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void CompletionQueue::ReleaseCallbackAlternativeCQ(CompletionQueue* cq) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ABSL_NO_THREAD_SAFETY_ANALYSIS { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   (void)cq; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // This accesses g_callback_alternative_cq without acquiring the mutex 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // but it's considered safe because it just reads the pointer address. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   GPR_DEBUG_ASSERT(cq == g_callback_alternative_cq.cq); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   g_callback_alternative_cq.Unref(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 |