Эх сурвалжийг харах

Merge branch 'master' of https://github.com/grpc/grpc into channel-tracing

ncteisen 7 жил өмнө
parent
commit
94dad67f43
100 өөрчлөгдсөн 1898 нэмэгдсэн , 734 устгасан
  1. 12 21
      BUILD
  2. 52 4
      CMakeLists.txt
  3. 4 5
      Makefile
  4. 4 5
      build.yaml
  5. 3 3
      config.m4
  6. 3 3
      config.w32
  7. 1 0
      doc/g_stands_for.md
  8. 9 0
      examples/android/helloworld/.gitignore
  9. 24 0
      examples/android/helloworld/README.md
  10. 1 0
      examples/android/helloworld/app/.gitignore
  11. 123 0
      examples/android/helloworld/app/CMakeLists.txt
  12. 53 0
      examples/android/helloworld/app/build.gradle
  13. 21 0
      examples/android/helloworld/app/proguard-rules.pro
  14. 22 0
      examples/android/helloworld/app/src/main/AndroidManifest.xml
  15. 142 0
      examples/android/helloworld/app/src/main/cpp/grpc-helloworld.cc
  16. 167 0
      examples/android/helloworld/app/src/main/java/io/grpc/helloworldexample/cpp/HelloworldActivity.java
  17. 86 0
      examples/android/helloworld/app/src/main/res/layout/activity_helloworld.xml
  18. BIN
      examples/android/helloworld/app/src/main/res/mipmap-hdpi/ic_launcher.png
  19. BIN
      examples/android/helloworld/app/src/main/res/mipmap-mdpi/ic_launcher.png
  20. BIN
      examples/android/helloworld/app/src/main/res/mipmap-xhdpi/ic_launcher.png
  21. BIN
      examples/android/helloworld/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
  22. 3 0
      examples/android/helloworld/app/src/main/res/values/strings.xml
  23. 24 0
      examples/android/helloworld/build.gradle
  24. 17 0
      examples/android/helloworld/gradle.properties
  25. BIN
      examples/android/helloworld/gradle/wrapper/gradle-wrapper.jar
  26. 6 0
      examples/android/helloworld/gradle/wrapper/gradle-wrapper.properties
  27. 160 0
      examples/android/helloworld/gradlew
  28. 90 0
      examples/android/helloworld/gradlew.bat
  29. 1 0
      examples/android/helloworld/settings.gradle
  30. 2 2
      gRPC-C++.podspec
  31. 4 5
      gRPC-Core.podspec
  32. 3 4
      grpc.gemspec
  33. 2 3
      grpc.gyp
  34. 3 4
      package.xml
  35. 0 51
      src/core/lib/gpr/thd.cc
  36. 0 72
      src/core/lib/gpr/thd.h
  37. 0 154
      src/core/lib/gpr/thd_posix.cc
  38. 0 107
      src/core/lib/gpr/thd_windows.cc
  39. 135 0
      src/core/lib/gprpp/thd.h
  40. 209 0
      src/core/lib/gprpp/thd_posix.cc
  41. 162 0
      src/core/lib/gprpp/thd_windows.cc
  42. 57 9
      src/core/lib/iomgr/ev_poll_posix.cc
  43. 1 1
      src/core/lib/iomgr/exec_ctx.cc
  44. 11 11
      src/core/lib/iomgr/executor.cc
  45. 2 2
      src/core/lib/iomgr/fork_posix.cc
  46. 1 1
      src/core/lib/iomgr/iocp_windows.cc
  47. 1 1
      src/core/lib/iomgr/iomgr.cc
  48. 1 1
      src/core/lib/iomgr/pollset_windows.cc
  49. 1 1
      src/core/lib/iomgr/resolve_address_posix.cc
  50. 1 1
      src/core/lib/iomgr/resolve_address_windows.cc
  51. 10 19
      src/core/lib/iomgr/timer_manager.cc
  52. 1 1
      src/core/lib/iomgr/wakeup_fd_cv.cc
  53. 6 7
      src/core/lib/profiling/basic_timers.cc
  54. 2 2
      src/core/lib/surface/init.cc
  55. 1 1
      src/core/tsi/alts_transport_security.cc
  56. 2 2
      src/core/tsi/alts_transport_security.h
  57. 1 1
      src/cpp/client/channel_cc.cc
  58. 10 6
      src/cpp/server/dynamic_thread_pool.cc
  59. 2 2
      src/cpp/server/dynamic_thread_pool.h
  60. 10 5
      src/cpp/thread_manager/thread_manager.cc
  61. 5 5
      src/cpp/thread_manager/thread_manager.h
  62. 2 3
      src/python/grpcio/grpc_core_dependencies.py
  63. 26 0
      templates/CMakeLists.txt.template
  64. 5 3
      test/core/bad_client/bad_client.cc
  65. 11 6
      test/core/end2end/bad_server_response_test.cc
  66. 0 1
      test/core/end2end/fixtures/h2_census.cc
  67. 0 1
      test/core/end2end/fixtures/h2_compress.cc
  68. 0 1
      test/core/end2end/fixtures/h2_full+pipe.cc
  69. 0 1
      test/core/end2end/fixtures/h2_full+trace.cc
  70. 0 1
      test/core/end2end/fixtures/h2_full+workarounds.cc
  71. 0 1
      test/core/end2end/fixtures/h2_full.cc
  72. 0 1
      test/core/end2end/fixtures/h2_http_proxy.cc
  73. 0 1
      test/core/end2end/fixtures/h2_load_reporting.cc
  74. 0 1
      test/core/end2end/fixtures/h2_proxy.cc
  75. 0 1
      test/core/end2end/fixtures/h2_sockpair+trace.cc
  76. 0 1
      test/core/end2end/fixtures/h2_sockpair.cc
  77. 0 1
      test/core/end2end/fixtures/h2_sockpair_1byte.cc
  78. 0 1
      test/core/end2end/fixtures/h2_uds.cc
  79. 5 7
      test/core/end2end/fixtures/http_proxy_fixture.cc
  80. 0 1
      test/core/end2end/fixtures/inproc.cc
  81. 5 7
      test/core/end2end/fixtures/proxy.cc
  82. 0 1
      test/core/end2end/tests/bad_ping.cc
  83. 4 7
      test/core/end2end/tests/connectivity.cc
  84. 0 1
      test/core/end2end/tests/ping.cc
  85. 0 10
      test/core/gpr/BUILD
  86. 10 10
      test/core/gpr/arena_test.cc
  87. 18 8
      test/core/gpr/cpu_test.cc
  88. 16 22
      test/core/gpr/mpscq_test.cc
  89. 11 11
      test/core/gpr/spinlock_test.cc
  90. 37 24
      test/core/gpr/sync_test.cc
  91. 0 1
      test/core/gpr/time_test.cc
  92. 12 13
      test/core/gpr/tls_test.cc
  93. 19 10
      test/core/gprpp/BUILD
  94. 0 1
      test/core/gprpp/manual_constructor_test.cc
  95. 31 36
      test/core/gprpp/thd_test.cc
  96. 6 7
      test/core/handshake/client_ssl.cc
  97. 0 1
      test/core/handshake/readahead_handshaker_server_ssl.cc
  98. 0 1
      test/core/handshake/server_ssl.cc
  99. 6 7
      test/core/handshake/server_ssl_common.cc
  100. 0 1
      test/core/handshake/server_ssl_common.h

+ 12 - 21
BUILD

@@ -527,9 +527,6 @@ grpc_cc_library(
         "src/core/lib/gpr/sync.cc",
         "src/core/lib/gpr/sync.cc",
         "src/core/lib/gpr/sync_posix.cc",
         "src/core/lib/gpr/sync_posix.cc",
         "src/core/lib/gpr/sync_windows.cc",
         "src/core/lib/gpr/sync_windows.cc",
-        "src/core/lib/gpr/thd.cc",
-        "src/core/lib/gpr/thd_posix.cc",
-        "src/core/lib/gpr/thd_windows.cc",
         "src/core/lib/gpr/time.cc",
         "src/core/lib/gpr/time.cc",
         "src/core/lib/gpr/time_posix.cc",
         "src/core/lib/gpr/time_posix.cc",
         "src/core/lib/gpr/time_precise.cc",
         "src/core/lib/gpr/time_precise.cc",
@@ -539,6 +536,8 @@ grpc_cc_library(
         "src/core/lib/gpr/tmpfile_posix.cc",
         "src/core/lib/gpr/tmpfile_posix.cc",
         "src/core/lib/gpr/tmpfile_windows.cc",
         "src/core/lib/gpr/tmpfile_windows.cc",
         "src/core/lib/gpr/wrap_memcpy.cc",
         "src/core/lib/gpr/wrap_memcpy.cc",
+        "src/core/lib/gprpp/thd_posix.cc",
+        "src/core/lib/gprpp/thd_windows.cc",
         "src/core/lib/profiling/basic_timers.cc",
         "src/core/lib/profiling/basic_timers.cc",
         "src/core/lib/profiling/stap_timers.cc",
         "src/core/lib/profiling/stap_timers.cc",
     ],
     ],
@@ -552,7 +551,6 @@ grpc_cc_library(
         "src/core/lib/gpr/spinlock.h",
         "src/core/lib/gpr/spinlock.h",
         "src/core/lib/gpr/string.h",
         "src/core/lib/gpr/string.h",
         "src/core/lib/gpr/string_windows.h",
         "src/core/lib/gpr/string_windows.h",
-        "src/core/lib/gpr/thd.h",
         "src/core/lib/gpr/time_precise.h",
         "src/core/lib/gpr/time_precise.h",
         "src/core/lib/gpr/tls.h",
         "src/core/lib/gpr/tls.h",
         "src/core/lib/gpr/tls_gcc.h",
         "src/core/lib/gpr/tls_gcc.h",
@@ -560,6 +558,10 @@ grpc_cc_library(
         "src/core/lib/gpr/tls_pthread.h",
         "src/core/lib/gpr/tls_pthread.h",
         "src/core/lib/gpr/tmpfile.h",
         "src/core/lib/gpr/tmpfile.h",
         "src/core/lib/gpr/useful.h",
         "src/core/lib/gpr/useful.h",
+        "src/core/lib/gprpp/abstract.h",
+        "src/core/lib/gprpp/manual_constructor.h",
+        "src/core/lib/gprpp/memory.h",
+        "src/core/lib/gprpp/thd.h",
         "src/core/lib/profiling/timers.h",
         "src/core/lib/profiling/timers.h",
     ],
     ],
     language = "c++",
     language = "c++",
@@ -601,16 +603,6 @@ grpc_cc_library(
     ],
     ],
 )
 )
 
 
