1
#include "source/common/grpc/google_grpc_context.h"
2

            
3
#include <atomic>
4

            
5
#include "source/common/common/assert.h"
6
#include "source/common/common/lock_guard.h"
7
#include "source/common/common/macros.h"
8
#include "source/common/common/thread.h"
9

            
10
#ifdef ENVOY_GOOGLE_GRPC
11
#include "grpcpp/grpcpp.h"
12
#endif
13

            
14
namespace Envoy {
15
namespace Grpc {
16

            
17
21954
GoogleGrpcContext::GoogleGrpcContext() : instance_tracker_(instanceTracker()) {
18
21954
#ifdef ENVOY_GOOGLE_GRPC
19
21954
  Thread::LockGuard lock(instance_tracker_.mutex_);
20
21954
  if (++instance_tracker_.live_instances_ == 1) {
21
11106
    grpc_init();
22
11106
  }
23
21954
#endif
24
21954
}
25

            
26
21954
GoogleGrpcContext::~GoogleGrpcContext() {
27
21954
#ifdef ENVOY_GOOGLE_GRPC
28
  // Per https://github.com/grpc/grpc/issues/20303 it is OK to call
29
  // grpc_shutdown_blocking() as long as no one can concurrently call
30
  // grpc_init(). We use check_format.py to ensure that this file contains the
31
  // only callers to grpc_init(), and the mutex to then make that guarantee
32
  // across users of this class.
33
21954
  Thread::LockGuard lock(instance_tracker_.mutex_);
34
21954
  ASSERT(instance_tracker_.live_instances_ > 0);
35
21954
  if (--instance_tracker_.live_instances_ == 0) {
36
11106
    grpc_shutdown_blocking(); // Waiting for quiescence avoids non-determinism in tests.
37
11106
  }
38
21954
#endif
39
21954
}
40

            
41
21954
GoogleGrpcContext::InstanceTracker& GoogleGrpcContext::instanceTracker() {
42
21954
  MUTABLE_CONSTRUCT_ON_FIRST_USE(InstanceTracker);
43
21954
}
44

            
45
} // namespace Grpc
46
} // namespace Envoy