-grpc_cc_library(
-    name = "gpr++_base",
-    language = "c++",
-    public_hdrs = [
-        "src/core/lib/gprpp/abstract.h",
-        "src/core/lib/gprpp/manual_constructor.h",
-        "src/core/lib/gprpp/memory.h",
-    ],
-)
-
 grpc_cc_library(
 grpc_cc_library(
     name = "atomic",
     name = "atomic",
     hdrs = [
     hdrs = [
@@ -633,7 +625,7 @@ grpc_cc_library(
         "src/core/lib/gprpp/inlined_vector.h",
         "src/core/lib/gprpp/inlined_vector.h",
     ],
     ],
     deps = [
     deps = [
-        "gpr++_base",
+        "gpr_base",
     ],
     ],
 )
 )
 
 
@@ -649,7 +641,7 @@ grpc_cc_library(
     public_hdrs = ["src/core/lib/gprpp/orphanable.h"],
     public_hdrs = ["src/core/lib/gprpp/orphanable.h"],
     deps = [
     deps = [
         "debug_location",
         "debug_location",
-        "gpr++_base",
+        "gpr_base",
         "grpc_trace",
         "grpc_trace",
         "ref_counted_ptr",
         "ref_counted_ptr",
     ],
     ],
@@ -661,7 +653,7 @@ grpc_cc_library(
     public_hdrs = ["src/core/lib/gprpp/ref_counted.h"],
     public_hdrs = ["src/core/lib/gprpp/ref_counted.h"],
     deps = [
     deps = [
         "debug_location",
         "debug_location",
-        "gpr++_base",
+        "gpr_base",
         "grpc_trace",
         "grpc_trace",
         "ref_counted_ptr",
         "ref_counted_ptr",
     ],
     ],
@@ -672,7 +664,7 @@ grpc_cc_library(
     language = "c++",
     language = "c++",
     public_hdrs = ["src/core/lib/gprpp/ref_counted_ptr.h"],
     public_hdrs = ["src/core/lib/gprpp/ref_counted_ptr.h"],
     deps = [
     deps = [
-        "gpr++_base",
+        "gpr_base",
     ],
     ],
 )
 )
 
 
@@ -947,13 +939,12 @@ grpc_cc_library(
     language = "c++",
     language = "c++",
     public_hdrs = GRPC_PUBLIC_HDRS,
     public_hdrs = GRPC_PUBLIC_HDRS,
     deps = [
     deps = [
-        "gpr++_base",
         "gpr_base",
         "gpr_base",
         "grpc_codegen",
         "grpc_codegen",
         "grpc_trace",
         "grpc_trace",
+        "inlined_vector",
         "ref_counted",
         "ref_counted",
         "ref_counted_ptr",
         "ref_counted_ptr",
-        "inlined_vector",
     ],
     ],
 )
 )
 
 
@@ -1429,7 +1420,7 @@ grpc_cc_library(
     ],
     ],
     language = "c++",
     language = "c++",
     deps = [
     deps = [
-        "gpr++_base",
+        "gpr_base",
         "grpc_base",
         "grpc_base",
         "grpc_http_filters",
         "grpc_http_filters",
         "grpc_transport_chttp2_alpn",
         "grpc_transport_chttp2_alpn",

+ 52 - 4
CMakeLists.txt

@@ -37,6 +37,7 @@ set(gRPC_INSTALL_CMAKEDIR "lib/cmake/${PACKAGE_NAME}" CACHE STRING "Installation
 
 
 # Options
 # Options
 option(gRPC_BUILD_TESTS "Build tests" OFF)
 option(gRPC_BUILD_TESTS "Build tests" OFF)
+option(gRPC_BUILD_CODEGEN "Build codegen" ON)
 
 
 set(gRPC_INSTALL_default ON)
 set(gRPC_INSTALL_default ON)
 if (NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
 if (NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
@@ -78,6 +79,8 @@ if(UNIX)
     set(_gRPC_PLATFORM_LINUX ON)
     set(_gRPC_PLATFORM_LINUX ON)
   elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
   elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
     set(_gRPC_PLATFORM_MAC ON)
     set(_gRPC_PLATFORM_MAC ON)
+  elseif(${CMAKE_SYSTEM_NAME} MATCHES "Android")
+    set(_gRPC_PLATFORM_ANDROID ON)
   else()
   else()
     set(_gRPC_PLATFORM_POSIX ON)
     set(_gRPC_PLATFORM_POSIX ON)
   endif()
   endif()
@@ -120,6 +123,8 @@ endif()
 
 
 if(_gRPC_PLATFORM_MAC)
 if(_gRPC_PLATFORM_MAC)
   set(_gRPC_ALLTARGETS_LIBRARIES ${CMAKE_DL_LIBS} m pthread)
   set(_gRPC_ALLTARGETS_LIBRARIES ${CMAKE_DL_LIBS} m pthread)
+elseif(_gRPC_PLATFORM_ANDROID)
+  set(_gRPC_ALLTARGETS_LIBRARIES ${CMAKE_DL_LIBS} m)
 elseif(UNIX)
 elseif(UNIX)
   set(_gRPC_ALLTARGETS_LIBRARIES ${CMAKE_DL_LIBS} rt m pthread)
   set(_gRPC_ALLTARGETS_LIBRARIES ${CMAKE_DL_LIBS} rt m pthread)
 endif()
 endif()
@@ -655,9 +660,6 @@ add_library(gpr
   src/core/lib/gpr/sync.cc
   src/core/lib/gpr/sync.cc
   src/core/lib/gpr/sync_posix.cc
   src/core/lib/gpr/sync_posix.cc
   src/core/lib/gpr/sync_windows.cc
   src/core/lib/gpr/sync_windows.cc
-  src/core/lib/gpr/thd.cc
-  src/core/lib/gpr/thd_posix.cc
-  src/core/lib/gpr/thd_windows.cc
   src/core/lib/gpr/time.cc
   src/core/lib/gpr/time.cc
   src/core/lib/gpr/time_posix.cc
   src/core/lib/gpr/time_posix.cc
   src/core/lib/gpr/time_precise.cc
   src/core/lib/gpr/time_precise.cc
@@ -667,6 +669,8 @@ add_library(gpr
   src/core/lib/gpr/tmpfile_posix.cc
   src/core/lib/gpr/tmpfile_posix.cc
   src/core/lib/gpr/tmpfile_windows.cc
   src/core/lib/gpr/tmpfile_windows.cc
   src/core/lib/gpr/wrap_memcpy.cc
   src/core/lib/gpr/wrap_memcpy.cc
+  src/core/lib/gprpp/thd_posix.cc
+  src/core/lib/gprpp/thd_windows.cc
   src/core/lib/profiling/basic_timers.cc
   src/core/lib/profiling/basic_timers.cc
   src/core/lib/profiling/stap_timers.cc
   src/core/lib/profiling/stap_timers.cc
 )
 )
@@ -697,6 +701,12 @@ target_include_directories(gpr
 target_link_libraries(gpr
 target_link_libraries(gpr
   ${_gRPC_ALLTARGETS_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
 )
 )
+if (_gRPC_PLATFORM_ANDROID)
+  target_link_libraries(gpr
+    android
+    log
+  )
+endif (_gRPC_PLATFORM_ANDROID)
 
 
 foreach(_hdr
 foreach(_hdr
   include/grpc/support/alloc.h
   include/grpc/support/alloc.h
@@ -2713,6 +2723,7 @@ endif()
 
 
 if (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
 
+if (gRPC_BUILD_CODEGEN)
 add_library(grpc++_core_stats
 add_library(grpc++_core_stats
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/core/stats.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/core/stats.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/core/stats.grpc.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/core/stats.grpc.pb.cc
@@ -2758,6 +2769,7 @@ target_link_libraries(grpc++_core_stats
   grpc++
   grpc++
 )
 )
 
 
+endif (gRPC_BUILD_CODEGEN)
 
 
 endif (gRPC_BUILD_TESTS)
 endif (gRPC_BUILD_TESTS)
 
 
@@ -3254,6 +3266,7 @@ if (gRPC_INSTALL)
 endif()
 endif()
 
 
 
 
+if (gRPC_BUILD_CODEGEN)
 add_library(grpc++_error_details
 add_library(grpc++_error_details
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/status/status.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/status/status.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/status/status.grpc.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/status/status.grpc.pb.cc
@@ -3306,6 +3319,7 @@ foreach(_hdr
     DESTINATION "${gRPC_INSTALL_INCLUDEDIR}/${_path}"
     DESTINATION "${gRPC_INSTALL_INCLUDEDIR}/${_path}"
   )
   )
 endforeach()
 endforeach()
+endif (gRPC_BUILD_CODEGEN)
 
 
 
 
 if (gRPC_INSTALL)
 if (gRPC_INSTALL)
@@ -3318,6 +3332,7 @@ endif()
 
 
 if (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
 
+if (gRPC_BUILD_CODEGEN)
 add_library(grpc++_proto_reflection_desc_db
 add_library(grpc++_proto_reflection_desc_db
   test/cpp/util/proto_reflection_descriptor_database.cc
   test/cpp/util/proto_reflection_descriptor_database.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.pb.cc
@@ -3374,9 +3389,11 @@ foreach(_hdr
     DESTINATION "${gRPC_INSTALL_INCLUDEDIR}/${_path}"
     DESTINATION "${gRPC_INSTALL_INCLUDEDIR}/${_path}"
   )
   )
 endforeach()
 endforeach()
+endif (gRPC_BUILD_CODEGEN)
 
 
 endif (gRPC_BUILD_TESTS)
 endif (gRPC_BUILD_TESTS)
 
 
+if (gRPC_BUILD_CODEGEN)
 add_library(grpc++_reflection
 add_library(grpc++_reflection
   src/cpp/ext/proto_server_reflection.cc
   src/cpp/ext/proto_server_reflection.cc
   src/cpp/ext/proto_server_reflection_plugin.cc
   src/cpp/ext/proto_server_reflection_plugin.cc
@@ -3430,6 +3447,7 @@ foreach(_hdr
     DESTINATION "${gRPC_INSTALL_INCLUDEDIR}/${_path}"
     DESTINATION "${gRPC_INSTALL_INCLUDEDIR}/${_path}"
   )
   )
 endforeach()
 endforeach()
+endif (gRPC_BUILD_CODEGEN)
 
 
 
 
 if (gRPC_INSTALL)
 if (gRPC_INSTALL)
@@ -3483,6 +3501,7 @@ target_link_libraries(grpc++_test_config
 endif (gRPC_BUILD_TESTS)
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
 
+if (gRPC_BUILD_CODEGEN)
 add_library(grpc++_test_util
 add_library(grpc++_test_util
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.grpc.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.grpc.pb.cc
@@ -3651,10 +3670,12 @@ foreach(_hdr
     DESTINATION "${gRPC_INSTALL_INCLUDEDIR}/${_path}"
     DESTINATION "${gRPC_INSTALL_INCLUDEDIR}/${_path}"
   )
   )
 endforeach()
 endforeach()
+endif (gRPC_BUILD_CODEGEN)
 
 
 endif (gRPC_BUILD_TESTS)
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
 
+if (gRPC_BUILD_CODEGEN)
 add_library(grpc++_test_util_unsecure
 add_library(grpc++_test_util_unsecure
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.grpc.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.grpc.pb.cc
@@ -3821,6 +3842,7 @@ foreach(_hdr
     DESTINATION "${gRPC_INSTALL_INCLUDEDIR}/${_path}"
     DESTINATION "${gRPC_INSTALL_INCLUDEDIR}/${_path}"
   )
   )
 endforeach()
 endforeach()
+endif (gRPC_BUILD_CODEGEN)
 
 
 endif (gRPC_BUILD_TESTS)
 endif (gRPC_BUILD_TESTS)
 
 
@@ -4163,6 +4185,7 @@ target_link_libraries(grpc_benchmark
 endif (gRPC_BUILD_TESTS)
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
 
+if (gRPC_BUILD_CODEGEN)
 add_library(grpc_cli_libs
 add_library(grpc_cli_libs
   test/cpp/util/cli_call.cc
   test/cpp/util/cli_call.cc
   test/cpp/util/cli_credentials.cc
   test/cpp/util/cli_credentials.cc
@@ -4224,6 +4247,7 @@ foreach(_hdr
     DESTINATION "${gRPC_INSTALL_INCLUDEDIR}/${_path}"
     DESTINATION "${gRPC_INSTALL_INCLUDEDIR}/${_path}"
   )
   )
 endforeach()
 endforeach()
+endif (gRPC_BUILD_CODEGEN)
 
 
 endif (gRPC_BUILD_TESTS)
 endif (gRPC_BUILD_TESTS)
 
 
@@ -4289,6 +4313,7 @@ endif()
 
 
 if (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
 
+if (gRPC_BUILD_CODEGEN)
 add_library(http2_client_main
 add_library(http2_client_main
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.cc
@@ -4352,10 +4377,12 @@ target_link_libraries(http2_client_main
   grpc++_test_config
   grpc++_test_config
 )
 )
 
 
+endif (gRPC_BUILD_CODEGEN)
 
 
 endif (gRPC_BUILD_TESTS)
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
 
+if (gRPC_BUILD_CODEGEN)
 add_library(interop_client_helper
 add_library(interop_client_helper
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.cc
@@ -4405,10 +4432,12 @@ target_link_libraries(interop_client_helper
   gpr
   gpr
 )
 )
 
 
+endif (gRPC_BUILD_CODEGEN)
 
 
 endif (gRPC_BUILD_TESTS)
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
 
+if (gRPC_BUILD_CODEGEN)
 add_library(interop_client_main
 add_library(interop_client_main
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.cc
@@ -4476,6 +4505,7 @@ target_link_libraries(interop_client_main
   grpc++_test_config
   grpc++_test_config
 )
 )
 
 
+endif (gRPC_BUILD_CODEGEN)
 
 
 endif (gRPC_BUILD_TESTS)
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
@@ -4526,6 +4556,7 @@ target_link_libraries(interop_server_helper
 endif (gRPC_BUILD_TESTS)
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
 
+if (gRPC_BUILD_CODEGEN)
 add_library(interop_server_lib
 add_library(interop_server_lib
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.cc
@@ -4592,6 +4623,7 @@ target_link_libraries(interop_server_lib
   grpc++_test_config
   grpc++_test_config
 )
 )
 
 
+endif (gRPC_BUILD_CODEGEN)
 
 
 endif (gRPC_BUILD_TESTS)
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
@@ -4638,6 +4670,7 @@ target_link_libraries(interop_server_main
 endif (gRPC_BUILD_TESTS)
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
 
+if (gRPC_BUILD_CODEGEN)
 add_library(qps
 add_library(qps
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.cc
@@ -4724,6 +4757,7 @@ target_link_libraries(qps
   grpc
   grpc
 )
 )
 
 
+endif (gRPC_BUILD_CODEGEN)
 
 
 endif (gRPC_BUILD_TESTS)
 endif (gRPC_BUILD_TESTS)
 
 
@@ -6264,7 +6298,7 @@ endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
 
 add_executable(gpr_thd_test
 add_executable(gpr_thd_test
-  test/core/gpr/thd_test.cc
+  test/core/gprpp/thd_test.cc
 )
 )
 
 
 
 
@@ -10307,6 +10341,7 @@ target_link_libraries(grpc_cli
 )
 )
 
 
 endif (gRPC_BUILD_TESTS)
 endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_CODEGEN)
 
 
 add_executable(grpc_cpp_plugin
 add_executable(grpc_cpp_plugin
   src/compiler/cpp_plugin.cc
   src/compiler/cpp_plugin.cc
@@ -10341,6 +10376,8 @@ if (gRPC_INSTALL)
   )
   )
 endif()
 endif()
 
 
+endif (gRPC_BUILD_CODEGEN)
+if (gRPC_BUILD_CODEGEN)
 
 
 add_executable(grpc_csharp_plugin
 add_executable(grpc_csharp_plugin
   src/compiler/csharp_plugin.cc
   src/compiler/csharp_plugin.cc
@@ -10375,6 +10412,8 @@ if (gRPC_INSTALL)
   )
   )
 endif()
 endif()
 
 
+endif (gRPC_BUILD_CODEGEN)
+if (gRPC_BUILD_CODEGEN)
 
 
 add_executable(grpc_node_plugin
 add_executable(grpc_node_plugin
   src/compiler/node_plugin.cc
   src/compiler/node_plugin.cc
@@ -10409,6 +10448,8 @@ if (gRPC_INSTALL)
   )
   )
 endif()
 endif()
 
 
+endif (gRPC_BUILD_CODEGEN)
+if (gRPC_BUILD_CODEGEN)
 
 
 add_executable(grpc_objective_c_plugin
 add_executable(grpc_objective_c_plugin
   src/compiler/objective_c_plugin.cc
   src/compiler/objective_c_plugin.cc
@@ -10443,6 +10484,8 @@ if (gRPC_INSTALL)
   )
   )
 endif()
 endif()
 
 
+endif (gRPC_BUILD_CODEGEN)
+if (gRPC_BUILD_CODEGEN)
 
 
 add_executable(grpc_php_plugin
 add_executable(grpc_php_plugin
   src/compiler/php_plugin.cc
   src/compiler/php_plugin.cc
@@ -10477,6 +10520,8 @@ if (gRPC_INSTALL)
   )
   )
 endif()
 endif()
 
 
+endif (gRPC_BUILD_CODEGEN)
+if (gRPC_BUILD_CODEGEN)
 
 
 add_executable(grpc_python_plugin
 add_executable(grpc_python_plugin
   src/compiler/python_plugin.cc
   src/compiler/python_plugin.cc
@@ -10511,6 +10556,8 @@ if (gRPC_INSTALL)
   )
   )
 endif()
 endif()
 
 
+endif (gRPC_BUILD_CODEGEN)
+if (gRPC_BUILD_CODEGEN)
 
 
 add_executable(grpc_ruby_plugin
 add_executable(grpc_ruby_plugin
   src/compiler/ruby_plugin.cc
   src/compiler/ruby_plugin.cc
@@ -10545,6 +10592,7 @@ if (gRPC_INSTALL)
   )
   )
 endif()
 endif()
 
 
+endif (gRPC_BUILD_CODEGEN)
 if (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
 
 add_executable(grpc_tool_test
 add_executable(grpc_tool_test

+ 4 - 5
Makefile

@@ -2924,9 +2924,6 @@ LIBGPR_SRC = \
     src/core/lib/gpr/sync.cc \
     src/core/lib/gpr/sync.cc \
     src/core/lib/gpr/sync_posix.cc \
     src/core/lib/gpr/sync_posix.cc \
     src/core/lib/gpr/sync_windows.cc \
     src/core/lib/gpr/sync_windows.cc \
-    src/core/lib/gpr/thd.cc \
-    src/core/lib/gpr/thd_posix.cc \
-    src/core/lib/gpr/thd_windows.cc \
     src/core/lib/gpr/time.cc \
     src/core/lib/gpr/time.cc \
     src/core/lib/gpr/time_posix.cc \
     src/core/lib/gpr/time_posix.cc \
     src/core/lib/gpr/time_precise.cc \
     src/core/lib/gpr/time_precise.cc \
@@ -2936,6 +2933,8 @@ LIBGPR_SRC = \
     src/core/lib/gpr/tmpfile_posix.cc \
     src/core/lib/gpr/tmpfile_posix.cc \
     src/core/lib/gpr/tmpfile_windows.cc \
     src/core/lib/gpr/tmpfile_windows.cc \
     src/core/lib/gpr/wrap_memcpy.cc \
     src/core/lib/gpr/wrap_memcpy.cc \
+    src/core/lib/gprpp/thd_posix.cc \
+    src/core/lib/gprpp/thd_windows.cc \
     src/core/lib/profiling/basic_timers.cc \
     src/core/lib/profiling/basic_timers.cc \
     src/core/lib/profiling/stap_timers.cc \
     src/core/lib/profiling/stap_timers.cc \
 
 
@@ -11096,7 +11095,7 @@ endif
 
 
 
 
 GPR_THD_TEST_SRC = \
 GPR_THD_TEST_SRC = \
-    test/core/gpr/thd_test.cc \
+    test/core/gprpp/thd_test.cc \
 
 
 GPR_THD_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_THD_TEST_SRC))))
 GPR_THD_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_THD_TEST_SRC))))
 ifeq ($(NO_SECURE),true)
 ifeq ($(NO_SECURE),true)
@@ -11116,7 +11115,7 @@ $(BINDIR)/$(CONFIG)/gpr_thd_test: $(GPR_THD_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgp
 
 
 endif
 endif
 
 
-$(OBJDIR)/$(CONFIG)/test/core/gpr/thd_test.o:  $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(OBJDIR)/$(CONFIG)/test/core/gprpp/thd_test.o:  $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
 
 
 deps_gpr_thd_test: $(GPR_THD_TEST_OBJS:.o=.dep)
 deps_gpr_thd_test: $(GPR_THD_TEST_OBJS:.o=.dep)
 
 

+ 4 - 5
build.yaml

@@ -59,9 +59,6 @@ filegroups:
   - src/core/lib/gpr/sync.cc
   - src/core/lib/gpr/sync.cc
   - src/core/lib/gpr/sync_posix.cc
   - src/core/lib/gpr/sync_posix.cc
   - src/core/lib/gpr/sync_windows.cc
   - src/core/lib/gpr/sync_windows.cc
-  - src/core/lib/gpr/thd.cc
-  - src/core/lib/gpr/thd_posix.cc
-  - src/core/lib/gpr/thd_windows.cc
   - src/core/lib/gpr/time.cc
   - src/core/lib/gpr/time.cc
   - src/core/lib/gpr/time_posix.cc
   - src/core/lib/gpr/time_posix.cc
   - src/core/lib/gpr/time_precise.cc
   - src/core/lib/gpr/time_precise.cc
@@ -71,6 +68,8 @@ filegroups:
   - src/core/lib/gpr/tmpfile_posix.cc
   - src/core/lib/gpr/tmpfile_posix.cc
   - src/core/lib/gpr/tmpfile_windows.cc
   - src/core/lib/gpr/tmpfile_windows.cc
   - src/core/lib/gpr/wrap_memcpy.cc
   - src/core/lib/gpr/wrap_memcpy.cc
+  - src/core/lib/gprpp/thd_posix.cc
+  - src/core/lib/gprpp/thd_windows.cc
   - src/core/lib/profiling/basic_timers.cc
   - src/core/lib/profiling/basic_timers.cc
   - src/core/lib/profiling/stap_timers.cc
   - src/core/lib/profiling/stap_timers.cc
   uses:
   uses:
@@ -104,7 +103,6 @@ filegroups:
   - src/core/lib/gpr/spinlock.h
   - src/core/lib/gpr/spinlock.h
   - src/core/lib/gpr/string.h
   - src/core/lib/gpr/string.h
   - src/core/lib/gpr/string_windows.h
   - src/core/lib/gpr/string_windows.h
-  - src/core/lib/gpr/thd.h
   - src/core/lib/gpr/time_precise.h
   - src/core/lib/gpr/time_precise.h
   - src/core/lib/gpr/tls.h
   - src/core/lib/gpr/tls.h
   - src/core/lib/gpr/tls_gcc.h
   - src/core/lib/gpr/tls_gcc.h
@@ -118,6 +116,7 @@ filegroups:
   - src/core/lib/gprpp/atomic_with_std.h
   - src/core/lib/gprpp/atomic_with_std.h
   - src/core/lib/gprpp/manual_constructor.h
   - src/core/lib/gprpp/manual_constructor.h
   - src/core/lib/gprpp/memory.h
   - src/core/lib/gprpp/memory.h
+  - src/core/lib/gprpp/thd.h
   - src/core/lib/profiling/timers.h
   - src/core/lib/profiling/timers.h
   uses:
   uses:
   - gpr_codegen
   - gpr_codegen
@@ -2336,7 +2335,7 @@ targets:
   build: test
   build: test
   language: c
   language: c
   src:
   src:
-  - test/core/gpr/thd_test.cc
+  - test/core/gprpp/thd_test.cc
   deps:
   deps:
   - gpr_test_util
   - gpr_test_util
   - gpr
   - gpr

+ 3 - 3
config.m4

@@ -65,9 +65,6 @@ if test "$PHP_GRPC" != "no"; then
     src/core/lib/gpr/sync.cc \
     src/core/lib/gpr/sync.cc \
     src/core/lib/gpr/sync_posix.cc \
     src/core/lib/gpr/sync_posix.cc \
     src/core/lib/gpr/sync_windows.cc \
     src/core/lib/gpr/sync_windows.cc \
-    src/core/lib/gpr/thd.cc \
-    src/core/lib/gpr/thd_posix.cc \
-    src/core/lib/gpr/thd_windows.cc \
     src/core/lib/gpr/time.cc \
     src/core/lib/gpr/time.cc \
     src/core/lib/gpr/time_posix.cc \
     src/core/lib/gpr/time_posix.cc \
     src/core/lib/gpr/time_precise.cc \
     src/core/lib/gpr/time_precise.cc \
@@ -77,6 +74,8 @@ if test "$PHP_GRPC" != "no"; then
     src/core/lib/gpr/tmpfile_posix.cc \
     src/core/lib/gpr/tmpfile_posix.cc \
     src/core/lib/gpr/tmpfile_windows.cc \
     src/core/lib/gpr/tmpfile_windows.cc \
     src/core/lib/gpr/wrap_memcpy.cc \
     src/core/lib/gpr/wrap_memcpy.cc \
+    src/core/lib/gprpp/thd_posix.cc \
+    src/core/lib/gprpp/thd_windows.cc \
     src/core/lib/profiling/basic_timers.cc \
     src/core/lib/profiling/basic_timers.cc \
     src/core/lib/profiling/stap_timers.cc \
     src/core/lib/profiling/stap_timers.cc \
     src/core/lib/surface/init.cc \
     src/core/lib/surface/init.cc \
@@ -631,6 +630,7 @@ if test "$PHP_GRPC" != "no"; then
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/compression)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/compression)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/debug)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/debug)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/gpr)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/gpr)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/gprpp)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/http)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/http)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/iomgr)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/iomgr)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/json)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/json)

+ 3 - 3
config.w32

@@ -42,9 +42,6 @@ if (PHP_GRPC != "no") {
     "src\\core\\lib\\gpr\\sync.cc " +
     "src\\core\\lib\\gpr\\sync.cc " +
     "src\\core\\lib\\gpr\\sync_posix.cc " +
     "src\\core\\lib\\gpr\\sync_posix.cc " +
     "src\\core\\lib\\gpr\\sync_windows.cc " +
     "src\\core\\lib\\gpr\\sync_windows.cc " +
-    "src\\core\\lib\\gpr\\thd.cc " +
-    "src\\core\\lib\\gpr\\thd_posix.cc " +
-    "src\\core\\lib\\gpr\\thd_windows.cc " +
     "src\\core\\lib\\gpr\\time.cc " +
     "src\\core\\lib\\gpr\\time.cc " +
     "src\\core\\lib\\gpr\\time_posix.cc " +
     "src\\core\\lib\\gpr\\time_posix.cc " +
     "src\\core\\lib\\gpr\\time_precise.cc " +
     "src\\core\\lib\\gpr\\time_precise.cc " +
@@ -54,6 +51,8 @@ if (PHP_GRPC != "no") {
     "src\\core\\lib\\gpr\\tmpfile_posix.cc " +
     "src\\core\\lib\\gpr\\tmpfile_posix.cc " +
     "src\\core\\lib\\gpr\\tmpfile_windows.cc " +
     "src\\core\\lib\\gpr\\tmpfile_windows.cc " +
     "src\\core\\lib\\gpr\\wrap_memcpy.cc " +
     "src\\core\\lib\\gpr\\wrap_memcpy.cc " +
+    "src\\core\\lib\\gprpp\\thd_posix.cc " +
+    "src\\core\\lib\\gprpp\\thd_windows.cc " +
     "src\\core\\lib\\profiling\\basic_timers.cc " +
     "src\\core\\lib\\profiling\\basic_timers.cc " +
     "src\\core\\lib\\profiling\\stap_timers.cc " +
     "src\\core\\lib\\profiling\\stap_timers.cc " +
     "src\\core\\lib\\surface\\init.cc " +
     "src\\core\\lib\\surface\\init.cc " +
@@ -643,6 +642,7 @@ if (PHP_GRPC != "no") {
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\compression");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\compression");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\debug");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\debug");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\gpr");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\gpr");
+  FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\gprpp");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\http");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\http");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\iomgr");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\iomgr");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\json");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\json");

+ 1 - 0
doc/g_stands_for.md

@@ -14,3 +14,4 @@ future), and the corresponding version numbers that used them:
 - 1.8 'g' stands for 'generous'
 - 1.8 'g' stands for 'generous'
 - 1.9 'g' stands for 'glossy'
 - 1.9 'g' stands for 'glossy'
 - 1.10 'g' stands for 'glamorous'
 - 1.10 'g' stands for 'glamorous'
+- 1.11 'g' stands for 'gorgeous'

+ 9 - 0
examples/android/helloworld/.gitignore

@@ -0,0 +1,9 @@
+*.iml
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
+.externalNativeBuild

+ 24 - 0
examples/android/helloworld/README.md

@@ -0,0 +1,24 @@
+gRPC on Android
+==============
+
+Note: Building the protobuf dependency for Android requires
+https://github.com/google/protobuf/pull/3878. This fix will be in the next
+protobuf release, but until then must be manually patched in to
+`third_party/protobuf` to build gRPC for Android.
+
+PREREQUISITES
+-------------
+
+- Android SDK
+- Android NDK
+- `protoc` and `grpc_cpp_plugin` binaries on the host system
+
+INSTALL
+-------
+
+The example application can be built via Android Studio or on the command line
+using `gradle`:
+
+  ```sh
+  $ ./gradlew installDebug
+  ```

+ 1 - 0
examples/android/helloworld/app/.gitignore

@@ -0,0 +1 @@
+/build

+ 123 - 0
examples/android/helloworld/app/CMakeLists.txt

@@ -0,0 +1,123 @@
+cmake_minimum_required(VERSION 3.4.1)
+
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+
+set(helloworld_PROTOBUF_PROTOC_EXECUTABLE "/usr/local/bin/protoc" CACHE STRING "Protoc binary on host")
+set(helloworld_GRPC_CPP_PLUGIN_EXECUTABLE "/usr/local/bin/grpc_cpp_plugin" CACHE STRING "gRPC CPP plugin binary on host")
+
+set(GRPC_SRC_DIR ../../../../)
+
+set(GRPC_BUILD_DIR ../grpc/outputs/${ANDROID_ABI})
+file(MAKE_DIRECTORY ${GRPC_BUILD_DIR})
+
+add_subdirectory(${GRPC_SRC_DIR} ${GRPC_BUILD_DIR})
+
+include_directories(${GRPC_SRC_DIR}/include)
+
+add_library(libgrpc STATIC IMPORTED)
+set_target_properties(libgrpc PROPERTIES IMPORTED_LOCATION
+  ${GRPC_BUILD_DIR}/libgrpc.a)
+
+add_library(libgrpc++ STATIC IMPORTED)
+set_target_properties(libgrpc++ PROPERTIES IMPORTED_LOCATION
+  ${GRPC_BUILD_DIR}/libgrpc++.a)
+
+add_library(libgpr STATIC IMPORTED)
+set_target_properties(libgpr PROPERTIES IMPORTED_LOCATION
+  ${GRPC_BUILD_DIR}/libgpr.a)
+
+add_library(libcares STATIC IMPORTED)
+set_target_properties(libcares PROPERTIES IMPORTED_LOCATION
+  ${GRPC_BUILD_DIR}/third_party/cares/cares/lib/libcares.a)
+
+add_library(libzlib STATIC IMPORTED)
+set_target_properties(libzlib PROPERTIES IMPORTED_LOCATION
+  ${GRPC_BUILD_DIR}/third_party/zlib/libz.a)
+
+add_library(libcrypto STATIC IMPORTED)
+set_target_properties(libcrypto PROPERTIES IMPORTED_LOCATION
+  ${GRPC_BUILD_DIR}/third_party/boringssl/crypto/libcrypto.a)
+
+add_library(libssl STATIC IMPORTED)
+set_target_properties(libssl PROPERTIES IMPORTED_LOCATION
+  ${GRPC_BUILD_DIR}/third_party/boringssl/ssl/libssl.a)
+
+set(GRPC_PROTO_GENS_DIR ${CMAKE_BINARY_DIR}/gens)
+file(MAKE_DIRECTORY ${GRPC_PROTO_GENS_DIR})
+include_directories(${GRPC_PROTO_GENS_DIR})
+
+function(android_protobuf_grpc_generate_cpp SRC_FILES HDR_FILES INCLUDE_ROOT)
+  if(NOT ARGN)
+    message(SEND_ERROR "Error: android_protobuf_grpc_generate_cpp() called without any proto files")
+    return()
+  endif()
+
+  set(${SRC_FILES})
+  set(${HDR_FILES})
+  set(PROTOBUF_INCLUDE_PATH -I ${INCLUDE_ROOT})
+  foreach(FIL ${ARGN})
+    get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
+    get_filename_component(FIL_WE ${FIL} NAME_WE)
+    file(RELATIVE_PATH REL_FIL ${CMAKE_CURRENT_SOURCE_DIR}/${INCLUDE_ROOT} ${ABS_FIL})
+    get_filename_component(REL_DIR ${REL_FIL} DIRECTORY)
+    set(RELFIL_WE "${REL_DIR}/${FIL_WE}")
+
+    list(APPEND ${SRC_FILES} "${GRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.cc")
+    list(APPEND ${HDR_FILES} "${GRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.h")
+    list(APPEND ${SRC_FILES} "${GRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.cc")
+    list(APPEND ${HDR_FILES} "${GRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.h")
+
+    add_custom_command(
+      OUTPUT "${GRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.cc"
+             "${GRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.h"
+             "${GRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.cc"
+             "${GRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.h"
+      COMMAND ${helloworld_PROTOBUF_PROTOC_EXECUTABLE}
+      ARGS --grpc_out=${GRPC_PROTO_GENS_DIR}
+        --cpp_out=${GRPC_PROTO_GENS_DIR}
+        --plugin=protoc-gen-grpc=${helloworld_GRPC_CPP_PLUGIN_EXECUTABLE}
+        ${PROTOBUF_INCLUDE_PATH}
+        ${REL_FIL}
+      WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+      DEPENDS ${helloworld_PROTOBUF_PROTOC_EXECUTABLE} ${helloworld_GRPC_CPP_PLUGIN_EXECUTABLE} ${ABS_FIL} )
+  endforeach()
+
+  set_source_files_properties(${${SRC_FILES}} ${${HDR_FILES}} PROPERTIES GENERATED TRUE)
+  set(${SRC_FILES} ${${SRC_FILES}} PARENT_SCOPE)
+  set(${HDR_FILES} ${${HDR_FILES}} PARENT_SCOPE)
+endfunction()
+
+set(PROTO_BASE_DIR ${GRPC_SRC_DIR}/examples/protos)
+
+android_protobuf_grpc_generate_cpp(
+  HELLOWORLD_PROTO_SRCS HELLOWORLD_PROTO_HDRS ${PROTO_BASE_DIR} ${PROTO_BASE_DIR}/helloworld.proto)
+
+add_library(helloworld_proto_lib
+  SHARED ${HELLOWORLD_PROTO_HDRS} ${HELLOWORLD_PROTO_SRCS})
+
+target_link_libraries(helloworld_proto_lib
+  libprotobuf
+  libgrpc++
+  android
+  log)
+
+find_library(log-lib
+ log)
+
+add_library(grpc-helloworld
+  SHARED src/main/cpp/grpc-helloworld.cc)
+
+target_include_directories(grpc-helloworld
+  PRIVATE ${HELLOWORLD_PROTO_HEADERS})
+
+target_link_libraries(grpc-helloworld
+  libgrpc++
+  libgrpc
+  libzlib
+  libcares
+  libssl
+  libcrypto
+  helloworld_proto_lib
+  libgpr
+  android
+  ${log-lib})

+ 53 - 0
examples/android/helloworld/app/build.gradle

@@ -0,0 +1,53 @@
+apply plugin: 'com.android.application'
+
+android {
+    compileSdkVersion 26
+    defaultConfig {
+        applicationId "io.grpc.android.cpp.helloworldexample"
+        minSdkVersion 14
+        targetSdkVersion 26
+        versionCode 1
+        versionName "1.0"
+        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+        externalNativeBuild {
+            cmake {
+                cppFlags "-std=c++14 -frtti -fexceptions"
+                arguments '-DANDROID_STL=c++_static'
+                arguments '-DRUN_HAVE_POSIX_REGEX=0'
+                arguments '-DRUN_HAVE_STD_REGEX=0'
+                arguments '-DRUN_HAVE_STEADY_CLOCK=0'
+                arguments '-Dprotobuf_BUILD_PROTOC_BINARIES=off'
+                arguments '-DgRPC_BUILD_CODEGEN=off'
+                // Set this to the path to the protoc binary on the host system (codegen is not
+                // cross-compiled to Android)
+                arguments '-Dhelloworld_PROTOBUF_PROTOC_EXECUTABLE=/usr/local/bin/protoc'
+                // Set this to the path to the gRPC C++ protoc plugin binary on the host system
+                // (codegen is not cross-compiled to Android)
+                arguments '-Dhelloworld_GRPC_CPP_PLUGIN_EXECUTABLE=/usr/local/bin/grpc_cpp_plugin'
+            }
+        }
+        ndk.abiFilters 'x86'
+    }
+    buildTypes {
+        debug {
+            minifyEnabled false
+        }
+        release {
+            minifyEnabled true
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+        }
+    }
+    externalNativeBuild {
+        cmake {
+            path "CMakeLists.txt"
+        }
+    }
+}
+
+dependencies {
+    implementation fileTree(dir: 'libs', include: ['*.jar'])
+    implementation 'com.android.support:appcompat-v7:26.1.0'
+    testImplementation 'junit:junit:4.12'
+    androidTestImplementation 'com.android.support.test:runner:1.0.1'
+    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
+}

+ 21 - 0
examples/android/helloworld/app/proguard-rules.pro

@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile

+ 22 - 0
examples/android/helloworld/app/src/main/AndroidManifest.xml

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="io.grpc.helloworldexample.cpp" >
+
+    <uses-permission android:name="android.permission.INTERNET" />
+
+    <application
+        android:allowBackup="false"
+        android:icon="@mipmap/ic_launcher"
+        android:label="@string/app_name"
+        android:theme="@style/Base.V7.Theme.AppCompat.Light" >
+        <activity
+            android:name=".HelloworldActivity"
+            android:label="@string/app_name" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+</manifest>

+ 142 - 0
examples/android/helloworld/app/src/main/cpp/grpc-helloworld.cc

@@ -0,0 +1,142 @@
+/*
+ *
+ * Copyright 2018 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.
+ *
+ */
+
+#include <atomic>
+
+#include <grpc++/grpc++.h>
+#include <jni.h>
+
+#include "helloworld.grpc.pb.h"
+
+using grpc::Channel;
+using grpc::ClientContext;
+using grpc::Server;
+using grpc::ServerBuilder;
+using grpc::ServerContext;
+using grpc::Status;
+using helloworld::Greeter;
+using helloworld::HelloReply;
+using helloworld::HelloRequest;
+
+std::atomic<bool> stop_server(false);
+
+// Logic and data behind the server's behavior.
+class GreeterServiceImpl final : public Greeter::Service {
+  Status SayHello(ServerContext* context, const HelloRequest* request,
+                  HelloReply* reply) override {
+    std::string prefix("Hello ");
+    reply->set_message(prefix + request->name());
+    return Status::OK;
+  }
+};
+
+void StartServer(JNIEnv* env, jobject obj, jmethodID is_cancelled_mid,
+                 int port) {
+  const int host_port_buf_size = 1024;
+  char host_port[host_port_buf_size];
+  snprintf(host_port, host_port_buf_size, "0.0.0.0:%d", port);
+
+  GreeterServiceImpl service;
+  ServerBuilder builder;
+  // Listen on the given address without any authentication mechanism.
+  builder.AddListeningPort(host_port, grpc::InsecureServerCredentials());
+  // Register "service" as the instance through which we'll communicate with
+  // clients. In this case it corresponds to an *synchronous* service.
+  builder.RegisterService(&service);
+  // Finally assemble the server.
+  std::unique_ptr<Server> server(builder.BuildAndStart());
+  while (!stop_server.load()) {
+    // Check with the Java code to see if the user has requested the server stop or the app is no
+    // longer in the foreground.
+    jboolean is_cancelled = env->CallBooleanMethod(obj, is_cancelled_mid);
+    if (is_cancelled == JNI_TRUE) {
+      stop_server = true;
+    }
+  }
+}
+
+class GreeterClient {
+ public:
+  GreeterClient(std::shared_ptr<Channel> channel)
+      : stub_(Greeter::NewStub(channel)) {}
+
+  // Assembles the client's payload, sends it and presents the response back
+  // from the server.
+  std::string SayHello(const std::string& user) {
+    // Data we are sending to the server.
+    HelloRequest request;
+    request.set_name(user);
+
+    // Container for the data we expect from the server.
+    HelloReply reply;
+
+    // Context for the client. It could be used to convey extra information to
+    // the server and/or tweak certain RPC behaviors.
+    ClientContext context;
+    // The actual RPC.
+    Status status = stub_->SayHello(&context, request, &reply);
+
+    if (status.ok()) {
+      return reply.message();
+    } else {
+      return status.error_message();
+    }
+  }
+
+ private:
+  std::unique_ptr<Greeter::Stub> stub_;
+};
+
+// Send an RPC and return the response. Invoked from Java code.
+extern "C" JNIEXPORT jstring JNICALL
+Java_io_grpc_helloworldexample_cpp_HelloworldActivity_sayHello(
+    JNIEnv* env, jobject obj_unused, jstring host_raw, jint port_raw,
+    jstring message_raw) {
+  const char* host_chars = env->GetStringUTFChars(host_raw, (jboolean*)0);
+  std::string host(host_chars, env->GetStringUTFLength(host_raw));
+
+  int port = static_cast<int>(port_raw);
+
+  const char* message_chars = env->GetStringUTFChars(message_raw, (jboolean*)0);
+  std::string message(message_chars, env->GetStringUTFLength(message_raw));
+
+  const int host_port_buf_size = 1024;
+  char host_port[host_port_buf_size];
+  snprintf(host_port, host_port_buf_size, "%s:%d", host.c_str(), port);
+
+  GreeterClient greeter(
+      grpc::CreateChannel(host_port, grpc::InsecureChannelCredentials()));
+  std::string reply = greeter.SayHello(message);
+
+  return env->NewStringUTF(reply.c_str());
+}
+
+// Start the server. Invoked from Java code.
+extern "C" JNIEXPORT void JNICALL
+Java_io_grpc_helloworldexample_cpp_HelloworldActivity_startServer(
+    JNIEnv* env, jobject obj_this, jint port_raw) {
+  int port = static_cast<int>(port_raw);
+
+  jclass cls = env->GetObjectClass(obj_this);
+  jmethodID is_cancelled_mid =
+      env->GetMethodID(cls, "isRunServerTaskCancelled", "()Z");
+
+  stop_server = false;
+
+  StartServer(env, obj_this, is_cancelled_mid, port);
+}

+ 167 - 0
examples/android/helloworld/app/src/main/java/io/grpc/helloworldexample/cpp/HelloworldActivity.java

@@ -0,0 +1,167 @@
+/*
+ * Copyright 2018, gRPC Authors All rights reserved.
+ *
+ * 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.
+ */
+
+package io.grpc.helloworldexample.cpp;
+
+import android.content.Context;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.support.v7.app.AppCompatActivity;
+import android.text.TextUtils;
+import android.text.method.ScrollingMovementMethod;
+import android.view.View;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.TextView;
+import android.widget.Toast;
+import java.lang.ref.WeakReference;
+
+public class HelloworldActivity extends AppCompatActivity {
+
+  static {
+    System.loadLibrary("grpc-helloworld");
+  }
+
+  private Button sendButton;
+  private Button serverButton;
+  private EditText hostEdit;
+  private EditText portEdit;
+  private EditText messageEdit;
+  private EditText serverPortEdit;
+  private TextView resultText;
+  private GrpcTask grpcTask;
+  private RunServerTask runServerTask;
+
+  @Override
+  protected void onCreate(Bundle savedInstanceState) {
+    super.onCreate(savedInstanceState);
+    setContentView(R.layout.activity_helloworld);
+    sendButton = (Button) findViewById(R.id.send_button);
+    serverButton = (Button) findViewById(R.id.server_button);
+    hostEdit = (EditText) findViewById(R.id.host_edit_text);
+    portEdit = (EditText) findViewById(R.id.port_edit_text);
+    messageEdit = (EditText) findViewById(R.id.message_edit_text);
+    serverPortEdit = (EditText) findViewById(R.id.server_port_edit_text);
+    resultText = (TextView) findViewById(R.id.grpc_response_text);
+    resultText.setMovementMethod(new ScrollingMovementMethod());
+  }
+
+  @Override
+  protected void onPause() {
+    super.onPause();
+    if (runServerTask != null) {
+      runServerTask.cancel(true);
+      runServerTask = null;
+      serverButton.setText("Start gRPC Server");
+    }
+    if (grpcTask != null) {
+      grpcTask.cancel(true);
+      grpcTask = null;
+    }
+  }
+
+  public void sendMessage(View view) {
+    ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE))
+        .hideSoftInputFromWindow(hostEdit.getWindowToken(), 0);
+    sendButton.setEnabled(false);
+    resultText.setText("");
+    grpcTask = new GrpcTask(this);
+    grpcTask.executeOnExecutor(
+        AsyncTask.THREAD_POOL_EXECUTOR,
+        hostEdit.getText().toString(),
+        messageEdit.getText().toString(),
+        portEdit.getText().toString());
+  }
+
+  public void startOrStopServer(View view) {
+    if (runServerTask != null) {
+      runServerTask.cancel(true);
+      runServerTask = null;
+      serverButton.setText("Start gRPC Server");
+      Toast.makeText(this, "Server stopped", Toast.LENGTH_SHORT).show();
+    } else {
+      runServerTask = new RunServerTask(this);
+      String portStr = serverPortEdit.getText().toString();
+      int port = TextUtils.isEmpty(portStr) ? 50051 : Integer.valueOf(portStr);
+      runServerTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, port);
+      serverButton.setText("Stop gRPC Server");
+      Toast.makeText(this, "Server started on port " + port, Toast.LENGTH_SHORT).show();
+    }
+  }
+
+  private static class RunServerTask extends AsyncTask<Integer, Void, Void> {
+    private final WeakReference<HelloworldActivity> activityReference;
+
+    private RunServerTask(HelloworldActivity activity) {
+      this.activityReference = new WeakReference<HelloworldActivity>(activity);
+    }
+
+    @Override
+    protected Void doInBackground(Integer... params) {
+      int port = params[0];
+      HelloworldActivity activity = activityReference.get();
+      if (activity != null) {
+        activity.startServer(port);
+      }
+      return null;
+    }
+  }
+
+  private static class GrpcTask extends AsyncTask<String, Void, String> {
+    private final WeakReference<HelloworldActivity> activityReference;
+
+    private GrpcTask(HelloworldActivity activity) {
+      this.activityReference = new WeakReference<HelloworldActivity>(activity);
+    }
+
+    @Override
+    protected String doInBackground(String... params) {
+      String host = params[0];
+      String message = params[1];
+      String portStr = params[2];
+      int port = TextUtils.isEmpty(portStr) ? 50051 : Integer.valueOf(portStr);
+      return sayHello(host, port, message);
+    }
+
+    @Override
+    protected void onPostExecute(String result) {
+      HelloworldActivity activity = activityReference.get();
+      if (activity == null || isCancelled()) {
+        return;
+      }
+      TextView resultText = (TextView) activity.findViewById(R.id.grpc_response_text);
+      Button sendButton = (Button) activity.findViewById(R.id.send_button);
+      resultText.setText(result);
+      sendButton.setEnabled(true);
+    }
+  }
+
+  /**
+   * Invoked by native code to stop server when RunServerTask has been canceled, either by user
+   * request or upon app moving to background.
+   */
+  public boolean isRunServerTaskCancelled() {
+    if (runServerTask != null) {
+      return runServerTask.isCancelled();
+    }
+    return false;
+  }
+
+  public static native String sayHello(String host, int port, String message);
+
+  public native void startServer(int port);
+}

+ 86 - 0
examples/android/helloworld/app/src/main/res/layout/activity_helloworld.xml

@@ -0,0 +1,86 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
+              android:layout_height="match_parent"
+              tools:context=".HelloworldActivity"
+              android:orientation="vertical" >
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingTop="12dp"
+        android:paddingBottom="12dp"
+        android:textSize="16sp"
+        android:text="gRPC Client Configuration"
+        android:textStyle="bold" />
+
+    <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal">
+        <EditText
+                android:id="@+id/host_edit_text"
+                android:layout_weight="2"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:hint="Enter Host" />
+        <EditText
+                android:id="@+id/port_edit_text"
+                android:layout_weight="1"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:inputType="numberDecimal"
+                android:hint="Enter Port" />
+    </LinearLayout>
+
+
+    <EditText
+            android:id="@+id/message_edit_text"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:hint="Enter message to send" />
+
+    <Button
+            android:id="@+id/send_button"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:onClick="sendMessage"
+            android:text="Send gRPC Request" />
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingTop="12dp"
+        android:paddingBottom="12dp"
+        android:textSize="16sp"
+        android:text="Response:" />
+
+    <TextView
+        android:id="@+id/grpc_response_text"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:scrollbars = "vertical"
+        android:textSize="16sp" />
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingTop="12dp"
+        android:paddingBottom="12dp"
+        android:textSize="16sp"
+        android:text="gRPC Server Configuration"
+        android:textStyle="bold" />
+
+    <EditText
+        android:id="@+id/server_port_edit_text"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:hint="Server port" />
+
+    <Button
+        android:id="@+id/server_button"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:onClick="startOrStopServer"
+        android:text="Start gRPC Server" />
+
+</LinearLayout>

BIN
examples/android/helloworld/app/src/main/res/mipmap-hdpi/ic_launcher.png


BIN
examples/android/helloworld/app/src/main/res/mipmap-mdpi/ic_launcher.png


BIN
examples/android/helloworld/app/src/main/res/mipmap-xhdpi/ic_launcher.png


BIN
examples/android/helloworld/app/src/main/res/mipmap-xxhdpi/ic_launcher.png


+ 3 - 0
examples/android/helloworld/app/src/main/res/values/strings.xml

@@ -0,0 +1,3 @@
+<resources>
+    <string name="app_name">GrpcHelloworldCppExample</string>
+</resources>

+ 24 - 0
examples/android/helloworld/build.gradle

@@ -0,0 +1,24 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+    repositories {
+        google()
+        jcenter()
+    }
+    dependencies {
+        classpath 'com.android.tools.build:gradle:3.0.1'
+        // NOTE: Do not place your application dependencies here; they belong
+        // in the individual module build.gradle files
+    }
+}
+
+allprojects {
+    repositories {
+        google()
+        jcenter()
+    }
+}
+
+task clean(type: Delete) {
+    delete rootProject.buildDir
+}

+ 17 - 0
examples/android/helloworld/gradle.properties

@@ -0,0 +1,17 @@
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx1536m
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true

BIN
examples/android/helloworld/gradle/wrapper/gradle-wrapper.jar


+ 6 - 0
examples/android/helloworld/gradle/wrapper/gradle-wrapper.properties

@@ -0,0 +1,6 @@
+#Thu Jan 25 11:45:30 PST 2018
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip

+ 160 - 0
examples/android/helloworld/gradlew

@@ -0,0 +1,160 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+    echo "$*"
+}
+
+die ( ) {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+esac
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+    JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

+ 90 - 0
examples/android/helloworld/gradlew.bat

@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega

+ 1 - 0
examples/android/helloworld/settings.gradle

@@ -0,0 +1 @@
+include ':app'

+ 2 - 2
gRPC-C++.podspec

@@ -220,7 +220,6 @@ Pod::Spec.new do |s|
                       'src/core/lib/gpr/spinlock.h',
                       'src/core/lib/gpr/spinlock.h',
                       'src/core/lib/gpr/string.h',
                       'src/core/lib/gpr/string.h',
                       'src/core/lib/gpr/string_windows.h',
                       'src/core/lib/gpr/string_windows.h',
-                      'src/core/lib/gpr/thd.h',
                       'src/core/lib/gpr/time_precise.h',
                       'src/core/lib/gpr/time_precise.h',
                       'src/core/lib/gpr/tls.h',
                       'src/core/lib/gpr/tls.h',
                       'src/core/lib/gpr/tls_gcc.h',
                       'src/core/lib/gpr/tls_gcc.h',
@@ -234,6 +233,7 @@ Pod::Spec.new do |s|
                       'src/core/lib/gprpp/atomic_with_std.h',
                       'src/core/lib/gprpp/atomic_with_std.h',
                       'src/core/lib/gprpp/manual_constructor.h',
                       'src/core/lib/gprpp/manual_constructor.h',
                       'src/core/lib/gprpp/memory.h',
                       'src/core/lib/gprpp/memory.h',
+                      'src/core/lib/gprpp/thd.h',
                       'src/core/lib/profiling/timers.h',
                       'src/core/lib/profiling/timers.h',
                       'src/core/ext/transport/chttp2/transport/bin_decoder.h',
                       'src/core/ext/transport/chttp2/transport/bin_decoder.h',
                       'src/core/ext/transport/chttp2/transport/bin_encoder.h',
                       'src/core/ext/transport/chttp2/transport/bin_encoder.h',
@@ -477,7 +477,6 @@ Pod::Spec.new do |s|
                               'src/core/lib/gpr/spinlock.h',
                               'src/core/lib/gpr/spinlock.h',
                               'src/core/lib/gpr/string.h',
                               'src/core/lib/gpr/string.h',
                               'src/core/lib/gpr/string_windows.h',
                               'src/core/lib/gpr/string_windows.h',
-                              'src/core/lib/gpr/thd.h',
                               'src/core/lib/gpr/time_precise.h',
                               'src/core/lib/gpr/time_precise.h',
                               'src/core/lib/gpr/tls.h',
                               'src/core/lib/gpr/tls.h',
                               'src/core/lib/gpr/tls_gcc.h',
                               'src/core/lib/gpr/tls_gcc.h',
@@ -491,6 +490,7 @@ Pod::Spec.new do |s|
                               'src/core/lib/gprpp/atomic_with_std.h',
                               'src/core/lib/gprpp/atomic_with_std.h',
                               'src/core/lib/gprpp/manual_constructor.h',
                               'src/core/lib/gprpp/manual_constructor.h',
                               'src/core/lib/gprpp/memory.h',
                               'src/core/lib/gprpp/memory.h',
+                              'src/core/lib/gprpp/thd.h',
                               'src/core/lib/profiling/timers.h',
                               'src/core/lib/profiling/timers.h',
                               'src/core/lib/avl/avl.h',
                               'src/core/lib/avl/avl.h',
                               'src/core/lib/backoff/backoff.h',
                               'src/core/lib/backoff/backoff.h',

+ 4 - 5
gRPC-Core.podspec

@@ -192,7 +192,6 @@ Pod::Spec.new do |s|
                       'src/core/lib/gpr/spinlock.h',
                       'src/core/lib/gpr/spinlock.h',
                       'src/core/lib/gpr/string.h',
                       'src/core/lib/gpr/string.h',
                       'src/core/lib/gpr/string_windows.h',
                       'src/core/lib/gpr/string_windows.h',
-                      'src/core/lib/gpr/thd.h',
                       'src/core/lib/gpr/time_precise.h',
                       'src/core/lib/gpr/time_precise.h',
                       'src/core/lib/gpr/tls.h',
                       'src/core/lib/gpr/tls.h',
                       'src/core/lib/gpr/tls_gcc.h',
                       'src/core/lib/gpr/tls_gcc.h',
@@ -206,6 +205,7 @@ Pod::Spec.new do |s|
                       'src/core/lib/gprpp/atomic_with_std.h',
                       'src/core/lib/gprpp/atomic_with_std.h',
                       'src/core/lib/gprpp/manual_constructor.h',
                       'src/core/lib/gprpp/manual_constructor.h',
                       'src/core/lib/gprpp/memory.h',
                       'src/core/lib/gprpp/memory.h',
+                      'src/core/lib/gprpp/thd.h',
                       'src/core/lib/profiling/timers.h',
                       'src/core/lib/profiling/timers.h',
                       'src/core/lib/gpr/alloc.cc',
                       'src/core/lib/gpr/alloc.cc',
                       'src/core/lib/gpr/arena.cc',
                       'src/core/lib/gpr/arena.cc',
@@ -233,9 +233,6 @@ Pod::Spec.new do |s|
                       'src/core/lib/gpr/sync.cc',
                       'src/core/lib/gpr/sync.cc',
                       'src/core/lib/gpr/sync_posix.cc',
                       'src/core/lib/gpr/sync_posix.cc',
                       'src/core/lib/gpr/sync_windows.cc',
                       'src/core/lib/gpr/sync_windows.cc',
-                      'src/core/lib/gpr/thd.cc',
-                      'src/core/lib/gpr/thd_posix.cc',
-                      'src/core/lib/gpr/thd_windows.cc',
                       'src/core/lib/gpr/time.cc',
                       'src/core/lib/gpr/time.cc',
                       'src/core/lib/gpr/time_posix.cc',
                       'src/core/lib/gpr/time_posix.cc',
                       'src/core/lib/gpr/time_precise.cc',
                       'src/core/lib/gpr/time_precise.cc',
@@ -245,6 +242,8 @@ Pod::Spec.new do |s|
                       'src/core/lib/gpr/tmpfile_posix.cc',
                       'src/core/lib/gpr/tmpfile_posix.cc',
                       'src/core/lib/gpr/tmpfile_windows.cc',
                       'src/core/lib/gpr/tmpfile_windows.cc',
                       'src/core/lib/gpr/wrap_memcpy.cc',
                       'src/core/lib/gpr/wrap_memcpy.cc',
+                      'src/core/lib/gprpp/thd_posix.cc',
+                      'src/core/lib/gprpp/thd_windows.cc',
                       'src/core/lib/profiling/basic_timers.cc',
                       'src/core/lib/profiling/basic_timers.cc',
                       'src/core/lib/profiling/stap_timers.cc',
                       'src/core/lib/profiling/stap_timers.cc',
                       'src/core/ext/transport/chttp2/transport/bin_decoder.h',
                       'src/core/ext/transport/chttp2/transport/bin_decoder.h',
@@ -730,7 +729,6 @@ Pod::Spec.new do |s|
                               'src/core/lib/gpr/spinlock.h',
                               'src/core/lib/gpr/spinlock.h',
                               'src/core/lib/gpr/string.h',
                               'src/core/lib/gpr/string.h',
                               'src/core/lib/gpr/string_windows.h',
                               'src/core/lib/gpr/string_windows.h',
-                              'src/core/lib/gpr/thd.h',
                               'src/core/lib/gpr/time_precise.h',
                               'src/core/lib/gpr/time_precise.h',
                               'src/core/lib/gpr/tls.h',
                               'src/core/lib/gpr/tls.h',
                               'src/core/lib/gpr/tls_gcc.h',
                               'src/core/lib/gpr/tls_gcc.h',
@@ -744,6 +742,7 @@ Pod::Spec.new do |s|
                               'src/core/lib/gprpp/atomic_with_std.h',
                               'src/core/lib/gprpp/atomic_with_std.h',
                               'src/core/lib/gprpp/manual_constructor.h',
                               'src/core/lib/gprpp/manual_constructor.h',
                               'src/core/lib/gprpp/memory.h',
                               'src/core/lib/gprpp/memory.h',
+                              'src/core/lib/gprpp/thd.h',
                               'src/core/lib/profiling/timers.h',
                               'src/core/lib/profiling/timers.h',
                               'src/core/ext/transport/chttp2/transport/bin_decoder.h',
                               'src/core/ext/transport/chttp2/transport/bin_decoder.h',
                               'src/core/ext/transport/chttp2/transport/bin_encoder.h',
                               'src/core/ext/transport/chttp2/transport/bin_encoder.h',

+ 3 - 4
grpc.gemspec

@@ -83,7 +83,6 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/lib/gpr/spinlock.h )
   s.files += %w( src/core/lib/gpr/spinlock.h )
   s.files += %w( src/core/lib/gpr/string.h )
   s.files += %w( src/core/lib/gpr/string.h )
   s.files += %w( src/core/lib/gpr/string_windows.h )
   s.files += %w( src/core/lib/gpr/string_windows.h )
-  s.files += %w( src/core/lib/gpr/thd.h )
   s.files += %w( src/core/lib/gpr/time_precise.h )
   s.files += %w( src/core/lib/gpr/time_precise.h )
   s.files += %w( src/core/lib/gpr/tls.h )
   s.files += %w( src/core/lib/gpr/tls.h )
   s.files += %w( src/core/lib/gpr/tls_gcc.h )
   s.files += %w( src/core/lib/gpr/tls_gcc.h )
@@ -97,6 +96,7 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/lib/gprpp/atomic_with_std.h )
   s.files += %w( src/core/lib/gprpp/atomic_with_std.h )
   s.files += %w( src/core/lib/gprpp/manual_constructor.h )
   s.files += %w( src/core/lib/gprpp/manual_constructor.h )
   s.files += %w( src/core/lib/gprpp/memory.h )
   s.files += %w( src/core/lib/gprpp/memory.h )
+  s.files += %w( src/core/lib/gprpp/thd.h )
   s.files += %w( src/core/lib/profiling/timers.h )
   s.files += %w( src/core/lib/profiling/timers.h )
   s.files += %w( src/core/lib/gpr/alloc.cc )
   s.files += %w( src/core/lib/gpr/alloc.cc )
   s.files += %w( src/core/lib/gpr/arena.cc )
   s.files += %w( src/core/lib/gpr/arena.cc )
@@ -124,9 +124,6 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/lib/gpr/sync.cc )
   s.files += %w( src/core/lib/gpr/sync.cc )
   s.files += %w( src/core/lib/gpr/sync_posix.cc )
   s.files += %w( src/core/lib/gpr/sync_posix.cc )
   s.files += %w( src/core/lib/gpr/sync_windows.cc )
   s.files += %w( src/core/lib/gpr/sync_windows.cc )
-  s.files += %w( src/core/lib/gpr/thd.cc )
-  s.files += %w( src/core/lib/gpr/thd_posix.cc )
-  s.files += %w( src/core/lib/gpr/thd_windows.cc )
   s.files += %w( src/core/lib/gpr/time.cc )
   s.files += %w( src/core/lib/gpr/time.cc )
   s.files += %w( src/core/lib/gpr/time_posix.cc )
   s.files += %w( src/core/lib/gpr/time_posix.cc )
   s.files += %w( src/core/lib/gpr/time_precise.cc )
   s.files += %w( src/core/lib/gpr/time_precise.cc )
@@ -136,6 +133,8 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/lib/gpr/tmpfile_posix.cc )
   s.files += %w( src/core/lib/gpr/tmpfile_posix.cc )
   s.files += %w( src/core/lib/gpr/tmpfile_windows.cc )
   s.files += %w( src/core/lib/gpr/tmpfile_windows.cc )
   s.files += %w( src/core/lib/gpr/wrap_memcpy.cc )
   s.files += %w( src/core/lib/gpr/wrap_memcpy.cc )
+  s.files += %w( src/core/lib/gprpp/thd_posix.cc )
+  s.files += %w( src/core/lib/gprpp/thd_windows.cc )
   s.files += %w( src/core/lib/profiling/basic_timers.cc )
   s.files += %w( src/core/lib/profiling/basic_timers.cc )
   s.files += %w( src/core/lib/profiling/stap_timers.cc )
   s.files += %w( src/core/lib/profiling/stap_timers.cc )
   s.files += %w( include/grpc/impl/codegen/byte_buffer.h )
   s.files += %w( include/grpc/impl/codegen/byte_buffer.h )

+ 2 - 3
grpc.gyp

@@ -187,9 +187,6 @@
         'src/core/lib/gpr/sync.cc',
         'src/core/lib/gpr/sync.cc',
         'src/core/lib/gpr/sync_posix.cc',
         'src/core/lib/gpr/sync_posix.cc',
         'src/core/lib/gpr/sync_windows.cc',
         'src/core/lib/gpr/sync_windows.cc',
-        'src/core/lib/gpr/thd.cc',
-        'src/core/lib/gpr/thd_posix.cc',
-        'src/core/lib/gpr/thd_windows.cc',
         'src/core/lib/gpr/time.cc',
         'src/core/lib/gpr/time.cc',
         'src/core/lib/gpr/time_posix.cc',
         'src/core/lib/gpr/time_posix.cc',
         'src/core/lib/gpr/time_precise.cc',
         'src/core/lib/gpr/time_precise.cc',
@@ -199,6 +196,8 @@
         'src/core/lib/gpr/tmpfile_posix.cc',
         'src/core/lib/gpr/tmpfile_posix.cc',
         'src/core/lib/gpr/tmpfile_windows.cc',
         'src/core/lib/gpr/tmpfile_windows.cc',
         'src/core/lib/gpr/wrap_memcpy.cc',
         'src/core/lib/gpr/wrap_memcpy.cc',
+        'src/core/lib/gprpp/thd_posix.cc',
+        'src/core/lib/gprpp/thd_windows.cc',
         'src/core/lib/profiling/basic_timers.cc',
         'src/core/lib/profiling/basic_timers.cc',
         'src/core/lib/profiling/stap_timers.cc',
         'src/core/lib/profiling/stap_timers.cc',
       ],
       ],

+ 3 - 4
package.xml

@@ -90,7 +90,6 @@
     <file baseinstalldir="/" name="src/core/lib/gpr/spinlock.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gpr/spinlock.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gpr/string.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gpr/string.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gpr/string_windows.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gpr/string_windows.h" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/gpr/thd.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gpr/time_precise.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gpr/time_precise.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gpr/tls.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gpr/tls.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gpr/tls_gcc.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gpr/tls_gcc.h" role="src" />
@@ -104,6 +103,7 @@
     <file baseinstalldir="/" name="src/core/lib/gprpp/atomic_with_std.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gprpp/atomic_with_std.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gprpp/manual_constructor.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gprpp/manual_constructor.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gprpp/memory.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gprpp/memory.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/gprpp/thd.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/profiling/timers.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/profiling/timers.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gpr/alloc.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gpr/alloc.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gpr/arena.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gpr/arena.cc" role="src" />
@@ -131,9 +131,6 @@
     <file baseinstalldir="/" name="src/core/lib/gpr/sync.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gpr/sync.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gpr/sync_posix.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gpr/sync_posix.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gpr/sync_windows.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gpr/sync_windows.cc" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/gpr/thd.cc" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/gpr/thd_posix.cc" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/gpr/thd_windows.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gpr/time.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gpr/time.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gpr/time_posix.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gpr/time_posix.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gpr/time_precise.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gpr/time_precise.cc" role="src" />
@@ -143,6 +140,8 @@
     <file baseinstalldir="/" name="src/core/lib/gpr/tmpfile_posix.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gpr/tmpfile_posix.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gpr/tmpfile_windows.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gpr/tmpfile_windows.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gpr/wrap_memcpy.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gpr/wrap_memcpy.cc" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/gprpp/thd_posix.cc" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/gprpp/thd_windows.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/profiling/basic_timers.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/profiling/basic_timers.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/profiling/stap_timers.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/profiling/stap_timers.cc" role="src" />
     <file baseinstalldir="/" name="include/grpc/impl/codegen/byte_buffer.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/impl/codegen/byte_buffer.h" role="src" />

+ 0 - 51
src/core/lib/gpr/thd.cc

@@ -1,51 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-/* Platform-independent features for gpr threads. */
-
-#include <grpc/support/port_platform.h>
-
-#include "src/core/lib/gpr/thd.h"
-
-#include <string.h>
-
-enum { GPR_THD_JOINABLE = 1 };
-
-gpr_thd_options gpr_thd_options_default(void) {
-  gpr_thd_options options;
-  memset(&options, 0, sizeof(options));
-  return options;
-}
-
-void gpr_thd_options_set_detached(gpr_thd_options* options) {
-  options->flags &= ~GPR_THD_JOINABLE;
-}
-
-void gpr_thd_options_set_joinable(gpr_thd_options* options) {
-  options->flags |= GPR_THD_JOINABLE;
-}
-
-int gpr_thd_options_is_detached(const gpr_thd_options* options) {
-  if (!options) return 1;
-  return (options->flags & GPR_THD_JOINABLE) == 0;
-}
-
-int gpr_thd_options_is_joinable(const gpr_thd_options* options) {
-  if (!options) return 0;
-  return (options->flags & GPR_THD_JOINABLE) == GPR_THD_JOINABLE;
-}

+ 0 - 72
src/core/lib/gpr/thd.h

@@ -1,72 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef GRPC_CORE_LIB_GPR_THD_H
-#define GRPC_CORE_LIB_GPR_THD_H
-/** Internal thread interface for GPR.
-
-   Types
-        gpr_thd_options   options used when creating a thread
- */
-
-#include <grpc/support/port_platform.h>
-
-#include <grpc/support/thd_id.h>
-#include <grpc/support/time.h>
-
-/** Thread creation options. */
-typedef struct {
-  int flags; /** Opaque field. Get and set with accessors below. */
-} gpr_thd_options;
-
-/** Create a new thread running (*thd_body)(arg) and place its thread identifier
-   in *t, and return true.  If there are insufficient resources, return false.
-   thd_name is the name of the thread for identification purposes on platforms
-   that support thread naming.
-   If options==NULL, default options are used.
-   The thread is immediately runnable, and exits when (*thd_body)() returns.  */
-int gpr_thd_new(gpr_thd_id* t, const char* thd_name,
-                void (*thd_body)(void* arg), void* arg,
-                const gpr_thd_options* options);
-
-/** Return a gpr_thd_options struct with all fields set to defaults. */
-gpr_thd_options gpr_thd_options_default(void);
-
-/** Set the thread to become detached on startup - this is the default. */
-void gpr_thd_options_set_detached(gpr_thd_options* options);
-
-/** Set the thread to become joinable - mutually exclusive with detached. */
-void gpr_thd_options_set_joinable(gpr_thd_options* options);
-
-/** Returns non-zero if the option detached is set. */
-int gpr_thd_options_is_detached(const gpr_thd_options* options);
-
-/** Returns non-zero if the option joinable is set. */
-int gpr_thd_options_is_joinable(const gpr_thd_options* options);
-
-/** Blocks until the specified thread properly terminates.
-   Calling this on a detached thread has unpredictable results. */
-void gpr_thd_join(gpr_thd_id t);
-
-/* Internal interfaces between modules within the gpr support library.  */
-void gpr_thd_init();
-
-/* Wait for all outstanding threads to finish, up to deadline */
-int gpr_await_threads(gpr_timespec deadline);
-
-#endif /* GRPC_CORE_LIB_GPR_THD_H */

+ 0 - 154
src/core/lib/gpr/thd_posix.cc

@@ -1,154 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-/* Posix implementation for gpr threads. */
-
-#include <grpc/support/port_platform.h>
-
-#ifdef GPR_POSIX_SYNC
-
-#include "src/core/lib/gpr/thd.h"
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/sync.h>
-#include <grpc/support/thd_id.h>
-#include <pthread.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "src/core/lib/gpr/fork.h"
-#include "src/core/lib/gpr/useful.h"
-
-static gpr_mu g_mu;
-static gpr_cv g_cv;
-static int g_thread_count;
-static int g_awaiting_threads;
-
-struct thd_arg {
-  void (*body)(void* arg); /* body of a thread */
-  void* arg;               /* argument to a thread */
-  const char* name;        /* name of thread. Can be nullptr. */
-};
-
-static void inc_thd_count();
-static void dec_thd_count();
-
-/* Body of every thread started via gpr_thd_new. */
-static void* thread_body(void* v) {
-  struct thd_arg a = *static_cast<struct thd_arg*>(v);
-  free(v);
-  if (a.name != nullptr) {
-#if GPR_APPLE_PTHREAD_NAME
-    /* Apple supports 64 characters, and will truncate if it's longer. */
-    pthread_setname_np(a.name);
-#elif GPR_LINUX_PTHREAD_NAME
-    /* Linux supports 16 characters max, and will error if it's longer. */
-    char buf[16];
-    size_t buf_len = GPR_ARRAY_SIZE(buf) - 1;
-    strncpy(buf, a.name, buf_len);
-    buf[buf_len] = '\0';
-    pthread_setname_np(pthread_self(), buf);
-#endif  // GPR_APPLE_PTHREAD_NAME
-  }
-  (*a.body)(a.arg);
-  dec_thd_count();
-  return nullptr;
-}
-
-int gpr_thd_new(gpr_thd_id* t, const char* thd_name,
-                void (*thd_body)(void* arg), void* arg,
-                const gpr_thd_options* options) {
-  int thread_started;
-  pthread_attr_t attr;
-  pthread_t p;
-  /* don't use gpr_malloc as we may cause an infinite recursion with
-   * the profiling code */
-  struct thd_arg* a = static_cast<struct thd_arg*>(malloc(sizeof(*a)));
-  GPR_ASSERT(a != nullptr);
-  a->body = thd_body;
-  a->arg = arg;
-  a->name = thd_name;
-  inc_thd_count();
-
-  GPR_ASSERT(pthread_attr_init(&attr) == 0);
-  if (gpr_thd_options_is_detached(options)) {
-    GPR_ASSERT(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) ==
-               0);
-  } else {
-    GPR_ASSERT(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE) ==
-               0);
-  }
-  thread_started = (pthread_create(&p, &attr, &thread_body, a) == 0);
-  GPR_ASSERT(pthread_attr_destroy(&attr) == 0);
-  if (!thread_started) {
-    /* don't use gpr_free, as this was allocated using malloc (see above) */
-    free(a);
-    dec_thd_count();
-  }
-  *t = (gpr_thd_id)p;
-  return thread_started;
-}
-
-gpr_thd_id gpr_thd_currentid(void) { return (gpr_thd_id)pthread_self(); }
-
-void gpr_thd_join(gpr_thd_id t) { pthread_join((pthread_t)t, nullptr); }
-
-/*****************************************
- * Only used when fork support is enabled
- */
-
-static void inc_thd_count() {
-  if (grpc_fork_support_enabled()) {
-    gpr_mu_lock(&g_mu);
-    g_thread_count++;
-    gpr_mu_unlock(&g_mu);
-  }
-}
-
-static void dec_thd_count() {
-  if (grpc_fork_support_enabled()) {
-    gpr_mu_lock(&g_mu);
-    g_thread_count--;
-    if (g_awaiting_threads && g_thread_count == 0) {
-      gpr_cv_signal(&g_cv);
-    }
-    gpr_mu_unlock(&g_mu);
-  }
-}
-
-void gpr_thd_init() {
-  gpr_mu_init(&g_mu);
-  gpr_cv_init(&g_cv);
-  g_thread_count = 0;
-  g_awaiting_threads = 0;
-}
-
-int gpr_await_threads(gpr_timespec deadline) {
-  gpr_mu_lock(&g_mu);
-  g_awaiting_threads = 1;
-  int res = 0;
-  if (g_thread_count > 0) {
-    res = gpr_cv_wait(&g_cv, &g_mu, deadline);
-  }
-  g_awaiting_threads = 0;
-  gpr_mu_unlock(&g_mu);
-  return res == 0;
-}
-
-#endif /* GPR_POSIX_SYNC */

+ 0 - 107
src/core/lib/gpr/thd_windows.cc

@@ -1,107 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-/* Windows implementation for gpr threads. */
-
-#include <grpc/support/port_platform.h>
-
-#ifdef GPR_WINDOWS
-
-#include "src/core/lib/gpr/thd.h"
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/thd_id.h>
-#include <string.h>
-
-#if defined(_MSC_VER)
-#define thread_local __declspec(thread)
-#elif defined(__GNUC__)
-#define thread_local __thread
-#else
-#error "Unknown compiler - please file a bug report"
-#endif
-
-struct thd_info {
-  void (*body)(void* arg); /* body of a thread */
-  void* arg;               /* argument to a thread */
-  HANDLE join_event;       /* if joinable, the join event */
-  int joinable;            /* true if not detached */
-};
-
-static thread_local struct thd_info* g_thd_info;
-
-/* Destroys a thread info */
-static void destroy_thread(struct thd_info* t) {
-  if (t->joinable) CloseHandle(t->join_event);
-  gpr_free(t);
-}
-
-void gpr_thd_init(void) {}
-
-/* Body of every thread started via gpr_thd_new. */
-static DWORD WINAPI thread_body(void* v) {
-  g_thd_info = (struct thd_info*)v;
-  g_thd_info->body(g_thd_info->arg);
-  if (g_thd_info->joinable) {
-    BOOL ret = SetEvent(g_thd_info->join_event);
-    GPR_ASSERT(ret);
-  } else {
-    destroy_thread(g_thd_info);
-  }
-  return 0;
-}
-
-int gpr_thd_new(gpr_thd_id* t, const char* thd_name,
-                void (*thd_body)(void* arg), void* arg,
-                const gpr_thd_options* options) {
-  HANDLE handle;
-  struct thd_info* info = (struct thd_info*)gpr_malloc(sizeof(*info));
-  info->body = thd_body;
-  info->arg = arg;
-  *t = 0;
-  if (gpr_thd_options_is_joinable(options)) {
-    info->joinable = 1;
-    info->join_event = CreateEvent(NULL, FALSE, FALSE, NULL);
-    if (info->join_event == NULL) {
-      gpr_free(info);
-      return 0;
-    }
-  } else {
-    info->joinable = 0;
-  }
-  handle = CreateThread(NULL, 64 * 1024, thread_body, info, 0, NULL);
-  if (handle == NULL) {
-    destroy_thread(info);
-  } else {
-    *t = (gpr_thd_id)info;
-    CloseHandle(handle);
-  }
-  return handle != NULL;
-}
-
-gpr_thd_id gpr_thd_currentid(void) { return (gpr_thd_id)g_thd_info; }
-
-void gpr_thd_join(gpr_thd_id t) {
-  struct thd_info* info = (struct thd_info*)t;
-  DWORD ret = WaitForSingleObject(info->join_event, INFINITE);
-  GPR_ASSERT(ret == WAIT_OBJECT_0);
-  destroy_thread(info);
-}
-
-#endif /* GPR_WINDOWS */

+ 135 - 0
src/core/lib/gprpp/thd.h

@@ -0,0 +1,135 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#ifndef GRPC_CORE_LIB_GPRPP_THD_H
+#define GRPC_CORE_LIB_GPRPP_THD_H
+
+/** Internal thread interface. */
+
+#include <grpc/support/port_platform.h>
+
+#include <grpc/support/log.h>
+#include <grpc/support/sync.h>
+#include <grpc/support/thd_id.h>
+#include <grpc/support/time.h>
+
+#include "src/core/lib/gprpp/abstract.h"
+#include "src/core/lib/gprpp/memory.h"
+
+namespace grpc_core {
+namespace internal {
+
+/// Base class for platform-specific thread-state
+class ThreadInternalsInterface {
+ public:
+  virtual ~ThreadInternalsInterface() {}
+  virtual void Start() GRPC_ABSTRACT;
+  virtual void Join() GRPC_ABSTRACT;
+  GRPC_ABSTRACT_BASE_CLASS
+};
+
+}  // namespace internal
+
+class Thread {
+ public:
+  /// Default constructor only to allow use in structs that lack constructors
+  /// Does not produce a validly-constructed thread; must later
+  /// use placement new to construct a real thread. Does not init mu_ and cv_
+  Thread() : state_(FAKE), impl_(nullptr) {}
+
+  /// Normal constructor to create a thread with name \a thd_name,
+  /// which will execute a thread based on function \a thd_body
+  /// with argument \a arg once it is started.
+  /// The optional \a success argument indicates whether the thread
+  /// is successfully created.
+  Thread(const char* thd_name, void (*thd_body)(void* arg), void* arg,
+         bool* success = nullptr);
+
+  /// Move constructor for thread. After this is called, the other thread
+  /// no longer represents a living thread object
+  Thread(Thread&& other) : state_(other.state_), impl_(other.impl_) {
+    other.state_ = MOVED;
+    other.impl_ = nullptr;
+  }
+
+  /// Move assignment operator for thread. After this is called, the other
+  /// thread no longer represents a living thread object. Not allowed if this
+  /// thread actually exists
+  Thread& operator=(Thread&& other) {
+    if (this != &other) {
+      // TODO(vjpai): if we can be sure that all Thread's are actually
+      // constructed, then we should assert GPR_ASSERT(impl_ == nullptr) here.
+      // However, as long as threads come in structures that are
+      // allocated via gpr_malloc, this will not be the case, so we cannot
+      // assert it for the time being.
+      state_ = other.state_;
+      impl_ = other.impl_;
+      other.state_ = MOVED;
+      other.impl_ = nullptr;
+    }
+    return *this;
+  }
+
+  /// The destructor is strictly optional; either the thread never came to life
+  /// and the constructor itself killed it or it has already been joined and
+  /// the Join function kills it. The destructor shouldn't have to do anything.
+  ~Thread() { GPR_ASSERT(impl_ == nullptr); }
+
+  void Start() {
+    if (impl_ != nullptr) {
+      GPR_ASSERT(state_ == ALIVE);
+      state_ = STARTED;
+      impl_->Start();
+    } else {
+      GPR_ASSERT(state_ == FAILED);
+    }
+  };
+
+  void Join() {
+    if (impl_ != nullptr) {
+      impl_->Join();
+      grpc_core::Delete(impl_);
+      state_ = DONE;
+      impl_ = nullptr;
+    } else {
+      GPR_ASSERT(state_ == FAILED);
+    }
+  };
+
+  static void Init();
+  static bool AwaitAll(gpr_timespec deadline);
+
+ private:
+  Thread(const Thread&) = delete;
+  Thread& operator=(const Thread&) = delete;
+
+  /// The thread states are as follows:
+  /// FAKE -- just a dummy placeholder Thread created by the default constructor
+  /// ALIVE -- an actual thread of control exists associated with this thread
+  /// STARTED -- the thread of control has been started
+  /// DONE -- the thread of control has completed and been joined
+  /// FAILED -- the thread of control never came alive
+  /// MOVED -- contents were moved out and we're no longer tracking them
+  enum ThreadState { FAKE, ALIVE, STARTED, DONE, FAILED, MOVED };
+  ThreadState state_;
+  internal::ThreadInternalsInterface* impl_;
+};
+
+}  // namespace grpc_core
+
+#endif /* GRPC_CORE_LIB_GPRPP_THD_H */

+ 209 - 0
src/core/lib/gprpp/thd_posix.cc

@@ -0,0 +1,209 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+/* Posix implementation for gpr threads. */
+
+#include <grpc/support/port_platform.h>
+
+#ifdef GPR_POSIX_SYNC
+
+#include "src/core/lib/gprpp/thd.h"
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/sync.h>
+#include <grpc/support/thd_id.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "src/core/lib/gpr/fork.h"
+#include "src/core/lib/gpr/useful.h"
+#include "src/core/lib/gprpp/memory.h"
+
+namespace grpc_core {
+namespace {
+gpr_mu g_mu;
+gpr_cv g_cv;
+int g_thread_count;
+int g_awaiting_threads;
+
+class ThreadInternalsPosix;
+struct thd_arg {
+  ThreadInternalsPosix* thread;
+  void (*body)(void* arg); /* body of a thread */
+  void* arg;               /* argument to a thread */
+  const char* name;        /* name of thread. Can be nullptr. */
+};
+
+class ThreadInternalsPosix
+    : public grpc_core::internal::ThreadInternalsInterface {
+ public:
+  ThreadInternalsPosix(const char* thd_name, void (*thd_body)(void* arg),
+                       void* arg, bool* success)
+      : started_(false) {
+    gpr_mu_init(&mu_);
+    gpr_cv_init(&ready_);
+    pthread_attr_t attr;
+    /* don't use gpr_malloc as we may cause an infinite recursion with
+     * the profiling code */
+    thd_arg* info = static_cast<thd_arg*>(malloc(sizeof(*info)));
+    GPR_ASSERT(info != nullptr);
+    info->thread = this;
+    info->body = thd_body;
+    info->arg = arg;
+    info->name = thd_name;
+    inc_thd_count();
+
+    GPR_ASSERT(pthread_attr_init(&attr) == 0);
+    GPR_ASSERT(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE) ==
+               0);
+
+    *success =
+        (pthread_create(&pthread_id_, &attr,
+                        [](void* v) -> void* {
+                          thd_arg arg = *static_cast<thd_arg*>(v);
+                          free(v);
+                          if (arg.name != nullptr) {
+#if GPR_APPLE_PTHREAD_NAME
+                            /* Apple supports 64 characters, and will
+                             * truncate if it's longer. */
+                            pthread_setname_np(arg.name);
+#elif GPR_LINUX_PTHREAD_NAME
+                            /* Linux supports 16 characters max, and will
+                             * error if it's longer. */
+                            char buf[16];
+                            size_t buf_len = GPR_ARRAY_SIZE(buf) - 1;
+                            strncpy(buf, arg.name, buf_len);
+                            buf[buf_len] = '\0';
+                            pthread_setname_np(pthread_self(), buf);
+#endif  // GPR_APPLE_PTHREAD_NAME
+                          }
+
+                          gpr_mu_lock(&arg.thread->mu_);
+                          while (!arg.thread->started_) {
+                            gpr_cv_wait(&arg.thread->ready_, &arg.thread->mu_,
+                                        gpr_inf_future(GPR_CLOCK_MONOTONIC));
+                          }
+                          gpr_mu_unlock(&arg.thread->mu_);
+
+                          (*arg.body)(arg.arg);
+                          dec_thd_count();
+                          return nullptr;
+                        },
+                        info) == 0);
+
+    GPR_ASSERT(pthread_attr_destroy(&attr) == 0);
+
+    if (!success) {
+      /* don't use gpr_free, as this was allocated using malloc (see above) */
+      free(info);
+      dec_thd_count();
+    }
+  };
+
+  ~ThreadInternalsPosix() override {
+    gpr_mu_destroy(&mu_);
+    gpr_cv_destroy(&ready_);
+  }
+
+  void Start() override {
+    gpr_mu_lock(&mu_);
+    started_ = true;
+    gpr_cv_signal(&ready_);
+    gpr_mu_unlock(&mu_);
+  }
+
+  void Join() override { pthread_join(pthread_id_, nullptr); }
+
+ private:
+  /*****************************************
+   * Only used when fork support is enabled
+   */
+
+  static void inc_thd_count() {
+    if (grpc_fork_support_enabled()) {
+      gpr_mu_lock(&g_mu);
+      g_thread_count++;
+      gpr_mu_unlock(&g_mu);
+    }
+  }
+
+  static void dec_thd_count() {
+    if (grpc_fork_support_enabled()) {
+      gpr_mu_lock(&g_mu);
+      g_thread_count--;
+      if (g_awaiting_threads && g_thread_count == 0) {
+        gpr_cv_signal(&g_cv);
+      }
+      gpr_mu_unlock(&g_mu);
+    }
+  }
+
+  gpr_mu mu_;
+  gpr_cv ready_;
+  bool started_;
+  pthread_t pthread_id_;
+};
+
+}  // namespace
+
+Thread::Thread(const char* thd_name, void (*thd_body)(void* arg), void* arg,
+               bool* success) {
+  bool outcome = false;
+  impl_ =
+      grpc_core::New<ThreadInternalsPosix>(thd_name, thd_body, arg, &outcome);
+  if (outcome) {
+    state_ = ALIVE;
+  } else {
+    state_ = FAILED;
+    grpc_core::Delete(impl_);
+    impl_ = nullptr;
+  }
+
+  if (success != nullptr) {
+    *success = outcome;
+  }
+}
+
+void Thread::Init() {
+  gpr_mu_init(&g_mu);
+  gpr_cv_init(&g_cv);
+  g_thread_count = 0;
+  g_awaiting_threads = 0;
+}
+
+bool Thread::AwaitAll(gpr_timespec deadline) {
+  gpr_mu_lock(&g_mu);
+  g_awaiting_threads = 1;
+  int res = 0;
+  while ((g_thread_count > 0) &&
+         (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0)) {
+    res = gpr_cv_wait(&g_cv, &g_mu, deadline);
+  }
+  g_awaiting_threads = 0;
+  gpr_mu_unlock(&g_mu);
+  return res == 0;
+}
+
+}  // namespace grpc_core
+
+// The following is in the external namespace as it is exposed as C89 API
+gpr_thd_id gpr_thd_currentid(void) { return (gpr_thd_id)pthread_self(); }
+
+#endif /* GPR_POSIX_SYNC */

+ 162 - 0
src/core/lib/gprpp/thd_windows.cc

@@ -0,0 +1,162 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+/* Windows implementation for gpr threads. */
+
+#include <grpc/support/port_platform.h>
+
+#ifdef GPR_WINDOWS
+
+#include "src/core/lib/gprpp/thd.h"
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/thd_id.h>
+#include <string.h>
+
+#include "src/core/lib/gprpp/memory.h"
+
+#if defined(_MSC_VER)
+#define thread_local __declspec(thread)
+#define WIN_LAMBDA
+#elif defined(__GNUC__)
+#define thread_local __thread
+#define WIN_LAMBDA WINAPI
+#else
+#error "Unknown compiler - please file a bug report"
+#endif
+
+namespace {
+class ThreadInternalsWindows;
+struct thd_info {
+  ThreadInternalsWindows* thread;
+  void (*body)(void* arg); /* body of a thread */
+  void* arg;               /* argument to a thread */
+  HANDLE join_event;       /* the join event */
+};
+
+thread_local struct thd_info* g_thd_info;
+
+class ThreadInternalsWindows
+    : public grpc_core::internal::ThreadInternalsInterface {
+ public:
+  ThreadInternalsWindows(void (*thd_body)(void* arg), void* arg, bool* success)
+      : started_(false) {
+    gpr_mu_init(&mu_);
+    gpr_cv_init(&ready_);
+
+    HANDLE handle;
+    info_ = (struct thd_info*)gpr_malloc(sizeof(*info_));
+    info_->thread = this;
+    info_->body = thd_body;
+    info_->arg = arg;
+
+    info_->join_event = CreateEvent(nullptr, FALSE, FALSE, nullptr);
+    if (info_->join_event == nullptr) {
+      gpr_free(info_);
+      *success = false;
+    } else {
+      handle = CreateThread(
+          nullptr, 64 * 1024,
+          [](void* v) WIN_LAMBDA -> DWORD {
+            g_thd_info = static_cast<thd_info*>(v);
+            gpr_mu_lock(&g_thd_info->thread->mu_);
+            while (!g_thd_info->thread->started_) {
+              gpr_cv_wait(&g_thd_info->thread->ready_, &g_thd_info->thread->mu_,
+                          gpr_inf_future(GPR_CLOCK_MONOTONIC));
+            }
+            gpr_mu_unlock(&g_thd_info->thread->mu_);
+            g_thd_info->body(g_thd_info->arg);
+            BOOL ret = SetEvent(g_thd_info->join_event);
+            GPR_ASSERT(ret);
+            return 0;
+          },
+          info_, 0, nullptr);
+      if (handle == nullptr) {
+        destroy_thread();
+        *success = false;
+      } else {
+        CloseHandle(handle);
+        *success = true;
+      }
+    }
+  }
+
+  ~ThreadInternalsWindows() override {
+    gpr_mu_destroy(&mu_);
+    gpr_cv_destroy(&ready_);
+  }
+
+  void Start() override {
+    gpr_mu_lock(&mu_);
+    started_ = true;
+    gpr_cv_signal(&ready_);
+    gpr_mu_unlock(&mu_);
+  }
+
+  void Join() override {
+    DWORD ret = WaitForSingleObject(info_->join_event, INFINITE);
+    GPR_ASSERT(ret == WAIT_OBJECT_0);
+    destroy_thread();
+  }
+
+ private:
+  void destroy_thread() {
+    CloseHandle(info_->join_event);
+    gpr_free(info_);
+  }
+
+  gpr_mu mu_;
+  gpr_cv ready_;
+  bool started_;
+  thd_info* info_;
+};
+
+}  // namespace
+
+namespace grpc_core {
+
+void Thread::Init() {}
+
+bool Thread::AwaitAll(gpr_timespec deadline) {
+  // TODO: Consider adding this if needed
+  return false;
+}
+
+Thread::Thread(const char* thd_name, void (*thd_body)(void* arg), void* arg,
+               bool* success) {
+  bool outcome = false;
+  impl_ = grpc_core::New<ThreadInternalsWindows>(thd_body, arg, &outcome);
+  if (outcome) {
+    state_ = ALIVE;
+  } else {
+    state_ = FAILED;
+    grpc_core::Delete(impl_);
+    impl_ = nullptr;
+  }
+
+  if (success != nullptr) {
+    *success = outcome;
+  }
+}
+
+}  // namespace grpc_core
+
+gpr_thd_id gpr_thd_currentid(void) { return (gpr_thd_id)g_thd_info; }
+
+#endif /* GPR_WINDOWS */

+ 57 - 9
src/core/lib/iomgr/ev_poll_posix.cc

@@ -38,9 +38,9 @@
 
 
 #include "src/core/lib/debug/stats.h"
 #include "src/core/lib/debug/stats.h"
 #include "src/core/lib/gpr/murmur_hash.h"
 #include "src/core/lib/gpr/murmur_hash.h"
-#include "src/core/lib/gpr/thd.h"
 #include "src/core/lib/gpr/tls.h"
 #include "src/core/lib/gpr/tls.h"
 #include "src/core/lib/gpr/useful.h"
 #include "src/core/lib/gpr/useful.h"
+#include "src/core/lib/gprpp/thd.h"
 #include "src/core/lib/iomgr/block_annotate.h"
 #include "src/core/lib/iomgr/block_annotate.h"
 #include "src/core/lib/iomgr/iomgr_internal.h"
 #include "src/core/lib/iomgr/iomgr_internal.h"
 #include "src/core/lib/iomgr/wakeup_fd_cv.h"
 #include "src/core/lib/iomgr/wakeup_fd_cv.h"
@@ -255,8 +255,13 @@ typedef struct poll_result {
 } poll_result;
 } poll_result;
 
 
 typedef struct poll_args {
 typedef struct poll_args {
+  grpc_core::Thread poller_thd;
   gpr_cv trigger;
   gpr_cv trigger;
   int trigger_set;
   int trigger_set;
+  bool harvestable;
+  gpr_cv harvest;
+  bool joinable;
+  gpr_cv join;
   struct pollfd* fds;
   struct pollfd* fds;
   nfds_t nfds;
   nfds_t nfds;
   poll_result* result;
   poll_result* result;
@@ -266,15 +271,17 @@ typedef struct poll_args {
 
 
 // This is a 2-tiered cache, we mantain a hash table
 // This is a 2-tiered cache, we mantain a hash table
 // of active poll calls, so we can wait on the result
 // of active poll calls, so we can wait on the result
-// of that call.  We also maintain a freelist of inactive
-// poll threads.
+// of that call.  We also maintain freelists of inactive
+// poll args and of dead poller threads.
 typedef struct poll_hash_table {
 typedef struct poll_hash_table {
   poll_args* free_pollers;
   poll_args* free_pollers;
   poll_args** active_pollers;
   poll_args** active_pollers;
+  poll_args* dead_pollers;
   unsigned int size;
   unsigned int size;
   unsigned int count;
   unsigned int count;
 } poll_hash_table;
 } poll_hash_table;
 
 
+// TODO(kpayson64): Eliminate use of global non-POD variables
 poll_hash_table poll_cache;
 poll_hash_table poll_cache;
 grpc_cv_fd_table g_cvfds;
 grpc_cv_fd_table g_cvfds;
 
 
@@ -1301,6 +1308,7 @@ static void pollset_set_del_fd(grpc_pollset_set* pollset_set, grpc_fd* fd) {
 
 
 static void run_poll(void* args);
 static void run_poll(void* args);
 static void cache_poller_locked(poll_args* args);
 static void cache_poller_locked(poll_args* args);
+static void cache_harvest_locked();
 
 
 static void cache_insert_locked(poll_args* args) {
 static void cache_insert_locked(poll_args* args) {
   uint32_t key = gpr_murmur_hash3(args->fds, args->nfds * sizeof(struct pollfd),
   uint32_t key = gpr_murmur_hash3(args->fds, args->nfds * sizeof(struct pollfd),
@@ -1363,6 +1371,10 @@ static poll_args* get_poller_locked(struct pollfd* fds, nfds_t count) {
   poll_args* pargs =
   poll_args* pargs =
       static_cast<poll_args*>(gpr_malloc(sizeof(struct poll_args)));
       static_cast<poll_args*>(gpr_malloc(sizeof(struct poll_args)));
   gpr_cv_init(&pargs->trigger);
   gpr_cv_init(&pargs->trigger);
+  gpr_cv_init(&pargs->harvest);
+  gpr_cv_init(&pargs->join);
+  pargs->harvestable = false;
+  pargs->joinable = false;
   pargs->fds = fds;
   pargs->fds = fds;
   pargs->nfds = count;
   pargs->nfds = count;
   pargs->next = nullptr;
   pargs->next = nullptr;
@@ -1370,11 +1382,9 @@ static poll_args* get_poller_locked(struct pollfd* fds, nfds_t count) {
   pargs->trigger_set = 0;
   pargs->trigger_set = 0;
   init_result(pargs);
   init_result(pargs);
   cache_poller_locked(pargs);
   cache_poller_locked(pargs);
-  gpr_thd_id t_id;
-  gpr_thd_options opt = gpr_thd_options_default();
   gpr_ref(&g_cvfds.pollcount);
   gpr_ref(&g_cvfds.pollcount);
-  gpr_thd_options_set_detached(&opt);
-  GPR_ASSERT(gpr_thd_new(&t_id, "grpc_poller", &run_poll, pargs, &opt));
+  pargs->poller_thd = grpc_core::Thread("grpc_poller", &run_poll, pargs);
+  pargs->poller_thd.Start();
   return pargs;
   return pargs;
 }
 }
 
 
@@ -1439,7 +1449,33 @@ static void cache_destroy_locked(poll_args* args) {
     poll_cache.free_pollers = args->next;
     poll_cache.free_pollers = args->next;
   }
   }
 
 
-  gpr_free(args);
+  // Now move this args to the dead poller list for later join
+  if (poll_cache.dead_pollers != nullptr) {
+    poll_cache.dead_pollers->prev = args;
+  }
+  args->prev = nullptr;
+  args->next = poll_cache.dead_pollers;
+  poll_cache.dead_pollers = args;
+}
+
+static void cache_harvest_locked() {
+  while (poll_cache.dead_pollers) {
+    poll_args* args = poll_cache.dead_pollers;
+    poll_cache.dead_pollers = poll_cache.dead_pollers->next;
+    // Keep the list consistent in case new dead pollers get added when we
+    // release the lock below to wait on joining
+    if (poll_cache.dead_pollers) {
+      poll_cache.dead_pollers->prev = nullptr;
+    }
+    args->harvestable = true;
+    gpr_cv_signal(&args->harvest);
+    while (!args->joinable) {
+      gpr_cv_wait(&args->join, &g_cvfds.mu,
+                  gpr_inf_future(GPR_CLOCK_MONOTONIC));
+    }
+    args->poller_thd.Join();
+    gpr_free(args);
+  }
 }
 }
 
 
 static void decref_poll_result(poll_result* res) {
 static void decref_poll_result(poll_result* res) {
@@ -1471,6 +1507,7 @@ static void run_poll(void* args) {
     poll_result* result = pargs->result;
     poll_result* result = pargs->result;
     int retval = g_cvfds.poll(result->fds, result->nfds, CV_POLL_PERIOD_MS);
     int retval = g_cvfds.poll(result->fds, result->nfds, CV_POLL_PERIOD_MS);
     gpr_mu_lock(&g_cvfds.mu);
     gpr_mu_lock(&g_cvfds.mu);
+    cache_harvest_locked();
     if (retval != 0) {
     if (retval != 0) {
       result->completed = 1;
       result->completed = 1;
       result->retval = retval;
       result->retval = retval;
@@ -1490,6 +1527,7 @@ static void run_poll(void* args) {
       deadline = gpr_time_add(deadline, thread_grace);
       deadline = gpr_time_add(deadline, thread_grace);
       pargs->trigger_set = 0;
       pargs->trigger_set = 0;
       gpr_cv_wait(&pargs->trigger, &g_cvfds.mu, deadline);
       gpr_cv_wait(&pargs->trigger, &g_cvfds.mu, deadline);
+      cache_harvest_locked();
       if (!pargs->trigger_set) {
       if (!pargs->trigger_set) {
         cache_destroy_locked(pargs);
         cache_destroy_locked(pargs);
         break;
         break;
@@ -1498,10 +1536,15 @@ static void run_poll(void* args) {
     gpr_mu_unlock(&g_cvfds.mu);
     gpr_mu_unlock(&g_cvfds.mu);
   }
   }
 
 
-  // We still have the lock here
   if (gpr_unref(&g_cvfds.pollcount)) {
   if (gpr_unref(&g_cvfds.pollcount)) {
     gpr_cv_signal(&g_cvfds.shutdown_cv);
     gpr_cv_signal(&g_cvfds.shutdown_cv);
   }
   }
+  while (!pargs->harvestable) {
+    gpr_cv_wait(&pargs->harvest, &g_cvfds.mu,
+                gpr_inf_future(GPR_CLOCK_MONOTONIC));
+  }
+  pargs->joinable = true;
+  gpr_cv_signal(&pargs->join);
   gpr_mu_unlock(&g_cvfds.mu);
   gpr_mu_unlock(&g_cvfds.mu);
 }
 }
 
 
@@ -1514,6 +1557,7 @@ static int cvfd_poll(struct pollfd* fds, nfds_t nfds, int timeout) {
   nfds_t nsockfds = 0;
   nfds_t nsockfds = 0;
   poll_result* result = nullptr;
   poll_result* result = nullptr;
   gpr_mu_lock(&g_cvfds.mu);
   gpr_mu_lock(&g_cvfds.mu);
+  cache_harvest_locked();
   pollcv = static_cast<grpc_cv_node*>(gpr_malloc(sizeof(grpc_cv_node)));
   pollcv = static_cast<grpc_cv_node*>(gpr_malloc(sizeof(grpc_cv_node)));
   pollcv->next = nullptr;
   pollcv->next = nullptr;
   gpr_cv pollcv_cv;
   gpr_cv pollcv_cv;
@@ -1577,12 +1621,14 @@ static int cvfd_poll(struct pollfd* fds, nfds_t nfds, int timeout) {
     pargs->trigger_set = 1;
     pargs->trigger_set = 1;
     gpr_cv_signal(&pargs->trigger);
     gpr_cv_signal(&pargs->trigger);
     gpr_cv_wait(&pollcv_cv, &g_cvfds.mu, deadline);
     gpr_cv_wait(&pollcv_cv, &g_cvfds.mu, deadline);
+    cache_harvest_locked();
     res = result->retval;
     res = result->retval;
     errno = result->err;
     errno = result->err;
     result->watchcount--;
     result->watchcount--;
     remove_cvn(&result->watchers, pollcv);
     remove_cvn(&result->watchers, pollcv);
   } else if (!skip_poll) {
   } else if (!skip_poll) {
     gpr_cv_wait(&pollcv_cv, &g_cvfds.mu, deadline);
     gpr_cv_wait(&pollcv_cv, &g_cvfds.mu, deadline);
+    cache_harvest_locked();
   }
   }
 
 
   idx = 0;
   idx = 0;
@@ -1639,6 +1685,7 @@ static void global_cv_fd_table_init() {
   for (unsigned int i = 0; i < poll_cache.size; i++) {
   for (unsigned int i = 0; i < poll_cache.size; i++) {
     poll_cache.active_pollers[i] = nullptr;
     poll_cache.active_pollers[i] = nullptr;
   }
   }
+  poll_cache.dead_pollers = nullptr;
 
 
   gpr_mu_unlock(&g_cvfds.mu);
   gpr_mu_unlock(&g_cvfds.mu);
 }
 }
@@ -1657,6 +1704,7 @@ static void global_cv_fd_table_shutdown() {
   grpc_poll_function = g_cvfds.poll;
   grpc_poll_function = g_cvfds.poll;
   gpr_free(g_cvfds.cvfds);
   gpr_free(g_cvfds.cvfds);
 
 
+  cache_harvest_locked();
   gpr_free(poll_cache.active_pollers);
   gpr_free(poll_cache.active_pollers);
 
 
   gpr_mu_unlock(&g_cvfds.mu);
   gpr_mu_unlock(&g_cvfds.mu);

+ 1 - 1
src/core/lib/iomgr/exec_ctx.cc

@@ -23,7 +23,7 @@
 #include <grpc/support/log.h>
 #include <grpc/support/log.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/sync.h>
 
 
-#include "src/core/lib/gpr/thd.h"
+#include "src/core/lib/gprpp/thd.h"
 #include "src/core/lib/iomgr/combiner.h"
 #include "src/core/lib/iomgr/combiner.h"
 #include "src/core/lib/profiling/timers.h"
 #include "src/core/lib/profiling/timers.h"
 
 

+ 11 - 11
src/core/lib/iomgr/executor.cc

@@ -29,9 +29,9 @@
 
 
 #include "src/core/lib/debug/stats.h"
 #include "src/core/lib/debug/stats.h"
 #include "src/core/lib/gpr/spinlock.h"
 #include "src/core/lib/gpr/spinlock.h"
-#include "src/core/lib/gpr/thd.h"
 #include "src/core/lib/gpr/tls.h"
 #include "src/core/lib/gpr/tls.h"
 #include "src/core/lib/gpr/useful.h"
 #include "src/core/lib/gpr/useful.h"
+#include "src/core/lib/gprpp/thd.h"
 #include "src/core/lib/iomgr/exec_ctx.h"
 #include "src/core/lib/iomgr/exec_ctx.h"
 
 
 #define MAX_DEPTH 2
 #define MAX_DEPTH 2
@@ -43,7 +43,7 @@ typedef struct {
   size_t depth;
   size_t depth;
   bool shutdown;
   bool shutdown;
   bool queued_long_job;
   bool queued_long_job;
-  gpr_thd_id id;
+  grpc_core::Thread thd;
 } thread_state;
 } thread_state;
 
 
 static thread_state* g_thread_state;
 static thread_state* g_thread_state;
@@ -101,13 +101,13 @@ void grpc_executor_set_threading(bool threading) {
     for (size_t i = 0; i < g_max_threads; i++) {
     for (size_t i = 0; i < g_max_threads; i++) {
       gpr_mu_init(&g_thread_state[i].mu);
       gpr_mu_init(&g_thread_state[i].mu);
       gpr_cv_init(&g_thread_state[i].cv);
       gpr_cv_init(&g_thread_state[i].cv);
+      g_thread_state[i].thd = grpc_core::Thread();
       g_thread_state[i].elems = GRPC_CLOSURE_LIST_INIT;
       g_thread_state[i].elems = GRPC_CLOSURE_LIST_INIT;
     }
     }
 
 
-    gpr_thd_options opt = gpr_thd_options_default();
-    gpr_thd_options_set_joinable(&opt);
-    gpr_thd_new(&g_thread_state[0].id, "grpc_executor", executor_thread,
-                &g_thread_state[0], &opt);
+    g_thread_state[0].thd =
+        grpc_core::Thread("grpc_executor", executor_thread, &g_thread_state[0]);
+    g_thread_state[0].thd.Start();
   } else {
   } else {
     if (cur_threads == 0) return;
     if (cur_threads == 0) return;
     for (size_t i = 0; i < g_max_threads; i++) {
     for (size_t i = 0; i < g_max_threads; i++) {
@@ -121,7 +121,7 @@ void grpc_executor_set_threading(bool threading) {
     gpr_spinlock_lock(&g_adding_thread_lock);
     gpr_spinlock_lock(&g_adding_thread_lock);
     gpr_spinlock_unlock(&g_adding_thread_lock);
     gpr_spinlock_unlock(&g_adding_thread_lock);
     for (gpr_atm i = 0; i < g_cur_threads; i++) {
     for (gpr_atm i = 0; i < g_cur_threads; i++) {
-      gpr_thd_join(g_thread_state[i].id);
+      g_thread_state[i].thd.Join();
     }
     }
     gpr_atm_no_barrier_store(&g_cur_threads, 0);
     gpr_atm_no_barrier_store(&g_cur_threads, 0);
     for (size_t i = 0; i < g_max_threads; i++) {
     for (size_t i = 0; i < g_max_threads; i++) {
@@ -264,10 +264,10 @@ static void executor_push(grpc_closure* closure, grpc_error* error,
       if (cur_thread_count < g_max_threads) {
       if (cur_thread_count < g_max_threads) {
         gpr_atm_no_barrier_store(&g_cur_threads, cur_thread_count + 1);
         gpr_atm_no_barrier_store(&g_cur_threads, cur_thread_count + 1);
 
 
-        gpr_thd_options opt = gpr_thd_options_default();
-        gpr_thd_options_set_joinable(&opt);
-        gpr_thd_new(&g_thread_state[cur_thread_count].id, "gpr_executor",
-                    executor_thread, &g_thread_state[cur_thread_count], &opt);
+        g_thread_state[cur_thread_count].thd =
+            grpc_core::Thread("grpc_executor", executor_thread,
+                              &g_thread_state[cur_thread_count]);
+        g_thread_state[cur_thread_count].thd.Start();
       }
       }
       gpr_spinlock_unlock(&g_adding_thread_lock);
       gpr_spinlock_unlock(&g_adding_thread_lock);
     }
     }

+ 2 - 2
src/core/lib/iomgr/fork_posix.cc

@@ -29,7 +29,7 @@
 
 
 #include "src/core/lib/gpr/env.h"
 #include "src/core/lib/gpr/env.h"
 #include "src/core/lib/gpr/fork.h"
 #include "src/core/lib/gpr/fork.h"
-#include "src/core/lib/gpr/thd.h"
+#include "src/core/lib/gprpp/thd.h"
 #include "src/core/lib/iomgr/ev_posix.h"
 #include "src/core/lib/iomgr/ev_posix.h"
 #include "src/core/lib/iomgr/executor.h"
 #include "src/core/lib/iomgr/executor.h"
 #include "src/core/lib/iomgr/timer_manager.h"
 #include "src/core/lib/iomgr/timer_manager.h"
@@ -53,7 +53,7 @@ void grpc_prefork() {
     grpc_timer_manager_set_threading(false);
     grpc_timer_manager_set_threading(false);
     grpc_executor_set_threading(false);
     grpc_executor_set_threading(false);
     grpc_core::ExecCtx::Get()->Flush();
     grpc_core::ExecCtx::Get()->Flush();
-    if (!gpr_await_threads(
+    if (!grpc_core::Thread::AwaitAll(
             gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
             gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
                          gpr_time_from_seconds(3, GPR_TIMESPAN)))) {
                          gpr_time_from_seconds(3, GPR_TIMESPAN)))) {
       gpr_log(GPR_ERROR, "gRPC thread still active! Cannot fork!");
       gpr_log(GPR_ERROR, "gRPC thread still active! Cannot fork!");

+ 1 - 1
src/core/lib/iomgr/iocp_windows.cc

@@ -30,7 +30,7 @@
 #include <grpc/support/log_windows.h>
 #include <grpc/support/log_windows.h>
 
 
 #include "src/core/lib/debug/stats.h"
 #include "src/core/lib/debug/stats.h"
-#include "src/core/lib/gpr/thd.h"
+#include "src/core/lib/gprpp/thd.h"
 #include "src/core/lib/iomgr/iocp_windows.h"
 #include "src/core/lib/iomgr/iocp_windows.h"
 #include "src/core/lib/iomgr/iomgr_internal.h"
 #include "src/core/lib/iomgr/iomgr_internal.h"
 #include "src/core/lib/iomgr/socket_windows.h"
 #include "src/core/lib/iomgr/socket_windows.h"

+ 1 - 1
src/core/lib/iomgr/iomgr.cc

@@ -31,8 +31,8 @@
 
 
 #include "src/core/lib/gpr/env.h"
 #include "src/core/lib/gpr/env.h"
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gpr/string.h"
-#include "src/core/lib/gpr/thd.h"
 #include "src/core/lib/gpr/useful.h"
 #include "src/core/lib/gpr/useful.h"
+#include "src/core/lib/gprpp/thd.h"
 #include "src/core/lib/iomgr/exec_ctx.h"
 #include "src/core/lib/iomgr/exec_ctx.h"
 #include "src/core/lib/iomgr/executor.h"
 #include "src/core/lib/iomgr/executor.h"
 #include "src/core/lib/iomgr/iomgr_internal.h"
 #include "src/core/lib/iomgr/iomgr_internal.h"

+ 1 - 1
src/core/lib/iomgr/pollset_windows.cc

@@ -24,7 +24,7 @@
 
 
 #include <grpc/support/log.h>
 #include <grpc/support/log.h>
 
 
-#include "src/core/lib/gpr/thd.h"
+#include "src/core/lib/gprpp/thd.h"
 #include "src/core/lib/iomgr/iocp_windows.h"
 #include "src/core/lib/iomgr/iocp_windows.h"
 #include "src/core/lib/iomgr/iomgr_internal.h"
 #include "src/core/lib/iomgr/iomgr_internal.h"
 #include "src/core/lib/iomgr/pollset.h"
 #include "src/core/lib/iomgr/pollset.h"

+ 1 - 1
src/core/lib/iomgr/resolve_address_posix.cc

@@ -35,8 +35,8 @@
 
 
 #include "src/core/lib/gpr/host_port.h"
 #include "src/core/lib/gpr/host_port.h"
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gpr/string.h"
-#include "src/core/lib/gpr/thd.h"
 #include "src/core/lib/gpr/useful.h"
 #include "src/core/lib/gpr/useful.h"
+#include "src/core/lib/gprpp/thd.h"
 #include "src/core/lib/iomgr/block_annotate.h"
 #include "src/core/lib/iomgr/block_annotate.h"
 #include "src/core/lib/iomgr/executor.h"
 #include "src/core/lib/iomgr/executor.h"
 #include "src/core/lib/iomgr/iomgr_internal.h"
 #include "src/core/lib/iomgr/iomgr_internal.h"

+ 1 - 1
src/core/lib/iomgr/resolve_address_windows.cc

@@ -37,7 +37,7 @@
 
 
 #include "src/core/lib/gpr/host_port.h"
 #include "src/core/lib/gpr/host_port.h"
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gpr/string.h"
-#include "src/core/lib/gpr/thd.h"
+#include "src/core/lib/gprpp/thd.h"
 #include "src/core/lib/iomgr/block_annotate.h"
 #include "src/core/lib/iomgr/block_annotate.h"
 #include "src/core/lib/iomgr/executor.h"
 #include "src/core/lib/iomgr/executor.h"
 #include "src/core/lib/iomgr/iomgr_internal.h"
 #include "src/core/lib/iomgr/iomgr_internal.h"

+ 10 - 19
src/core/lib/iomgr/timer_manager.cc

@@ -18,21 +18,20 @@
 
 
 #include <grpc/support/port_platform.h>
 #include <grpc/support/port_platform.h>
 
 
-#include "src/core/lib/iomgr/timer_manager.h"
+#include <inttypes.h>
 
 
 #include <grpc/support/alloc.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/log.h>
 
 
-#include <inttypes.h>
-
 #include "src/core/lib/debug/trace.h"
 #include "src/core/lib/debug/trace.h"
-#include "src/core/lib/gpr/thd.h"
+#include "src/core/lib/gprpp/thd.h"
 #include "src/core/lib/iomgr/timer.h"
 #include "src/core/lib/iomgr/timer.h"
+#include "src/core/lib/iomgr/timer_manager.h"
 
 
-typedef struct completed_thread {
-  gpr_thd_id t;
-  struct completed_thread* next;
-} completed_thread;
+struct completed_thread {
+  grpc_core::Thread thd;
+  completed_thread* next;
+};
 
 
 extern grpc_core::TraceFlag grpc_timer_check_trace;
 extern grpc_core::TraceFlag grpc_timer_check_trace;
 
 
@@ -68,7 +67,7 @@ static void gc_completed_threads(void) {
     g_completed_threads = nullptr;
     g_completed_threads = nullptr;
     gpr_mu_unlock(&g_mu);
     gpr_mu_unlock(&g_mu);
     while (to_gc != nullptr) {
     while (to_gc != nullptr) {
-      gpr_thd_join(to_gc->t);
+      to_gc->thd.Join();
       completed_thread* next = to_gc->next;
       completed_thread* next = to_gc->next;
       gpr_free(to_gc);
       gpr_free(to_gc);
       to_gc = next;
       to_gc = next;
@@ -85,18 +84,10 @@ static void start_timer_thread_and_unlock(void) {
   if (grpc_timer_check_trace.enabled()) {
   if (grpc_timer_check_trace.enabled()) {
     gpr_log(GPR_DEBUG, "Spawn timer thread");
     gpr_log(GPR_DEBUG, "Spawn timer thread");
   }
   }
-  gpr_thd_options opt = gpr_thd_options_default();
-  gpr_thd_options_set_joinable(&opt);
   completed_thread* ct =
   completed_thread* ct =
       static_cast<completed_thread*>(gpr_malloc(sizeof(*ct)));
       static_cast<completed_thread*>(gpr_malloc(sizeof(*ct)));
-  // The call to gpr_thd_new() has to be under the same lock used by
-  // gc_completed_threads(), particularly due to ct->t, which is written here
-  // (internally by gpr_thd_new) and read there. Otherwise it's possible for ct
-  // to leak through g_completed_threads and be freed in gc_completed_threads()
-  // before "&ct->t" is written to, causing a use-after-free.
-  gpr_mu_lock(&g_mu);
-  gpr_thd_new(&ct->t, "grpc_global_timer", timer_thread, ct, &opt);
-  gpr_mu_unlock(&g_mu);
+  ct->thd = grpc_core::Thread("grpc_global_timer", timer_thread, ct);
+  ct->thd.Start();
 }
 }
 
 
 void grpc_timer_manager_tick() {
 void grpc_timer_manager_tick() {

+ 1 - 1
src/core/lib/iomgr/wakeup_fd_cv.cc

@@ -32,8 +32,8 @@
 #include <grpc/support/sync.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/time.h>
 #include <grpc/support/time.h>
 
 
-#include "src/core/lib/gpr/thd.h"
 #include "src/core/lib/gpr/useful.h"
 #include "src/core/lib/gpr/useful.h"
+#include "src/core/lib/gprpp/thd.h"
 
 
 #define MAX_TABLE_RESIZE 256
 #define MAX_TABLE_RESIZE 256
 
 

+ 6 - 7
src/core/lib/profiling/basic_timers.cc

@@ -30,7 +30,7 @@
 #include <string.h>
 #include <string.h>
 
 
 #include "src/core/lib/gpr/env.h"
 #include "src/core/lib/gpr/env.h"
-#include "src/core/lib/gpr/thd.h"
+#include "src/core/lib/gprpp/thd.h"
 
 
 typedef enum { BEGIN = '{', END = '}', MARK = '.' } marker_type;
 typedef enum { BEGIN = '{', END = '}', MARK = '.' } marker_type;
 
 
@@ -68,7 +68,7 @@ static pthread_cond_t g_cv;
 static gpr_timer_log_list g_in_progress_logs;
 static gpr_timer_log_list g_in_progress_logs;
 static gpr_timer_log_list g_done_logs;
 static gpr_timer_log_list g_done_logs;
 static int g_shutdown;
 static int g_shutdown;
-static gpr_thd_id g_writing_thread;
+static grpc_core::Thread* g_writing_thread;
 static __thread int g_thread_id;
 static __thread int g_thread_id;
 static int g_next_thread_id;
 static int g_next_thread_id;
 static int g_writing_enabled = 1;
 static int g_writing_enabled = 1;
@@ -182,7 +182,8 @@ static void finish_writing(void) {
   g_shutdown = 1;
   g_shutdown = 1;
   pthread_cond_signal(&g_cv);
   pthread_cond_signal(&g_cv);
   pthread_mutex_unlock(&g_mu);
   pthread_mutex_unlock(&g_mu);
-  gpr_thd_join(g_writing_thread);
+  g_writing_thread->Join();
+  grpc_core::Delete(g_writing_thread);
 
 
   gpr_log(GPR_INFO, "flushing logs");
   gpr_log(GPR_INFO, "flushing logs");
 
 
@@ -201,10 +202,8 @@ void gpr_timers_set_log_filename(const char* filename) {
 }
 }
 
 
 static void init_output() {
 static void init_output() {
-  gpr_thd_options options = gpr_thd_options_default();
-  gpr_thd_options_set_joinable(&options);
-  GPR_ASSERT(gpr_thd_new(&g_writing_thread, "timer_output_thread",
-                         writing_thread, NULL, &options));
+  g_writing_thread = grpc_core::New<grpc_core::Thread>("timer_output_thread",
+                                                       writing_thread, nullptr);
   atexit(finish_writing);
   atexit(finish_writing);
 }
 }
 
 

+ 2 - 2
src/core/lib/surface/init.cc

@@ -33,7 +33,7 @@
 #include "src/core/lib/debug/stats.h"
 #include "src/core/lib/debug/stats.h"
 #include "src/core/lib/debug/trace.h"
 #include "src/core/lib/debug/trace.h"
 #include "src/core/lib/gpr/fork.h"
 #include "src/core/lib/gpr/fork.h"
-#include "src/core/lib/gpr/thd.h"
+#include "src/core/lib/gprpp/thd.h"
 #include "src/core/lib/http/parser.h"
 #include "src/core/lib/http/parser.h"
 #include "src/core/lib/iomgr/call_combiner.h"
 #include "src/core/lib/iomgr/call_combiner.h"
 #include "src/core/lib/iomgr/combiner.h"
 #include "src/core/lib/iomgr/combiner.h"
@@ -124,7 +124,7 @@ void grpc_init(void) {
   gpr_mu_lock(&g_init_mu);
   gpr_mu_lock(&g_init_mu);
   if (++g_initializations == 1) {
   if (++g_initializations == 1) {
     gpr_time_init();
     gpr_time_init();
-    gpr_thd_init();
+    grpc_core::Thread::Init();
     grpc_stats_init();
     grpc_stats_init();
     grpc_slice_intern_init();
     grpc_slice_intern_init();
     grpc_mdctx_global_init();
     grpc_mdctx_global_init();

+ 1 - 1
src/core/tsi/alts_transport_security.cc

@@ -56,7 +56,7 @@ void grpc_tsi_alts_shutdown() {
     grpc_tsi_alts_wait_for_cq_drain();
     grpc_tsi_alts_wait_for_cq_drain();
     grpc_completion_queue_destroy(g_alts_resource.cq);
     grpc_completion_queue_destroy(g_alts_resource.cq);
     grpc_channel_destroy(g_alts_resource.channel);
     grpc_channel_destroy(g_alts_resource.channel);
-    gpr_thd_join(g_alts_resource.thread_id);
+    g_alts_resource.thread.Join();
   }
   }
   gpr_cv_destroy(&g_alts_resource.cv);
   gpr_cv_destroy(&g_alts_resource.cv);
   gpr_mu_destroy(&g_alts_resource.mu);
   gpr_mu_destroy(&g_alts_resource.mu);

+ 2 - 2
src/core/tsi/alts_transport_security.h

@@ -24,10 +24,10 @@
 #include <grpc/grpc.h>
 #include <grpc/grpc.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/sync.h>
 
 
-#include "src/core/lib/gpr/thd.h"
+#include "src/core/lib/gprpp/thd.h"
 
 
 typedef struct alts_shared_resource {
 typedef struct alts_shared_resource {
-  gpr_thd_id thread_id;
+  grpc_core::Thread thread;
   grpc_channel* channel;
   grpc_channel* channel;
   grpc_completion_queue* cq;
   grpc_completion_queue* cq;
   gpr_mu mu;
   gpr_mu mu;

+ 1 - 1
src/cpp/client/channel_cc.cc

@@ -42,7 +42,7 @@
 #include <grpcpp/support/time.h>
 #include <grpcpp/support/time.h>
 #include "src/core/lib/gpr/env.h"
 #include "src/core/lib/gpr/env.h"
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gpr/string.h"
-#include "src/core/lib/gpr/thd.h"
+#include "src/core/lib/gprpp/thd.h"
 #include "src/core/lib/profiling/timers.h"
 #include "src/core/lib/profiling/timers.h"
 
 
 namespace grpc {
 namespace grpc {

+ 10 - 6
src/cpp/server/dynamic_thread_pool.cc

@@ -19,20 +19,24 @@
 #include "src/cpp/server/dynamic_thread_pool.h"
 #include "src/cpp/server/dynamic_thread_pool.h"
 
 
 #include <mutex>
 #include <mutex>
-#include <thread>
 
 
 #include <grpc/support/log.h>
 #include <grpc/support/log.h>
 
 
+#include "src/core/lib/gprpp/thd.h"
+
 namespace grpc {
 namespace grpc {
 
 
 DynamicThreadPool::DynamicThread::DynamicThread(DynamicThreadPool* pool)
 DynamicThreadPool::DynamicThread::DynamicThread(DynamicThreadPool* pool)
     : pool_(pool),
     : pool_(pool),
-      thd_(new std::thread(&DynamicThreadPool::DynamicThread::ThreadFunc,
-                           this)) {}
-DynamicThreadPool::DynamicThread::~DynamicThread() {
-  thd_->join();
-  thd_.reset();
+      thd_("dynamic thread pool thread",
+           [](void* th) {
+             reinterpret_cast<DynamicThreadPool::DynamicThread*>(th)
+                 ->ThreadFunc();
+           },
+           this) {
+  thd_.Start();
 }
 }
+DynamicThreadPool::DynamicThread::~DynamicThread() { thd_.Join(); }
 
 
 void DynamicThreadPool::DynamicThread::ThreadFunc() {
 void DynamicThreadPool::DynamicThread::ThreadFunc() {
   pool_->ThreadFunc();
   pool_->ThreadFunc();

+ 2 - 2
src/cpp/server/dynamic_thread_pool.h

@@ -24,10 +24,10 @@
 #include <memory>
 #include <memory>
 #include <mutex>
 #include <mutex>
 #include <queue>
 #include <queue>
-#include <thread>
 
 
 #include <grpcpp/support/config.h>
 #include <grpcpp/support/config.h>
 
 
+#include "src/core/lib/gprpp/thd.h"
 #include "src/cpp/server/thread_pool_interface.h"
 #include "src/cpp/server/thread_pool_interface.h"
 
 
 namespace grpc {
 namespace grpc {
@@ -47,7 +47,7 @@ class DynamicThreadPool final : public ThreadPoolInterface {
 
 
    private:
    private:
     DynamicThreadPool* pool_;
     DynamicThreadPool* pool_;
-    std::unique_ptr<std::thread> thd_;
+    grpc_core::Thread thd_;
     void ThreadFunc();
     void ThreadFunc();
   };
   };
   std::mutex mu_;
   std::mutex mu_;

+ 10 - 5
src/cpp/thread_manager/thread_manager.cc

@@ -20,18 +20,24 @@
 
 
 #include <climits>
 #include <climits>
 #include <mutex>
 #include <mutex>
-#include <thread>
 
 
 #include <grpc/support/log.h>
 #include <grpc/support/log.h>
 
 
+#include "src/core/lib/gprpp/thd.h"
+
 namespace grpc {
 namespace grpc {
 
 
 ThreadManager::WorkerThread::WorkerThread(ThreadManager* thd_mgr)
 ThreadManager::WorkerThread::WorkerThread(ThreadManager* thd_mgr)
     : thd_mgr_(thd_mgr) {
     : thd_mgr_(thd_mgr) {
   // Make thread creation exclusive with respect to its join happening in
   // Make thread creation exclusive with respect to its join happening in
   // ~WorkerThread().
   // ~WorkerThread().
-  std::lock_guard<std::mutex> lock(wt_mu_);
-  thd_ = std::thread(&ThreadManager::WorkerThread::Run, this);
+  thd_ = grpc_core::Thread(
+      "sync server thread",
+      [](void* th) {
+        reinterpret_cast<ThreadManager::WorkerThread*>(th)->Run();
+      },
+      this);
+  thd_.Start();
 }
 }
 
 
 void ThreadManager::WorkerThread::Run() {
 void ThreadManager::WorkerThread::Run() {
@@ -41,8 +47,7 @@ void ThreadManager::WorkerThread::Run() {
 
 
 ThreadManager::WorkerThread::~WorkerThread() {
 ThreadManager::WorkerThread::~WorkerThread() {
   // Don't join until the thread is fully constructed.
   // Don't join until the thread is fully constructed.
-  std::lock_guard<std::mutex> lock(wt_mu_);
-  thd_.join();
+  thd_.Join();
 }
 }
 
 
 ThreadManager::ThreadManager(int min_pollers, int max_pollers)
 ThreadManager::ThreadManager(int min_pollers, int max_pollers)

+ 5 - 5
src/cpp/thread_manager/thread_manager.h

@@ -23,10 +23,11 @@
 #include <list>
 #include <list>
 #include <memory>
 #include <memory>
 #include <mutex>
 #include <mutex>
-#include <thread>
 
 
 #include <grpcpp/support/config.h>
 #include <grpcpp/support/config.h>
 
 
+#include "src/core/lib/gprpp/thd.h"
+
 namespace grpc {
 namespace grpc {
 
 
 class ThreadManager {
 class ThreadManager {
@@ -84,8 +85,8 @@ class ThreadManager {
   virtual void Wait();
   virtual void Wait();
 
 
  private:
  private:
-  // Helper wrapper class around std::thread. This takes a ThreadManager object
-  // and starts a new std::thread to calls the Run() function.
+  // Helper wrapper class around grpc_core::Thread. Takes a ThreadManager object
+  // and starts a new grpc_core::Thread to calls the Run() function.
   //
   //
   // The Run() function calls ThreadManager::MainWorkLoop() function and once
   // The Run() function calls ThreadManager::MainWorkLoop() function and once
   // that completes, it marks the WorkerThread completed by calling
   // that completes, it marks the WorkerThread completed by calling
@@ -101,8 +102,7 @@ class ThreadManager {
     void Run();
     void Run();
 
 
     ThreadManager* const thd_mgr_;
     ThreadManager* const thd_mgr_;
-    std::mutex wt_mu_;
-    std::thread thd_;
+    grpc_core::Thread thd_;
   };
   };
 
 
   // The main funtion in ThreadManager
   // The main funtion in ThreadManager

+ 2 - 3
src/python/grpcio/grpc_core_dependencies.py

@@ -41,9 +41,6 @@ CORE_SOURCE_FILES = [
     'src/core/lib/gpr/sync.cc',
     'src/core/lib/gpr/sync.cc',
     'src/core/lib/gpr/sync_posix.cc',
     'src/core/lib/gpr/sync_posix.cc',
     'src/core/lib/gpr/sync_windows.cc',
     'src/core/lib/gpr/sync_windows.cc',
-    'src/core/lib/gpr/thd.cc',
-    'src/core/lib/gpr/thd_posix.cc',
-    'src/core/lib/gpr/thd_windows.cc',
     'src/core/lib/gpr/time.cc',
     'src/core/lib/gpr/time.cc',
     'src/core/lib/gpr/time_posix.cc',
     'src/core/lib/gpr/time_posix.cc',
     'src/core/lib/gpr/time_precise.cc',
     'src/core/lib/gpr/time_precise.cc',
@@ -53,6 +50,8 @@ CORE_SOURCE_FILES = [
     'src/core/lib/gpr/tmpfile_posix.cc',
     'src/core/lib/gpr/tmpfile_posix.cc',
     'src/core/lib/gpr/tmpfile_windows.cc',
     'src/core/lib/gpr/tmpfile_windows.cc',
     'src/core/lib/gpr/wrap_memcpy.cc',
     'src/core/lib/gpr/wrap_memcpy.cc',
+    'src/core/lib/gprpp/thd_posix.cc',
+    'src/core/lib/gprpp/thd_windows.cc',
     'src/core/lib/profiling/basic_timers.cc',
     'src/core/lib/profiling/basic_timers.cc',
     'src/core/lib/profiling/stap_timers.cc',
     'src/core/lib/profiling/stap_timers.cc',
     'src/core/lib/surface/init.cc',
     'src/core/lib/surface/init.cc',

+ 26 - 0
templates/CMakeLists.txt.template

@@ -84,6 +84,7 @@
 
 
   # Options
   # Options
   option(gRPC_BUILD_TESTS "Build tests" OFF)
   option(gRPC_BUILD_TESTS "Build tests" OFF)
+  option(gRPC_BUILD_CODEGEN "Build codegen" ON)
 
 
   set(gRPC_INSTALL_default ON)
   set(gRPC_INSTALL_default ON)
   if (NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
   if (NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
@@ -125,6 +126,8 @@
       set(_gRPC_PLATFORM_LINUX ON)
       set(_gRPC_PLATFORM_LINUX ON)
     elseif(<%text>${CMAKE_SYSTEM_NAME}</%text> MATCHES "Darwin")
     elseif(<%text>${CMAKE_SYSTEM_NAME}</%text> MATCHES "Darwin")
       set(_gRPC_PLATFORM_MAC ON)
       set(_gRPC_PLATFORM_MAC ON)
+    elseif(<%text>${CMAKE_SYSTEM_NAME}</%text> MATCHES "Android")
+      set(_gRPC_PLATFORM_ANDROID ON)
     else()
     else()
       set(_gRPC_PLATFORM_POSIX ON)
       set(_gRPC_PLATFORM_POSIX ON)
     endif()
     endif()
@@ -168,6 +171,8 @@
 
 
   if(_gRPC_PLATFORM_MAC)
   if(_gRPC_PLATFORM_MAC)
     set(_gRPC_ALLTARGETS_LIBRARIES <%text>${CMAKE_DL_LIBS}</%text> m pthread)
     set(_gRPC_ALLTARGETS_LIBRARIES <%text>${CMAKE_DL_LIBS}</%text> m pthread)
+  elseif(_gRPC_PLATFORM_ANDROID)
+    set(_gRPC_ALLTARGETS_LIBRARIES <%text>${CMAKE_DL_LIBS}</%text> m)
   elseif(UNIX)
   elseif(UNIX)
     set(_gRPC_ALLTARGETS_LIBRARIES <%text>${CMAKE_DL_LIBS}</%text> rt m pthread)
     set(_gRPC_ALLTARGETS_LIBRARIES <%text>${CMAKE_DL_LIBS}</%text> rt m pthread)
   endif()
   endif()
@@ -304,6 +309,13 @@
   ${cc_binary(tgt)}
   ${cc_binary(tgt)}
   ${get_platforms_condition_end(tgt.platforms)}\
   ${get_platforms_condition_end(tgt.platforms)}\
   endif (gRPC_BUILD_TESTS)
   endif (gRPC_BUILD_TESTS)
+  % elif tgt.build in ["protoc"]:
+  if (gRPC_BUILD_CODEGEN)
+  ${get_platforms_condition_begin(tgt.platforms)}\
+  ${cc_binary(tgt)}
+  ${cc_install(tgt)}
+  ${get_platforms_condition_end(tgt.platforms)}\
+  endif (gRPC_BUILD_CODEGEN)
   % else:
   % else:
   ${get_platforms_condition_begin(tgt.platforms)}\
   ${get_platforms_condition_begin(tgt.platforms)}\
   ${cc_binary(tgt)}
   ${cc_binary(tgt)}
@@ -314,6 +326,9 @@
   % endfor
   % endfor
 
 
   <%def name="cc_library(lib)">
   <%def name="cc_library(lib)">
+  % if any(proto_re.match(src) for src in lib.src):
+  if (gRPC_BUILD_CODEGEN)
+  % endif
   add_library(${lib.name}${' SHARED' if lib.get('dll', None) == 'only' else ''}
   add_library(${lib.name}${' SHARED' if lib.get('dll', None) == 'only' else ''}
   % for src in lib.src:
   % for src in lib.src:
   % if not proto_re.match(src):
   % if not proto_re.match(src):
@@ -376,6 +391,14 @@
   % endfor
   % endfor
   )
   )
   % endif
   % endif
+  % if lib.name in ["gpr"]:
+  if (_gRPC_PLATFORM_ANDROID)
+    target_link_libraries(gpr
+      android
+      log
+    )
+  endif (_gRPC_PLATFORM_ANDROID)
+  % endif
 
 
   % if len(lib.get('public_headers', [])) > 0:
   % if len(lib.get('public_headers', [])) > 0:
   foreach(_hdr
   foreach(_hdr
@@ -390,6 +413,9 @@
     )
     )
   endforeach()
   endforeach()
   % endif
   % endif
+  % if any(proto_re.match(src) for src in lib.src):
+  endif (gRPC_BUILD_CODEGEN)
+  % endif
   </%def>
   </%def>
 
 
   <%def name="cc_binary(tgt)">
   <%def name="cc_binary(tgt)">

+ 5 - 3
test/core/bad_client/bad_client.cc

@@ -29,7 +29,7 @@
 #include "src/core/lib/channel/channel_stack.h"
 #include "src/core/lib/channel/channel_stack.h"
 #include "src/core/lib/gpr/murmur_hash.h"
 #include "src/core/lib/gpr/murmur_hash.h"
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gpr/string.h"
-#include "src/core/lib/gpr/thd.h"
+#include "src/core/lib/gprpp/thd.h"
 #include "src/core/lib/iomgr/endpoint_pair.h"
 #include "src/core/lib/iomgr/endpoint_pair.h"
 #include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/surface/completion_queue.h"
 #include "src/core/lib/surface/completion_queue.h"
@@ -220,11 +220,12 @@ void grpc_run_bad_client_test(
   /* Check a ground truth */
   /* Check a ground truth */
   GPR_ASSERT(grpc_server_has_open_connections(a.server));
   GPR_ASSERT(grpc_server_has_open_connections(a.server));
 
 
-  gpr_thd_id id;
   gpr_event_init(&a.done_thd);
   gpr_event_init(&a.done_thd);
   a.validator = server_validator;
   a.validator = server_validator;
   /* Start validator */
   /* Start validator */
-  gpr_thd_new(&id, "grpc_bad_client", thd_func, &a, nullptr);
+
+  grpc_core::Thread server_validator_thd("grpc_bad_client", thd_func, &a);
+  server_validator_thd.Start();
   for (int i = 0; i < num_args; i++) {
   for (int i = 0; i < num_args; i++) {
     grpc_run_client_side_validator(&args[i], i == (num_args - 1) ? flags : 0,
     grpc_run_client_side_validator(&args[i], i == (num_args - 1) ? flags : 0,
                                    &sfd, client_cq);
                                    &sfd, client_cq);
@@ -234,6 +235,7 @@ void grpc_run_bad_client_test(
 
 
   /* Shutdown. */
   /* Shutdown. */
   shutdown_client(&sfd.client);
   shutdown_client(&sfd.client);
+  server_validator_thd.Join();
 
 
   shutdown_cq = grpc_completion_queue_create_for_pluck(nullptr);
   shutdown_cq = grpc_completion_queue_create_for_pluck(nullptr);
   grpc_server_shutdown_and_notify(a.server, shutdown_cq, nullptr);
   grpc_server_shutdown_and_notify(a.server, shutdown_cq, nullptr);

+ 11 - 6
test/core/end2end/bad_server_response_test.cc

@@ -31,7 +31,8 @@
 
 
 #include "src/core/lib/gpr/host_port.h"
 #include "src/core/lib/gpr/host_port.h"
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gpr/string.h"
-#include "src/core/lib/gpr/thd.h"
+#include "src/core/lib/gprpp/memory.h"
+#include "src/core/lib/gprpp/thd.h"
 #include "src/core/lib/iomgr/sockaddr.h"
 #include "src/core/lib/iomgr/sockaddr.h"
 #include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/slice/slice_string_helpers.h"
 #include "src/core/lib/slice/slice_string_helpers.h"
@@ -253,15 +254,17 @@ static void actually_poll_server(void* arg) {
   gpr_free(pa);
   gpr_free(pa);
 }
 }
 
 
-static void poll_server_until_read_done(test_tcp_server* server,
-                                        gpr_event* signal_when_done) {
+static grpc_core::Thread* poll_server_until_read_done(
+    test_tcp_server* server, gpr_event* signal_when_done) {
   gpr_atm_rel_store(&state.done_atm, 0);
   gpr_atm_rel_store(&state.done_atm, 0);
   state.write_done = 0;
   state.write_done = 0;
-  gpr_thd_id id;
   poll_args* pa = static_cast<poll_args*>(gpr_malloc(sizeof(*pa)));
   poll_args* pa = static_cast<poll_args*>(gpr_malloc(sizeof(*pa)));
   pa->server = server;
   pa->server = server;
   pa->signal_when_done = signal_when_done;
   pa->signal_when_done = signal_when_done;
-  gpr_thd_new(&id, "grpc_poll_server", actually_poll_server, pa, nullptr);
+  auto* th = grpc_core::New<grpc_core::Thread>("grpc_poll_server",
+                                               actually_poll_server, pa);
+  th->Start();
+  return th;
 }
 }
 
 
 static void run_test(const char* response_payload,
 static void run_test(const char* response_payload,
@@ -281,9 +284,11 @@ static void run_test(const char* response_payload,
   state.response_payload_length = response_payload_length;
   state.response_payload_length = response_payload_length;
 
 
   /* poll server until sending out the response */
   /* poll server until sending out the response */
-  poll_server_until_read_done(&test_server, &ev);
+  grpc_core::UniquePtr<grpc_core::Thread> thdptr(
+      poll_server_until_read_done(&test_server, &ev));
   start_rpc(server_port, expected_status, expected_detail);
   start_rpc(server_port, expected_status, expected_detail);
   gpr_event_wait(&ev, gpr_inf_future(GPR_CLOCK_REALTIME));
   gpr_event_wait(&ev, gpr_inf_future(GPR_CLOCK_REALTIME));
+  thdptr->Join();
 
 
   /* clean up */
   /* clean up */
   grpc_endpoint_shutdown(state.tcp,
   grpc_endpoint_shutdown(state.tcp,

+ 0 - 1
test/core/end2end/fixtures/h2_census.cc

@@ -30,7 +30,6 @@
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/channel/connected_channel.h"
 #include "src/core/lib/channel/connected_channel.h"
 #include "src/core/lib/gpr/host_port.h"
 #include "src/core/lib/gpr/host_port.h"
-#include "src/core/lib/gpr/thd.h"
 #include "src/core/lib/surface/channel.h"
 #include "src/core/lib/surface/channel.h"
 #include "src/core/lib/surface/server.h"
 #include "src/core/lib/surface/server.h"
 #include "test/core/util/port.h"
 #include "test/core/util/port.h"

+ 0 - 1
test/core/end2end/fixtures/h2_compress.cc

@@ -30,7 +30,6 @@
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/channel/connected_channel.h"
 #include "src/core/lib/channel/connected_channel.h"
 #include "src/core/lib/gpr/host_port.h"
 #include "src/core/lib/gpr/host_port.h"
-#include "src/core/lib/gpr/thd.h"
 #include "src/core/lib/surface/channel.h"
 #include "src/core/lib/surface/channel.h"
 #include "src/core/lib/surface/server.h"
 #include "src/core/lib/surface/server.h"
 #include "test/core/util/port.h"
 #include "test/core/util/port.h"

+ 0 - 1
test/core/end2end/fixtures/h2_full+pipe.cc

@@ -34,7 +34,6 @@
 #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
 #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
 #include "src/core/lib/channel/connected_channel.h"
 #include "src/core/lib/channel/connected_channel.h"
 #include "src/core/lib/gpr/host_port.h"
 #include "src/core/lib/gpr/host_port.h"
-#include "src/core/lib/gpr/thd.h"
 #include "src/core/lib/iomgr/wakeup_fd_posix.h"
 #include "src/core/lib/iomgr/wakeup_fd_posix.h"
 #include "src/core/lib/surface/channel.h"
 #include "src/core/lib/surface/channel.h"
 #include "src/core/lib/surface/server.h"
 #include "src/core/lib/surface/server.h"

+ 0 - 1
test/core/end2end/fixtures/h2_full+trace.cc

@@ -35,7 +35,6 @@
 #include "src/core/lib/channel/connected_channel.h"
 #include "src/core/lib/channel/connected_channel.h"
 #include "src/core/lib/gpr/env.h"
 #include "src/core/lib/gpr/env.h"
 #include "src/core/lib/gpr/host_port.h"
 #include "src/core/lib/gpr/host_port.h"
-#include "src/core/lib/gpr/thd.h"
 #include "src/core/lib/surface/channel.h"
 #include "src/core/lib/surface/channel.h"
 #include "src/core/lib/surface/server.h"
 #include "src/core/lib/surface/server.h"
 #include "test/core/util/port.h"
 #include "test/core/util/port.h"

+ 0 - 1
test/core/end2end/fixtures/h2_full+workarounds.cc

@@ -31,7 +31,6 @@
 #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
 #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
 #include "src/core/lib/channel/connected_channel.h"
 #include "src/core/lib/channel/connected_channel.h"
 #include "src/core/lib/gpr/host_port.h"
 #include "src/core/lib/gpr/host_port.h"
-#include "src/core/lib/gpr/thd.h"
 #include "src/core/lib/surface/channel.h"
 #include "src/core/lib/surface/channel.h"
 #include "src/core/lib/surface/server.h"
 #include "src/core/lib/surface/server.h"
 #include "test/core/util/port.h"
 #include "test/core/util/port.h"

+ 0 - 1
test/core/end2end/fixtures/h2_full.cc

@@ -29,7 +29,6 @@
 #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
 #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
 #include "src/core/lib/channel/connected_channel.h"
 #include "src/core/lib/channel/connected_channel.h"
 #include "src/core/lib/gpr/host_port.h"
 #include "src/core/lib/gpr/host_port.h"
-#include "src/core/lib/gpr/thd.h"
 #include "src/core/lib/surface/channel.h"
 #include "src/core/lib/surface/channel.h"
 #include "src/core/lib/surface/server.h"
 #include "src/core/lib/surface/server.h"
 #include "test/core/util/port.h"
 #include "test/core/util/port.h"

+ 0 - 1
test/core/end2end/fixtures/h2_http_proxy.cc

@@ -31,7 +31,6 @@
 #include "src/core/lib/channel/connected_channel.h"
 #include "src/core/lib/channel/connected_channel.h"
 #include "src/core/lib/gpr/env.h"
 #include "src/core/lib/gpr/env.h"
 #include "src/core/lib/gpr/host_port.h"
 #include "src/core/lib/gpr/host_port.h"
-#include "src/core/lib/gpr/thd.h"
 #include "src/core/lib/surface/channel.h"
 #include "src/core/lib/surface/channel.h"
 #include "src/core/lib/surface/server.h"
 #include "src/core/lib/surface/server.h"
 #include "test/core/end2end/fixtures/http_proxy_fixture.h"
 #include "test/core/end2end/fixtures/http_proxy_fixture.h"

+ 0 - 1
test/core/end2end/fixtures/h2_load_reporting.cc

@@ -31,7 +31,6 @@
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/channel/connected_channel.h"
 #include "src/core/lib/channel/connected_channel.h"
 #include "src/core/lib/gpr/host_port.h"
 #include "src/core/lib/gpr/host_port.h"
-#include "src/core/lib/gpr/thd.h"
 #include "src/core/lib/surface/channel.h"
 #include "src/core/lib/surface/channel.h"
 #include "src/core/lib/surface/server.h"
 #include "src/core/lib/surface/server.h"
 #include "test/core/util/port.h"
 #include "test/core/util/port.h"

+ 0 - 1
test/core/end2end/fixtures/h2_proxy.cc

@@ -29,7 +29,6 @@
 #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
 #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
 #include "src/core/lib/channel/connected_channel.h"
 #include "src/core/lib/channel/connected_channel.h"
 #include "src/core/lib/gpr/host_port.h"
 #include "src/core/lib/gpr/host_port.h"
-#include "src/core/lib/gpr/thd.h"
 #include "src/core/lib/surface/channel.h"
 #include "src/core/lib/surface/channel.h"
 #include "src/core/lib/surface/server.h"
 #include "src/core/lib/surface/server.h"
 #include "test/core/end2end/fixtures/proxy.h"
 #include "test/core/end2end/fixtures/proxy.h"

+ 0 - 1
test/core/end2end/fixtures/h2_sockpair+trace.cc

@@ -36,7 +36,6 @@
 #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
 #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
 #include "src/core/lib/channel/connected_channel.h"
 #include "src/core/lib/channel/connected_channel.h"
 #include "src/core/lib/gpr/env.h"
 #include "src/core/lib/gpr/env.h"
-#include "src/core/lib/gpr/thd.h"
 #include "src/core/lib/iomgr/endpoint_pair.h"
 #include "src/core/lib/iomgr/endpoint_pair.h"
 #include "src/core/lib/iomgr/iomgr.h"
 #include "src/core/lib/iomgr/iomgr.h"
 #include "src/core/lib/surface/channel.h"
 #include "src/core/lib/surface/channel.h"

+ 0 - 1
test/core/end2end/fixtures/h2_sockpair.cc

@@ -30,7 +30,6 @@
 #include "src/core/ext/filters/http/server/http_server_filter.h"
 #include "src/core/ext/filters/http/server/http_server_filter.h"
 #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
 #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
 #include "src/core/lib/channel/connected_channel.h"
 #include "src/core/lib/channel/connected_channel.h"
-#include "src/core/lib/gpr/thd.h"
 #include "src/core/lib/iomgr/endpoint_pair.h"
 #include "src/core/lib/iomgr/endpoint_pair.h"
 #include "src/core/lib/iomgr/iomgr.h"
 #include "src/core/lib/iomgr/iomgr.h"
 #include "src/core/lib/surface/channel.h"
 #include "src/core/lib/surface/channel.h"

+ 0 - 1
test/core/end2end/fixtures/h2_sockpair_1byte.cc

@@ -30,7 +30,6 @@
 #include "src/core/ext/filters/http/server/http_server_filter.h"
 #include "src/core/ext/filters/http/server/http_server_filter.h"
 #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
 #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
 #include "src/core/lib/channel/connected_channel.h"
 #include "src/core/lib/channel/connected_channel.h"
-#include "src/core/lib/gpr/thd.h"
 #include "src/core/lib/iomgr/endpoint_pair.h"
 #include "src/core/lib/iomgr/endpoint_pair.h"
 #include "src/core/lib/iomgr/iomgr.h"
 #include "src/core/lib/iomgr/iomgr.h"
 #include "src/core/lib/surface/channel.h"
 #include "src/core/lib/surface/channel.h"

+ 0 - 1
test/core/end2end/fixtures/h2_uds.cc

@@ -33,7 +33,6 @@
 #include "src/core/lib/channel/connected_channel.h"
 #include "src/core/lib/channel/connected_channel.h"
 #include "src/core/lib/gpr/host_port.h"
 #include "src/core/lib/gpr/host_port.h"
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gpr/string.h"
-#include "src/core/lib/gpr/thd.h"
 #include "src/core/lib/surface/channel.h"
 #include "src/core/lib/surface/channel.h"
 #include "src/core/lib/surface/server.h"
 #include "src/core/lib/surface/server.h"
 #include "test/core/util/port.h"
 #include "test/core/util/port.h"

+ 5 - 7
test/core/end2end/fixtures/http_proxy_fixture.cc

@@ -33,7 +33,7 @@
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/gpr/host_port.h"
 #include "src/core/lib/gpr/host_port.h"
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gpr/string.h"
-#include "src/core/lib/gpr/thd.h"
+#include "src/core/lib/gprpp/thd.h"
 #include "src/core/lib/http/parser.h"
 #include "src/core/lib/http/parser.h"
 #include "src/core/lib/iomgr/closure.h"
 #include "src/core/lib/iomgr/closure.h"
 #include "src/core/lib/iomgr/combiner.h"
 #include "src/core/lib/iomgr/combiner.h"
@@ -53,7 +53,7 @@
 
 
 struct grpc_end2end_http_proxy {
 struct grpc_end2end_http_proxy {
   char* proxy_name;
   char* proxy_name;
-  gpr_thd_id thd;
+  grpc_core::Thread thd;
   grpc_tcp_server* server;
   grpc_tcp_server* server;
   grpc_channel_args* channel_args;
   grpc_channel_args* channel_args;
   gpr_mu* mu;
   gpr_mu* mu;
@@ -550,10 +550,8 @@ grpc_end2end_http_proxy* grpc_end2end_http_proxy_create(
   grpc_tcp_server_start(proxy->server, &proxy->pollset, 1, on_accept, proxy);
   grpc_tcp_server_start(proxy->server, &proxy->pollset, 1, on_accept, proxy);
 
 
   // Start proxy thread.
   // Start proxy thread.
-  gpr_thd_options opt = gpr_thd_options_default();
-  gpr_thd_options_set_joinable(&opt);
-  GPR_ASSERT(
-      gpr_thd_new(&proxy->thd, "grpc_http_proxy", thread_main, proxy, &opt));
+  proxy->thd = grpc_core::Thread("grpc_http_proxy", thread_main, proxy);
+  proxy->thd.Start();
   return proxy;
   return proxy;
 }
 }
 
 
@@ -566,7 +564,7 @@ static void destroy_pollset(void* arg, grpc_error* error) {
 void grpc_end2end_http_proxy_destroy(grpc_end2end_http_proxy* proxy) {
 void grpc_end2end_http_proxy_destroy(grpc_end2end_http_proxy* proxy) {
   gpr_unref(&proxy->users);  // Signal proxy thread to shutdown.
   gpr_unref(&proxy->users);  // Signal proxy thread to shutdown.
   grpc_core::ExecCtx exec_ctx;
   grpc_core::ExecCtx exec_ctx;
-  gpr_thd_join(proxy->thd);
+  proxy->thd.Join();
   grpc_tcp_server_shutdown_listeners(proxy->server);
   grpc_tcp_server_shutdown_listeners(proxy->server);
   grpc_tcp_server_unref(proxy->server);
   grpc_tcp_server_unref(proxy->server);
   gpr_free(proxy->proxy_name);
   gpr_free(proxy->proxy_name);

+ 0 - 1
test/core/end2end/fixtures/inproc.cc

@@ -29,7 +29,6 @@
 #include "src/core/ext/transport/inproc/inproc_transport.h"
 #include "src/core/ext/transport/inproc/inproc_transport.h"
 #include "src/core/lib/channel/connected_channel.h"
 #include "src/core/lib/channel/connected_channel.h"
 #include "src/core/lib/gpr/host_port.h"
 #include "src/core/lib/gpr/host_port.h"
-#include "src/core/lib/gpr/thd.h"
 #include "src/core/lib/surface/channel.h"
 #include "src/core/lib/surface/channel.h"
 #include "src/core/lib/surface/server.h"
 #include "src/core/lib/surface/server.h"
 #include "test/core/util/port.h"
 #include "test/core/util/port.h"

+ 5 - 7
test/core/end2end/fixtures/proxy.cc

@@ -25,12 +25,12 @@
 #include <grpc/support/sync.h>
 #include <grpc/support/sync.h>
 
 
 #include "src/core/lib/gpr/host_port.h"
 #include "src/core/lib/gpr/host_port.h"
-#include "src/core/lib/gpr/thd.h"
 #include "src/core/lib/gpr/useful.h"
 #include "src/core/lib/gpr/useful.h"
+#include "src/core/lib/gprpp/thd.h"
 #include "test/core/util/port.h"
 #include "test/core/util/port.h"
 
 
 struct grpc_end2end_proxy {
 struct grpc_end2end_proxy {
-  gpr_thd_id thd;
+  grpc_core::Thread thd;
   char* proxy_port;
   char* proxy_port;
   char* server_port;
   char* server_port;
   grpc_completion_queue* cq;
   grpc_completion_queue* cq;
@@ -76,7 +76,6 @@ static void request_call(grpc_end2end_proxy* proxy);
 grpc_end2end_proxy* grpc_end2end_proxy_create(const grpc_end2end_proxy_def* def,
 grpc_end2end_proxy* grpc_end2end_proxy_create(const grpc_end2end_proxy_def* def,
                                               grpc_channel_args* client_args,
                                               grpc_channel_args* client_args,
                                               grpc_channel_args* server_args) {
                                               grpc_channel_args* server_args) {
-  gpr_thd_options opt = gpr_thd_options_default();
   int proxy_port = grpc_pick_unused_port_or_die();
   int proxy_port = grpc_pick_unused_port_or_die();
   int server_port = grpc_pick_unused_port_or_die();
   int server_port = grpc_pick_unused_port_or_die();
 
 
@@ -98,9 +97,8 @@ grpc_end2end_proxy* grpc_end2end_proxy_create(const grpc_end2end_proxy_def* def,
   grpc_server_start(proxy->server);
   grpc_server_start(proxy->server);
 
 
   grpc_call_details_init(&proxy->new_call_details);
   grpc_call_details_init(&proxy->new_call_details);
-  gpr_thd_options_set_joinable(&opt);
-  GPR_ASSERT(
-      gpr_thd_new(&proxy->thd, "grpc_end2end_proxy", thread_main, proxy, &opt));
+  proxy->thd = grpc_core::Thread("grpc_end2end_proxy", thread_main, proxy);
+  proxy->thd.Start();
 
 
   request_call(proxy);
   request_call(proxy);
 
 
@@ -123,7 +121,7 @@ static void shutdown_complete(void* arg, int success) {
 void grpc_end2end_proxy_destroy(grpc_end2end_proxy* proxy) {
 void grpc_end2end_proxy_destroy(grpc_end2end_proxy* proxy) {
   grpc_server_shutdown_and_notify(proxy->server, proxy->cq,
   grpc_server_shutdown_and_notify(proxy->server, proxy->cq,
                                   new_closure(shutdown_complete, proxy));
                                   new_closure(shutdown_complete, proxy));
-  gpr_thd_join(proxy->thd);
+  proxy->thd.Join();
   gpr_free(proxy->proxy_port);
   gpr_free(proxy->proxy_port);
   gpr_free(proxy->server_port);
   gpr_free(proxy->server_port);
   grpc_server_destroy(proxy->server);
   grpc_server_destroy(proxy->server);

+ 0 - 1
test/core/end2end/tests/bad_ping.cc

@@ -25,7 +25,6 @@
 #include <grpc/support/sync.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/time.h>
 #include <grpc/support/time.h>
 
 
-#include "src/core/lib/gpr/thd.h"
 #include "src/core/lib/gpr/useful.h"
 #include "src/core/lib/gpr/useful.h"
 #include "test/core/end2end/cq_verifier.h"
 #include "test/core/end2end/cq_verifier.h"
 
 

+ 4 - 7
test/core/end2end/tests/connectivity.cc

@@ -22,7 +22,7 @@
 #include <grpc/support/sync.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/time.h>
 #include <grpc/support/time.h>
 
 
-#include "src/core/lib/gpr/thd.h"
+#include "src/core/lib/gprpp/thd.h"
 #include "test/core/end2end/cq_verifier.h"
 #include "test/core/end2end/cq_verifier.h"
 
 
 static void* tag(intptr_t t) { return (void*)t; }
 static void* tag(intptr_t t) { return (void*)t; }
@@ -50,8 +50,6 @@ static void test_connectivity(grpc_end2end_test_config config) {
   grpc_connectivity_state state;
   grpc_connectivity_state state;
   cq_verifier* cqv = cq_verifier_create(f.cq);
   cq_verifier* cqv = cq_verifier_create(f.cq);
   child_events ce;
   child_events ce;
-  gpr_thd_options thdopt = gpr_thd_options_default();
-  gpr_thd_id thdid;
 
 
   grpc_channel_args client_args;
   grpc_channel_args client_args;
   grpc_arg arg_array[1];
   grpc_arg arg_array[1];
@@ -67,9 +65,8 @@ static void test_connectivity(grpc_end2end_test_config config) {
   ce.channel = f.client;
   ce.channel = f.client;
   ce.cq = f.cq;
   ce.cq = f.cq;
   gpr_event_init(&ce.started);
   gpr_event_init(&ce.started);
-  gpr_thd_options_set_joinable(&thdopt);
-  GPR_ASSERT(
-      gpr_thd_new(&thdid, "grpc_connectivity", child_thread, &ce, &thdopt));
+  grpc_core::Thread thd("grpc_connectivity", child_thread, &ce);
+  thd.Start();
 
 
   gpr_event_wait(&ce.started, gpr_inf_future(GPR_CLOCK_MONOTONIC));
   gpr_event_wait(&ce.started, gpr_inf_future(GPR_CLOCK_MONOTONIC));
 
 
@@ -86,7 +83,7 @@ static void test_connectivity(grpc_end2end_test_config config) {
       f.client, GRPC_CHANNEL_IDLE, gpr_now(GPR_CLOCK_MONOTONIC), f.cq, tag(1));
       f.client, GRPC_CHANNEL_IDLE, gpr_now(GPR_CLOCK_MONOTONIC), f.cq, tag(1));
 
 
   /* eventually the child thread completion should trigger */
   /* eventually the child thread completion should trigger */
-  gpr_thd_join(thdid);
+  thd.Join();
 
 
   /* check that we're still in idle, and start connecting */
   /* check that we're still in idle, and start connecting */
   GPR_ASSERT(grpc_channel_check_connectivity_state(f.client, 1) ==
   GPR_ASSERT(grpc_channel_check_connectivity_state(f.client, 1) ==

+ 0 - 1
test/core/end2end/tests/ping.cc

@@ -22,7 +22,6 @@
 #include <grpc/support/sync.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/time.h>
 #include <grpc/support/time.h>
 
 
-#include "src/core/lib/gpr/thd.h"
 #include "src/core/lib/gpr/useful.h"
 #include "src/core/lib/gpr/useful.h"
 #include "test/core/end2end/cq_verifier.h"
 #include "test/core/end2end/cq_verifier.h"
 
 

+ 0 - 10
test/core/gpr/BUILD

@@ -128,16 +128,6 @@ grpc_cc_test(
     ],
     ],
 )
 )
 
 
-grpc_cc_test(
-    name = "thd_test",
-    srcs = ["thd_test.cc"],
-    language = "C++",
-    deps = [
-        "//:gpr",
-        "//test/core/util:gpr_test_util",
-    ],
-)
-
 grpc_cc_test(
 grpc_cc_test(
     name = "time_test",
     name = "time_test",
     srcs = ["time_test.cc"],
     srcs = ["time_test.cc"],

+ 10 - 10
test/core/gpr/arena_test.cc

@@ -18,16 +18,17 @@
 
 
 #include "src/core/lib/gpr/arena.h"
 #include "src/core/lib/gpr/arena.h"
 
 
+#include <inttypes.h>
+#include <string.h>
+
 #include <grpc/support/alloc.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 #include <grpc/support/string_util.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/sync.h>
-#include <inttypes.h>
-#include <string.h>
 
 
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gpr/string.h"
-#include "src/core/lib/gpr/thd.h"
 #include "src/core/lib/gpr/useful.h"
 #include "src/core/lib/gpr/useful.h"
+#include "src/core/lib/gprpp/thd.h"
 #include "test/core/util/test_config.h"
 #include "test/core/util/test_config.h"
 
 
 static void test_noop(void) { gpr_arena_destroy(gpr_arena_create(1)); }
 static void test_noop(void) { gpr_arena_destroy(gpr_arena_create(1)); }
@@ -97,19 +98,18 @@ static void concurrent_test(void) {
   gpr_event_init(&args.ev_start);
   gpr_event_init(&args.ev_start);
   args.arena = gpr_arena_create(1024);
   args.arena = gpr_arena_create(1024);
 
 
-  gpr_thd_id thds[CONCURRENT_TEST_THREADS];
+  grpc_core::Thread thds[CONCURRENT_TEST_THREADS];
 
 
   for (int i = 0; i < CONCURRENT_TEST_THREADS; i++) {
   for (int i = 0; i < CONCURRENT_TEST_THREADS; i++) {
-    gpr_thd_options opt = gpr_thd_options_default();
-    gpr_thd_options_set_joinable(&opt);
-    gpr_thd_new(&thds[i], "grpc_concurrent_test", concurrent_test_body, &args,
-                &opt);
+    thds[i] =
+        grpc_core::Thread("grpc_concurrent_test", concurrent_test_body, &args);
+    thds[i].Start();
   }
   }
 
 
   gpr_event_set(&args.ev_start, (void*)1);
   gpr_event_set(&args.ev_start, (void*)1);
 
 
-  for (int i = 0; i < CONCURRENT_TEST_THREADS; i++) {
-    gpr_thd_join(thds[i]);
+  for (auto& th : thds) {
+    th.Join();
   }
   }
 
 
   gpr_arena_destroy(args.arena);
   gpr_arena_destroy(args.arena);

+ 18 - 8
test/core/gpr/cpu_test.cc

@@ -21,15 +21,17 @@
    gpr_cpu_current_cpu()
    gpr_cpu_current_cpu()
 */
 */
 
 
-#include <grpc/support/alloc.h>
 #include <grpc/support/cpu.h>
 #include <grpc/support/cpu.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/log.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/time.h>
 #include <grpc/support/time.h>
-#include <stdio.h>
-#include <string.h>
 
 
-#include "src/core/lib/gpr/thd.h"
+#include "src/core/lib/gprpp/thd.h"
 #include "test/core/util/test_config.h"
 #include "test/core/util/test_config.h"
 
 
 /* Test structure is essentially:
 /* Test structure is essentially:
@@ -101,7 +103,6 @@ static void cpu_test(void) {
   uint32_t i;
   uint32_t i;
   int cores_seen = 0;
   int cores_seen = 0;
   struct cpu_test ct;
   struct cpu_test ct;
-  gpr_thd_id thd;
   ct.ncores = gpr_cpu_num_cores();
   ct.ncores = gpr_cpu_num_cores();
   GPR_ASSERT(ct.ncores > 0);
   GPR_ASSERT(ct.ncores > 0);
   ct.nthreads = static_cast<int>(ct.ncores) * 3;
   ct.nthreads = static_cast<int>(ct.ncores) * 3;
@@ -110,15 +111,24 @@ static void cpu_test(void) {
   gpr_mu_init(&ct.mu);
   gpr_mu_init(&ct.mu);
   gpr_cv_init(&ct.done_cv);
   gpr_cv_init(&ct.done_cv);
   ct.is_done = 0;
   ct.is_done = 0;
-  for (i = 0; i < ct.ncores * 3; i++) {
-    GPR_ASSERT(
-        gpr_thd_new(&thd, "grpc_cpu_test", &worker_thread, &ct, nullptr));
+
+  uint32_t nthreads = ct.ncores * 3;
+  grpc_core::Thread* thd =
+      static_cast<grpc_core::Thread*>(gpr_malloc(sizeof(*thd) * nthreads));
+
+  for (i = 0; i < nthreads; i++) {
+    thd[i] = grpc_core::Thread("grpc_cpu_test", &worker_thread, &ct);
+    thd[i].Start();
   }
   }
   gpr_mu_lock(&ct.mu);
   gpr_mu_lock(&ct.mu);
   while (!ct.is_done) {
   while (!ct.is_done) {
     gpr_cv_wait(&ct.done_cv, &ct.mu, gpr_inf_future(GPR_CLOCK_MONOTONIC));
     gpr_cv_wait(&ct.done_cv, &ct.mu, gpr_inf_future(GPR_CLOCK_MONOTONIC));
   }
   }
   gpr_mu_unlock(&ct.mu);
   gpr_mu_unlock(&ct.mu);
+  for (i = 0; i < nthreads; i++) {
+    thd[i].Join();
+  }
+  gpr_free(thd);
   fprintf(stderr, "Saw cores [");
   fprintf(stderr, "Saw cores [");
   fflush(stderr);
   fflush(stderr);
   for (i = 0; i < ct.ncores; i++) {
   for (i = 0; i < ct.ncores; i++) {

+ 16 - 22
test/core/gpr/mpscq_test.cc

@@ -24,8 +24,8 @@
 #include <grpc/support/log.h>
 #include <grpc/support/log.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/sync.h>
 
 
-#include "src/core/lib/gpr/thd.h"
 #include "src/core/lib/gpr/useful.h"
 #include "src/core/lib/gpr/useful.h"
+#include "src/core/lib/gprpp/thd.h"
 #include "test/core/util/test_config.h"
 #include "test/core/util/test_config.h"
 
 
 typedef struct test_node {
 typedef struct test_node {
@@ -76,18 +76,16 @@ static void test_mt(void) {
   gpr_log(GPR_DEBUG, "test_mt");
   gpr_log(GPR_DEBUG, "test_mt");
   gpr_event start;
   gpr_event start;
   gpr_event_init(&start);
   gpr_event_init(&start);
-  gpr_thd_id thds[100];
+  grpc_core::Thread thds[100];
   thd_args ta[GPR_ARRAY_SIZE(thds)];
   thd_args ta[GPR_ARRAY_SIZE(thds)];
   gpr_mpscq q;
   gpr_mpscq q;
   gpr_mpscq_init(&q);
   gpr_mpscq_init(&q);
   for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) {
   for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) {
-    gpr_thd_options options = gpr_thd_options_default();
-    gpr_thd_options_set_joinable(&options);
     ta[i].ctr = 0;
     ta[i].ctr = 0;
     ta[i].q = &q;
     ta[i].q = &q;
     ta[i].start = &start;
     ta[i].start = &start;
-    GPR_ASSERT(
-        gpr_thd_new(&thds[i], "grpc_mt_test", test_thread, &ta[i], &options));
+    thds[i] = grpc_core::Thread("grpc_mt_test", test_thread, &ta[i]);
+    thds[i].Start();
   }
   }
   size_t num_done = 0;
   size_t num_done = 0;
   size_t spins = 0;
   size_t spins = 0;
@@ -104,8 +102,8 @@ static void test_mt(void) {
     gpr_free(tn);
     gpr_free(tn);
   }
   }
   gpr_log(GPR_DEBUG, "spins: %" PRIdPTR, spins);
   gpr_log(GPR_DEBUG, "spins: %" PRIdPTR, spins);
-  for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) {
-    gpr_thd_join(thds[i]);
+  for (auto& th : thds) {
+    th.Join();
   }
   }
   gpr_mpscq_destroy(&q);
   gpr_mpscq_destroy(&q);
 }
 }
@@ -147,19 +145,17 @@ static void test_mt_multipop(void) {
   gpr_log(GPR_DEBUG, "test_mt_multipop");
   gpr_log(GPR_DEBUG, "test_mt_multipop");
   gpr_event start;
   gpr_event start;
   gpr_event_init(&start);
   gpr_event_init(&start);
-  gpr_thd_id thds[100];
-  gpr_thd_id pull_thds[100];
+  grpc_core::Thread thds[50];
+  grpc_core::Thread pull_thds[50];
   thd_args ta[GPR_ARRAY_SIZE(thds)];
   thd_args ta[GPR_ARRAY_SIZE(thds)];
   gpr_mpscq q;
   gpr_mpscq q;
   gpr_mpscq_init(&q);
   gpr_mpscq_init(&q);
   for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) {
   for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) {
-    gpr_thd_options options = gpr_thd_options_default();
-    gpr_thd_options_set_joinable(&options);
     ta[i].ctr = 0;
     ta[i].ctr = 0;
     ta[i].q = &q;
     ta[i].q = &q;
     ta[i].start = &start;
     ta[i].start = &start;
-    GPR_ASSERT(gpr_thd_new(&thds[i], "grpc_multipop_test", test_thread, &ta[i],
-                           &options));
+    thds[i] = grpc_core::Thread("grpc_multipop_test", test_thread, &ta[i]);
+    thds[i].Start();
   }
   }
   pull_args pa;
   pull_args pa;
   pa.ta = ta;
   pa.ta = ta;
@@ -170,18 +166,16 @@ static void test_mt_multipop(void) {
   pa.start = &start;
   pa.start = &start;
   gpr_mu_init(&pa.mu);
   gpr_mu_init(&pa.mu);
   for (size_t i = 0; i < GPR_ARRAY_SIZE(pull_thds); i++) {
   for (size_t i = 0; i < GPR_ARRAY_SIZE(pull_thds); i++) {
-    gpr_thd_options options = gpr_thd_options_default();
-    gpr_thd_options_set_joinable(&options);
-    GPR_ASSERT(gpr_thd_new(&pull_thds[i], "grpc_multipop_pull", pull_thread,
-                           &pa, &options));
+    pull_thds[i] = grpc_core::Thread("grpc_multipop_pull", pull_thread, &pa);
+    pull_thds[i].Start();
   }
   }
   gpr_event_set(&start, (void*)1);
   gpr_event_set(&start, (void*)1);
-  for (size_t i = 0; i < GPR_ARRAY_SIZE(pull_thds); i++) {
-    gpr_thd_join(pull_thds[i]);
+  for (auto& pth : pull_thds) {
+    pth.Join();
   }
   }
   gpr_log(GPR_DEBUG, "spins: %" PRIdPTR, pa.spins);
   gpr_log(GPR_DEBUG, "spins: %" PRIdPTR, pa.spins);
-  for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) {
-    gpr_thd_join(thds[i]);
+  for (auto& th : thds) {
+    th.Join();
   }
   }
   gpr_mpscq_destroy(&q);
   gpr_mpscq_destroy(&q);
 }
 }

+ 11 - 11
test/core/gpr/spinlock_test.cc

@@ -16,24 +16,26 @@
  *
  *
  */
  */
 
 
-/* Test of gpr synchronization support. */
+/* Test of gpr spin-lock support. */
 
 
 #include "src/core/lib/gpr/spinlock.h"
 #include "src/core/lib/gpr/spinlock.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
 #include <grpc/support/alloc.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/log.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/time.h>
 #include <grpc/support/time.h>
-#include <stdio.h>
-#include <stdlib.h>
 
 
-#include "src/core/lib/gpr/thd.h"
+#include "src/core/lib/gprpp/thd.h"
 #include "test/core/util/test_config.h"
 #include "test/core/util/test_config.h"
 
 
 /* ------------------------------------------------- */
 /* ------------------------------------------------- */
 /* Tests for gpr_spinlock. */
 /* Tests for gpr_spinlock. */
 struct test {
 struct test {
   int thread_count; /* number of threads */
   int thread_count; /* number of threads */
-  gpr_thd_id* threads;
+  grpc_core::Thread* threads;
 
 
   int64_t iterations; /* number of iterations per thread */
   int64_t iterations; /* number of iterations per thread */
   int64_t counter;
   int64_t counter;
@@ -46,7 +48,7 @@ struct test {
 static struct test* test_new(int threads, int64_t iterations, int incr_step) {
 static struct test* test_new(int threads, int64_t iterations, int incr_step) {
   struct test* m = static_cast<struct test*>(gpr_malloc(sizeof(*m)));
   struct test* m = static_cast<struct test*>(gpr_malloc(sizeof(*m)));
   m->thread_count = threads;
   m->thread_count = threads;
-  m->threads = static_cast<gpr_thd_id*>(
+  m->threads = static_cast<grpc_core::Thread*>(
       gpr_malloc(sizeof(*m->threads) * static_cast<size_t>(threads)));
       gpr_malloc(sizeof(*m->threads) * static_cast<size_t>(threads)));
   m->iterations = iterations;
   m->iterations = iterations;
   m->counter = 0;
   m->counter = 0;
@@ -66,10 +68,8 @@ static void test_destroy(struct test* m) {
 static void test_create_threads(struct test* m, void (*body)(void* arg)) {
 static void test_create_threads(struct test* m, void (*body)(void* arg)) {
   int i;
   int i;
   for (i = 0; i != m->thread_count; i++) {
   for (i = 0; i != m->thread_count; i++) {
-    gpr_thd_options opt = gpr_thd_options_default();
-    gpr_thd_options_set_joinable(&opt);
-    GPR_ASSERT(
-        gpr_thd_new(&m->threads[i], "grpc_create_threads", body, m, &opt));
+    m->threads[i] = grpc_core::Thread("grpc_create_threads", body, m);
+    m->threads[i].Start();
   }
   }
 }
 }
 
 
@@ -77,7 +77,7 @@ static void test_create_threads(struct test* m, void (*body)(void* arg)) {
 static void test_wait(struct test* m) {
 static void test_wait(struct test* m) {
   int i;
   int i;
   for (i = 0; i != m->thread_count; i++) {
   for (i = 0; i != m->thread_count; i++) {
-    gpr_thd_join(m->threads[i]);
+    m->threads[i].Join();
   }
   }
 }
 }
 
 

+ 37 - 24
test/core/gpr/sync_test.cc

@@ -18,14 +18,16 @@
 
 
 /* Test of gpr synchronization support. */
 /* Test of gpr synchronization support. */
 
 
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/sync.h>
-#include <grpc/support/time.h>
+
 #include <stdio.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdlib.h>
 
 
-#include "src/core/lib/gpr/thd.h"
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/time.h>
+
+#include "src/core/lib/gprpp/thd.h"
 #include "test/core/util/test_config.h"
 #include "test/core/util/test_config.h"
 
 
 /* ==================Example use of interface===================
 /* ==================Example use of interface===================
@@ -133,7 +135,8 @@ int queue_remove(queue* q, int* head, gpr_timespec abs_deadline) {
 /* ------------------------------------------------- */
 /* ------------------------------------------------- */
 /* Tests for gpr_mu and gpr_cv, and the queue example. */
 /* Tests for gpr_mu and gpr_cv, and the queue example. */
 struct test {
 struct test {
-  int threads; /* number of threads */
+  int nthreads; /* number of threads */
+  grpc_core::Thread* threads;
 
 
   int64_t iterations; /* number of iterations per thread */
   int64_t iterations; /* number of iterations per thread */
   int64_t counter;
   int64_t counter;
@@ -157,13 +160,15 @@ struct test {
 };
 };
 
 
 /* Return pointer to a new struct test. */
 /* Return pointer to a new struct test. */
-static struct test* test_new(int threads, int64_t iterations, int incr_step) {
+static struct test* test_new(int nthreads, int64_t iterations, int incr_step) {
   struct test* m = static_cast<struct test*>(gpr_malloc(sizeof(*m)));
   struct test* m = static_cast<struct test*>(gpr_malloc(sizeof(*m)));
-  m->threads = threads;
+  m->nthreads = nthreads;
+  m->threads = static_cast<grpc_core::Thread*>(
+      gpr_malloc(sizeof(*m->threads) * nthreads));
   m->iterations = iterations;
   m->iterations = iterations;
   m->counter = 0;
   m->counter = 0;
   m->thread_count = 0;
   m->thread_count = 0;
-  m->done = threads;
+  m->done = nthreads;
   m->incr_step = incr_step;
   m->incr_step = incr_step;
   gpr_mu_init(&m->mu);
   gpr_mu_init(&m->mu);
   gpr_cv_init(&m->cv);
   gpr_cv_init(&m->cv);
@@ -171,7 +176,7 @@ static struct test* test_new(int threads, int64_t iterations, int incr_step) {
   queue_init(&m->q);
   queue_init(&m->q);
   gpr_stats_init(&m->stats_counter, 0);
   gpr_stats_init(&m->stats_counter, 0);
   gpr_ref_init(&m->refcount, 0);
   gpr_ref_init(&m->refcount, 0);
-  gpr_ref_init(&m->thread_refcount, threads);
+  gpr_ref_init(&m->thread_refcount, nthreads);
   gpr_event_init(&m->event);
   gpr_event_init(&m->event);
   return m;
   return m;
 }
 }
@@ -182,15 +187,16 @@ static void test_destroy(struct test* m) {
   gpr_cv_destroy(&m->cv);
   gpr_cv_destroy(&m->cv);
   gpr_cv_destroy(&m->done_cv);
   gpr_cv_destroy(&m->done_cv);
   queue_destroy(&m->q);
   queue_destroy(&m->q);
+  gpr_free(m->threads);
   gpr_free(m);
   gpr_free(m);
 }
 }
 
 
-/* Create m->threads threads, each running (*body)(m) */
+/* Create m->nthreads threads, each running (*body)(m) */
 static void test_create_threads(struct test* m, void (*body)(void* arg)) {
 static void test_create_threads(struct test* m, void (*body)(void* arg)) {
-  gpr_thd_id id;
   int i;
   int i;
-  for (i = 0; i != m->threads; i++) {
-    GPR_ASSERT(gpr_thd_new(&id, "grpc_create_threads", body, m, nullptr));
+  for (i = 0; i != m->nthreads; i++) {
+    m->threads[i] = grpc_core::Thread("grpc_create_threads", body, m);
+    m->threads[i].Start();
   }
   }
 }
 }
 
 
@@ -201,9 +207,12 @@ static void test_wait(struct test* m) {
     gpr_cv_wait(&m->done_cv, &m->mu, gpr_inf_future(GPR_CLOCK_MONOTONIC));
     gpr_cv_wait(&m->done_cv, &m->mu, gpr_inf_future(GPR_CLOCK_MONOTONIC));
   }
   }
   gpr_mu_unlock(&m->mu);
   gpr_mu_unlock(&m->mu);
+  for (int i = 0; i != m->nthreads; i++) {
+    m->threads[i].Join();
+  }
 }
 }
 
 
-/* Get an integer thread id in the raneg 0..threads-1 */
+/* Get an integer thread id in the raneg 0..nthreads-1 */
 static int thread_id(struct test* m) {
 static int thread_id(struct test* m) {
   int id;
   int id;
   gpr_mu_lock(&m->mu);
   gpr_mu_lock(&m->mu);
@@ -245,16 +254,20 @@ static void test(const char* name, void (*body)(void* m),
     fprintf(stderr, " %ld", static_cast<long>(iterations));
     fprintf(stderr, " %ld", static_cast<long>(iterations));
     fflush(stderr);
     fflush(stderr);
     m = test_new(10, iterations, incr_step);
     m = test_new(10, iterations, incr_step);
+    grpc_core::Thread extra_thd;
     if (extra != nullptr) {
     if (extra != nullptr) {
-      gpr_thd_id id;
-      GPR_ASSERT(gpr_thd_new(&id, name, extra, m, nullptr));
+      extra_thd = grpc_core::Thread(name, extra, m);
+      extra_thd.Start();
       m->done++; /* one more thread to wait for */
       m->done++; /* one more thread to wait for */
     }
     }
     test_create_threads(m, body);
     test_create_threads(m, body);
     test_wait(m);
     test_wait(m);
-    if (m->counter != m->threads * m->iterations * m->incr_step) {
+    if (extra != nullptr) {
+      extra_thd.Join();
+    }
+    if (m->counter != m->nthreads * m->iterations * m->incr_step) {
       fprintf(stderr, "counter %ld  threads %d  iterations %ld\n",
       fprintf(stderr, "counter %ld  threads %d  iterations %ld\n",
-              static_cast<long>(m->counter), m->threads,
+              static_cast<long>(m->counter), m->nthreads,
               static_cast<long>(m->iterations));
               static_cast<long>(m->iterations));
       fflush(stderr);
       fflush(stderr);
       GPR_ASSERT(0);
       GPR_ASSERT(0);
@@ -296,7 +309,7 @@ static void inctry(void* v /*=m*/) {
   mark_thread_done(m);
   mark_thread_done(m);
 }
 }
 
 
-/* Increment counter only when (m->counter%m->threads)==m->thread_id; then mark
+/* Increment counter only when (m->counter%m->nthreads)==m->thread_id; then mark
    thread as done.  */
    thread as done.  */
 static void inc_by_turns(void* v /*=m*/) {
 static void inc_by_turns(void* v /*=m*/) {
   struct test* m = static_cast<struct test*>(v);
   struct test* m = static_cast<struct test*>(v);
@@ -304,7 +317,7 @@ static void inc_by_turns(void* v /*=m*/) {
   int id = thread_id(m);
   int id = thread_id(m);
   for (i = 0; i != m->iterations; i++) {
   for (i = 0; i != m->iterations; i++) {
     gpr_mu_lock(&m->mu);
     gpr_mu_lock(&m->mu);
-    while ((m->counter % m->threads) != id) {
+    while ((m->counter % m->nthreads) != id) {
       gpr_cv_wait(&m->cv, &m->mu, gpr_inf_future(GPR_CLOCK_MONOTONIC));
       gpr_cv_wait(&m->cv, &m->mu, gpr_inf_future(GPR_CLOCK_MONOTONIC));
     }
     }
     m->counter++;
     m->counter++;
@@ -369,12 +382,12 @@ static void many_producers(void* v /*=m*/) {
   mark_thread_done(m);
   mark_thread_done(m);
 }
 }
 
 
-/* Consume elements from m->q until m->threads*m->iterations are seen,
+/* Consume elements from m->q until m->nthreads*m->iterations are seen,
    wait an extra second to confirm that no more elements are arriving,
    wait an extra second to confirm that no more elements are arriving,
    then mark thread as done. */
    then mark thread as done. */
 static void consumer(void* v /*=m*/) {
 static void consumer(void* v /*=m*/) {
   struct test* m = static_cast<struct test*>(v);
   struct test* m = static_cast<struct test*>(v);
-  int64_t n = m->iterations * m->threads;
+  int64_t n = m->iterations * m->nthreads;
   int64_t i;
   int64_t i;
   int value;
   int value;
   for (i = 0; i != n; i++) {
   for (i = 0; i != n; i++) {
@@ -424,11 +437,11 @@ static void refinc(void* v /*=m*/) {
 }
 }
 
 
 /* Wait until m->event is set to (void *)1, then decrement m->refcount by 1
 /* Wait until m->event is set to (void *)1, then decrement m->refcount by 1
-   (m->threads * m->iterations * m->incr_step) times, and ensure that the last
+   (m->nthreads * m->iterations * m->incr_step) times, and ensure that the last
    decrement caused the counter to reach zero, then mark thread as done.  */
    decrement caused the counter to reach zero, then mark thread as done.  */
 static void refcheck(void* v /*=m*/) {
 static void refcheck(void* v /*=m*/) {
   struct test* m = static_cast<struct test*>(v);
   struct test* m = static_cast<struct test*>(v);
-  int64_t n = m->iterations * m->threads * m->incr_step;
+  int64_t n = m->iterations * m->nthreads * m->incr_step;
   int64_t i;
   int64_t i;
   GPR_ASSERT(gpr_event_wait(&m->event, gpr_inf_future(GPR_CLOCK_REALTIME)) ==
   GPR_ASSERT(gpr_event_wait(&m->event, gpr_inf_future(GPR_CLOCK_REALTIME)) ==
              (void*)1);
              (void*)1);

+ 0 - 1
test/core/gpr/time_test.cc

@@ -26,7 +26,6 @@
 #include <stdlib.h>
 #include <stdlib.h>
 #include <string.h>
 #include <string.h>
 
 
-#include "src/core/lib/gpr/thd.h"
 #include "test/core/util/test_config.h"
 #include "test/core/util/test_config.h"
 
 
 static void to_fp(void* arg, const char* buf, size_t len) {
 static void to_fp(void* arg, const char* buf, size_t len) {

+ 12 - 13
test/core/gpr/tls_test.cc

@@ -18,13 +18,15 @@
 
 
 /* Test of gpr thread local storage support. */
 /* Test of gpr thread local storage support. */
 
 
-#include <grpc/support/log.h>
-#include <grpc/support/sync.h>
+#include "src/core/lib/gpr/tls.h"
+
 #include <stdio.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdlib.h>
 
 
-#include "src/core/lib/gpr/thd.h"
-#include "src/core/lib/gpr/tls.h"
+#include <grpc/support/log.h>
+#include <grpc/support/sync.h>
+
+#include "src/core/lib/gprpp/thd.h"
 #include "test/core/util/test_config.h"
 #include "test/core/util/test_config.h"
 
 
 #define NUM_THREADS 100
 #define NUM_THREADS 100
@@ -46,21 +48,18 @@ static void thd_body(void* arg) {
 /* ------------------------------------------------- */
 /* ------------------------------------------------- */
 
 
 int main(int argc, char* argv[]) {
 int main(int argc, char* argv[]) {
-  gpr_thd_options opt = gpr_thd_options_default();
-  int i;
-  gpr_thd_id threads[NUM_THREADS];
+  grpc_core::Thread threads[NUM_THREADS];
 
 
   grpc_test_init(argc, argv);
   grpc_test_init(argc, argv);
 
 
   gpr_tls_init(&test_var);
   gpr_tls_init(&test_var);
 
 
-  gpr_thd_options_set_joinable(&opt);
-
-  for (i = 0; i < NUM_THREADS; i++) {
-    gpr_thd_new(&threads[i], "grpc_tls_test", thd_body, nullptr, &opt);
+  for (auto& th : threads) {
+    th = grpc_core::Thread("grpc_tls_test", thd_body, nullptr);
+    th.Start();
   }
   }
-  for (i = 0; i < NUM_THREADS; i++) {
-    gpr_thd_join(threads[i]);
+  for (auto& th : threads) {
+    th.Join();
   }
   }
 
 
   gpr_tls_destroy(&test_var);
   gpr_tls_destroy(&test_var);

+ 19 - 10
test/core/gprpp/BUILD

@@ -24,7 +24,6 @@ grpc_cc_test(
     language = "C++",
     language = "C++",
     deps = [
     deps = [
         "//:gpr",
         "//:gpr",
-        "//:gpr++_base",
         "//test/core/util:gpr_test_util",
         "//test/core/util:gpr_test_util",
     ],
     ],
 )
 )
@@ -37,7 +36,7 @@ grpc_cc_test(
     ],
     ],
     language = "C++",
     language = "C++",
     deps = [
     deps = [
-        "//:gpr++_base",
+        "//:gpr_base",
         "//test/core/util:gpr_test_util",
         "//test/core/util:gpr_test_util",
     ],
     ],
 )
 )
@@ -58,39 +57,49 @@ grpc_cc_test(
 grpc_cc_test(
 grpc_cc_test(
     name = "orphanable_test",
     name = "orphanable_test",
     srcs = ["orphanable_test.cc"],
     srcs = ["orphanable_test.cc"],
+    external_deps = [
+        "gtest",
+    ],
     language = "C++",
     language = "C++",
     deps = [
     deps = [
         "//:orphanable",
         "//:orphanable",
         "//test/core/util:gpr_test_util",
         "//test/core/util:gpr_test_util",
     ],
     ],
-    external_deps = [
-        "gtest",
-    ],
 )
 )
 
 
 grpc_cc_test(
 grpc_cc_test(
     name = "ref_counted_test",
     name = "ref_counted_test",
     srcs = ["ref_counted_test.cc"],
     srcs = ["ref_counted_test.cc"],
+    external_deps = [
+        "gtest",
+    ],
     language = "C++",
     language = "C++",
     deps = [
     deps = [
         "//:ref_counted",
         "//:ref_counted",
         "//test/core/util:gpr_test_util",
         "//test/core/util:gpr_test_util",
     ],
     ],
-    external_deps = [
-        "gtest",
-    ],
 )
 )
 
 
 grpc_cc_test(
 grpc_cc_test(
     name = "ref_counted_ptr_test",
     name = "ref_counted_ptr_test",
     srcs = ["ref_counted_ptr_test.cc"],
     srcs = ["ref_counted_ptr_test.cc"],
+    external_deps = [
+        "gtest",
+    ],
     language = "C++",
     language = "C++",
     deps = [
     deps = [
         "//:ref_counted",
         "//:ref_counted",
         "//:ref_counted_ptr",
         "//:ref_counted_ptr",
         "//test/core/util:gpr_test_util",
         "//test/core/util:gpr_test_util",
     ],
     ],
-    external_deps = [
-        "gtest",
+)
+
+grpc_cc_test(
+    name = "thd_test",
+    srcs = ["thd_test.cc"],
+    language = "C++",
+    deps = [
+        "//:gpr",
+        "//test/core/util:gpr_test_util",
     ],
     ],
 )
 )

+ 0 - 1
test/core/gprpp/manual_constructor_test.cc

@@ -26,7 +26,6 @@
 #include <stdlib.h>
 #include <stdlib.h>
 #include <cstring>
 #include <cstring>
 
 
-#include "src/core/lib/gpr/thd.h"
 #include "src/core/lib/gprpp/abstract.h"
 #include "src/core/lib/gprpp/abstract.h"
 #include "test/core/util/test_config.h"
 #include "test/core/util/test_config.h"
 
 

+ 31 - 36
test/core/gpr/thd_test.cc → test/core/gprpp/thd_test.cc

@@ -18,17 +18,18 @@
 
 
 /* Test of gpr thread support. */
 /* Test of gpr thread support. */
 
 
-#include "src/core/lib/gpr/thd.h"
+#include "src/core/lib/gprpp/thd.h"
+
+#include <stdio.h>
+#include <stdlib.h>
 
 
 #include <grpc/support/log.h>
 #include <grpc/support/log.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/time.h>
 #include <grpc/support/time.h>
-#include <stdio.h>
-#include <stdlib.h>
 
 
 #include "test/core/util/test_config.h"
 #include "test/core/util/test_config.h"
 
 
-#define NUM_THREADS 300
+#define NUM_THREADS 100
 
 
 struct test {
 struct test {
   gpr_mu mu;
   gpr_mu mu;
@@ -38,7 +39,7 @@ struct test {
 };
 };
 
 
 /* A Thread body.   Decrement t->n, and if is becomes zero, set t->done. */
 /* A Thread body.   Decrement t->n, and if is becomes zero, set t->done. */
-static void thd_body(void* v) {
+static void thd_body1(void* v) {
   struct test* t = static_cast<struct test*>(v);
   struct test* t = static_cast<struct test*>(v);
   gpr_mu_lock(&t->mu);
   gpr_mu_lock(&t->mu);
   t->n--;
   t->n--;
@@ -49,48 +50,42 @@ static void thd_body(void* v) {
   gpr_mu_unlock(&t->mu);
   gpr_mu_unlock(&t->mu);
 }
 }
 
 
-static void thd_body_joinable(void* v) {}
-
-/* Test thread options work as expected */
-static void test_options(void) {
-  gpr_thd_options options = gpr_thd_options_default();
-  GPR_ASSERT(!gpr_thd_options_is_joinable(&options));
-  GPR_ASSERT(gpr_thd_options_is_detached(&options));
-  gpr_thd_options_set_joinable(&options);
-  GPR_ASSERT(gpr_thd_options_is_joinable(&options));
-  GPR_ASSERT(!gpr_thd_options_is_detached(&options));
-  gpr_thd_options_set_detached(&options);
-  GPR_ASSERT(!gpr_thd_options_is_joinable(&options));
-  GPR_ASSERT(gpr_thd_options_is_detached(&options));
-}
-
-/* Test that we can create a number of threads and wait for them. */
-static void test(void) {
-  int i;
-  gpr_thd_id thd;
-  gpr_thd_id thds[NUM_THREADS];
+/* Test that we can create a number of threads, wait for them, and join them. */
+static void test1(void) {
+  grpc_core::Thread thds[NUM_THREADS];
   struct test t;
   struct test t;
-  gpr_thd_options options = gpr_thd_options_default();
   gpr_mu_init(&t.mu);
   gpr_mu_init(&t.mu);
   gpr_cv_init(&t.done_cv);
   gpr_cv_init(&t.done_cv);
   t.n = NUM_THREADS;
   t.n = NUM_THREADS;
   t.is_done = 0;
   t.is_done = 0;
-  for (i = 0; i < NUM_THREADS; i++) {
-    GPR_ASSERT(gpr_thd_new(&thd, "grpc_thread_test", &thd_body, &t, nullptr));
+  for (auto& th : thds) {
+    th = grpc_core::Thread("grpc_thread_body1_test", &thd_body1, &t);
+    th.Start();
   }
   }
   gpr_mu_lock(&t.mu);
   gpr_mu_lock(&t.mu);
   while (!t.is_done) {
   while (!t.is_done) {
     gpr_cv_wait(&t.done_cv, &t.mu, gpr_inf_future(GPR_CLOCK_REALTIME));
     gpr_cv_wait(&t.done_cv, &t.mu, gpr_inf_future(GPR_CLOCK_REALTIME));
   }
   }
   gpr_mu_unlock(&t.mu);
   gpr_mu_unlock(&t.mu);
+  for (auto& th : thds) {
+    th.Join();
+  }
   GPR_ASSERT(t.n == 0);
   GPR_ASSERT(t.n == 0);
-  gpr_thd_options_set_joinable(&options);
-  for (i = 0; i < NUM_THREADS; i++) {
-    GPR_ASSERT(gpr_thd_new(&thds[i], "grpc_joinable_thread_test",
-                           &thd_body_joinable, nullptr, &options));
+}
+
+static void thd_body2(void* v) {}
+
+/* Test that we can create a number of threads and join them. */
+static void test2(void) {
+  grpc_core::Thread thds[NUM_THREADS];
+  for (auto& th : thds) {
+    bool ok;
+    th = grpc_core::Thread("grpc_thread_body2_test", &thd_body2, nullptr, &ok);
+    GPR_ASSERT(ok);
+    th.Start();
   }
   }
-  for (i = 0; i < NUM_THREADS; i++) {
-    gpr_thd_join(thds[i]);
+  for (auto& th : thds) {
+    th.Join();
   }
   }
 }
 }
 
 
@@ -98,7 +93,7 @@ static void test(void) {
 
 
 int main(int argc, char* argv[]) {
 int main(int argc, char* argv[]) {
   grpc_test_init(argc, argv);
   grpc_test_init(argc, argv);
-  test_options();
-  test();
+  test1();
+  test2();
   return 0;
   return 0;
 }
 }

+ 6 - 7
test/core/handshake/client_ssl.cc

@@ -35,7 +35,7 @@
 #include <grpc/support/log.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 #include <grpc/support/string_util.h>
 
 
-#include "src/core/lib/gpr/thd.h"
+#include "src/core/lib/gprpp/thd.h"
 #include "src/core/lib/iomgr/load_file.h"
 #include "src/core/lib/iomgr/load_file.h"
 #include "test/core/util/port.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
 #include "test/core/util/test_config.h"
@@ -230,12 +230,11 @@ static bool client_ssl_test(char* server_alpn_preferred) {
   GPR_ASSERT(server_socket > 0 && port > 0);
   GPR_ASSERT(server_socket > 0 && port > 0);
 
 
   // Launch the TLS server thread.
   // Launch the TLS server thread.
-  gpr_thd_options thdopt = gpr_thd_options_default();
-  gpr_thd_id thdid;
-  gpr_thd_options_set_joinable(&thdopt);
   server_args args = {server_socket, server_alpn_preferred};
   server_args args = {server_socket, server_alpn_preferred};
-  GPR_ASSERT(gpr_thd_new(&thdid, "grpc_client_ssl_test", server_thread, &args,
-                         &thdopt));
+  bool ok;
+  grpc_core::Thread thd("grpc_client_ssl_test", server_thread, &args, &ok);
+  GPR_ASSERT(ok);
+  thd.Start();
 
 
   // Load key pair and establish client SSL credentials.
   // Load key pair and establish client SSL credentials.
   grpc_ssl_pem_key_cert_pair pem_key_cert_pair;
   grpc_ssl_pem_key_cert_pair pem_key_cert_pair;
@@ -303,7 +302,7 @@ static bool client_ssl_test(char* server_alpn_preferred) {
   grpc_slice_unref(key_slice);
   grpc_slice_unref(key_slice);
   grpc_slice_unref(ca_slice);
   grpc_slice_unref(ca_slice);
 
 
-  gpr_thd_join(thdid);
+  thd.Join();
 
 
   grpc_shutdown();
   grpc_shutdown();
 
 

+ 0 - 1
test/core/handshake/readahead_handshaker_server_ssl.cc

@@ -30,7 +30,6 @@
 #include <grpc/support/string_util.h>
 #include <grpc/support/string_util.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/sync.h>
 
 
-#include "src/core/lib/gpr/thd.h"
 #include "src/core/lib/iomgr/load_file.h"
 #include "src/core/lib/iomgr/load_file.h"
 #include "test/core/util/port.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
 #include "test/core/util/test_config.h"

+ 0 - 1
test/core/handshake/server_ssl.cc

@@ -30,7 +30,6 @@
 #include <grpc/support/string_util.h>
 #include <grpc/support/string_util.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/sync.h>
 
 
-#include "src/core/lib/gpr/thd.h"
 #include "src/core/lib/iomgr/load_file.h"
 #include "src/core/lib/iomgr/load_file.h"
 #include "test/core/util/port.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
 #include "test/core/util/test_config.h"

+ 6 - 7
test/core/handshake/server_ssl_common.cc

@@ -32,7 +32,7 @@
 #include <grpc/support/string_util.h>
 #include <grpc/support/string_util.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/sync.h>
 
 
-#include "src/core/lib/gpr/thd.h"
+#include "src/core/lib/gprpp/thd.h"
 #include "src/core/lib/iomgr/load_file.h"
 #include "src/core/lib/iomgr/load_file.h"
 #include "test/core/util/port.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
 #include "test/core/util/test_config.h"
@@ -138,11 +138,10 @@ bool server_ssl_test(const char* alpn_list[], unsigned int alpn_list_len,
   gpr_event_init(&client_handshake_complete);
   gpr_event_init(&client_handshake_complete);
 
 
   // Launch the gRPC server thread.
   // Launch the gRPC server thread.
-  gpr_thd_options thdopt = gpr_thd_options_default();
-  gpr_thd_id thdid;
-  gpr_thd_options_set_joinable(&thdopt);
-  GPR_ASSERT(
-      gpr_thd_new(&thdid, "grpc_ssl_test", server_thread, &port, &thdopt));
+  bool ok;
+  grpc_core::Thread thd("grpc_ssl_test", server_thread, &port, &ok);
+  GPR_ASSERT(ok);
+  thd.Start();
 
 
   SSL_load_error_strings();
   SSL_load_error_strings();
   OpenSSL_add_ssl_algorithms();
   OpenSSL_add_ssl_algorithms();
@@ -235,7 +234,7 @@ bool server_ssl_test(const char* alpn_list[], unsigned int alpn_list_len,
   EVP_cleanup();
   EVP_cleanup();
   close(sock);
   close(sock);
 
 
-  gpr_thd_join(thdid);
+  thd.Join();
 
 
   grpc_shutdown();
   grpc_shutdown();
 
 

+ 0 - 1
test/core/handshake/server_ssl_common.h

@@ -26,7 +26,6 @@
 #include <grpc/support/string_util.h>
 #include <grpc/support/string_util.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/sync.h>
 
 
-#include "src/core/lib/gpr/thd.h"
 #include "src/core/lib/iomgr/load_file.h"
 #include "src/core/lib/iomgr/load_file.h"
 #include "test/core/util/port.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
 #include "test/core/util/test_config.h"

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно