|  | @@ -1,6 +1,6 @@
 | 
	
		
			
				|  |  |  /*
 | 
	
		
			
				|  |  |   *
 | 
	
		
			
				|  |  | - * Copyright 2015 gRPC authors.
 | 
	
		
			
				|  |  | + * Copyright 2019 gRPC authors.
 | 
	
		
			
				|  |  |   *
 | 
	
		
			
				|  |  |   * Licensed under the Apache License, Version 2.0 (the "License");
 | 
	
		
			
				|  |  |   * you may not use this file except in compliance with the License.
 | 
	
	
		
			
				|  | @@ -15,31 +15,27 @@
 | 
	
		
			
				|  |  |   * limitations under the License.
 | 
	
		
			
				|  |  |   *
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  | +#if defined(GRPC_WINSOCK_SOCKET)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -#include "src/core/lib/iomgr/port.h"
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -#include "src/core/lib/iomgr/tcp_server.h"
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -#include <chrono>
 | 
	
		
			
				|  |  | -#include <condition_variable>
 | 
	
		
			
				|  |  | -#include <iostream>
 | 
	
		
			
				|  |  | -#include <thread>
 | 
	
		
			
				|  |  |  #include <vector>
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #include <grpc/grpc.h>
 | 
	
		
			
				|  |  | -#include <grpc/support/alloc.h>
 | 
	
		
			
				|  |  | -#include <grpc/support/log.h>
 | 
	
		
			
				|  |  | -#include <grpc/support/sync.h>
 | 
	
		
			
				|  |  |  #include <grpc/support/time.h>
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +#include "src/core/lib/gprpp/thd.h"
 | 
	
		
			
				|  |  |  #include "src/core/lib/iomgr/exec_ctx.h"
 | 
	
		
			
				|  |  |  #include "src/core/lib/iomgr/iocp_windows.h"
 | 
	
		
			
				|  |  |  #include "src/core/lib/iomgr/iomgr_internal.h"
 | 
	
		
			
				|  |  |  #include "src/core/lib/iomgr/pollset.h"
 | 
	
		
			
				|  |  |  #include "src/core/lib/iomgr/pollset_windows.h"
 | 
	
		
			
				|  |  |  #include "src/core/lib/surface/init.h"
 | 
	
		
			
				|  |  | +#include "test/core/util/test_config.h"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -#define LOG_TEST(x) gpr_log(GPR_INFO, "%s", #x)
 | 
	
		
			
				|  |  | +struct ThreadParams {
 | 
	
		
			
				|  |  | +  gpr_cv cv;
 | 
	
		
			
				|  |  | +  gpr_mu mu;
 | 
	
		
			
				|  |  | +  int complete;
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  int main(int argc, char** argv) {
 | 
	
		
			
				|  |  |    grpc_init();
 | 
	
	
		
			
				|  | @@ -60,49 +56,64 @@ int main(int argc, char** argv) {
 | 
	
		
			
				|  |  |    // specific grpc_pollset_kick will also kick pollers from other pollsets
 | 
	
		
			
				|  |  |    // if there are no pollers in the current pollset. This frees up the
 | 
	
		
			
				|  |  |    // last thread and completes the test.
 | 
	
		
			
				|  |  | -  std::condition_variable cv;
 | 
	
		
			
				|  |  | -  std::mutex m;
 | 
	
		
			
				|  |  | -  int complete = 0;
 | 
	
		
			
				|  |  | -  std::vector<std::thread> threads;
 | 
	
		
			
				|  |  | +  ThreadParams params = {};
 | 
	
		
			
				|  |  | +  gpr_cv_init(¶ms.cv);
 | 
	
		
			
				|  |  | +  gpr_mu_init(¶ms.mu);
 | 
	
		
			
				|  |  | +  std::vector<grpc_core::Thread> threads;
 | 
	
		
			
				|  |  |    for (int i = 0; i < 3; i++) {
 | 
	
		
			
				|  |  | -    threads.push_back(std::thread([&]() {
 | 
	
		
			
				|  |  | -      grpc_core::ExecCtx exec_ctx;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      gpr_mu* g_mu;
 | 
	
		
			
				|  |  | -      grpc_pollset g_pollset = {};
 | 
	
		
			
				|  |  | -      grpc_pollset_init(&g_pollset, &g_mu);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      gpr_mu_lock(g_mu);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      // Queue for work and once we're done, make sure to kick the remaining
 | 
	
		
			
				|  |  | -      // threads.
 | 
	
		
			
				|  |  | -      grpc_error* error;
 | 
	
		
			
				|  |  | -      error = grpc_pollset_work(&g_pollset, NULL, GRPC_MILLIS_INF_FUTURE);
 | 
	
		
			
				|  |  | -      error = grpc_pollset_kick(&g_pollset, NULL);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      gpr_mu_unlock(g_mu);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      {
 | 
	
		
			
				|  |  | -        std::unique_lock<std::mutex> lock(m);
 | 
	
		
			
				|  |  | -        complete++;
 | 
	
		
			
				|  |  | -        cv.notify_all();
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -    }));
 | 
	
		
			
				|  |  | +    grpc_core::Thread thd(
 | 
	
		
			
				|  |  | +        "Poller",
 | 
	
		
			
				|  |  | +        [](void* params) {
 | 
	
		
			
				|  |  | +          ThreadParams* tparams = static_cast<ThreadParams*>(params);
 | 
	
		
			
				|  |  | +          grpc_core::ExecCtx exec_ctx;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          gpr_mu* mu;
 | 
	
		
			
				|  |  | +          grpc_pollset pollset = {};
 | 
	
		
			
				|  |  | +          grpc_pollset_init(&pollset, &mu);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          gpr_mu_lock(mu);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          // Queue for work and once we're done, make sure to kick the remaining
 | 
	
		
			
				|  |  | +          // threads.
 | 
	
		
			
				|  |  | +          grpc_millis deadline = grpc_timespec_to_millis_round_up(
 | 
	
		
			
				|  |  | +              grpc_timeout_seconds_to_deadline(5));
 | 
	
		
			
				|  |  | +          grpc_error* error;
 | 
	
		
			
				|  |  | +          error = grpc_pollset_work(&pollset, NULL, deadline);
 | 
	
		
			
				|  |  | +          error = grpc_pollset_kick(&pollset, NULL);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          gpr_mu_unlock(mu);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          {
 | 
	
		
			
				|  |  | +            gpr_mu_lock(&tparams->mu);
 | 
	
		
			
				|  |  | +            tparams->complete++;
 | 
	
		
			
				|  |  | +            gpr_cv_signal(&tparams->cv);
 | 
	
		
			
				|  |  | +            gpr_mu_unlock(&tparams->mu);
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +        },
 | 
	
		
			
				|  |  | +        ¶ms);
 | 
	
		
			
				|  |  | +    thd.Start();
 | 
	
		
			
				|  |  | +    threads.push_back(std::move(thd));
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    // Wait for the threads to start working and then kick one of them.
 | 
	
		
			
				|  |  | -  std::this_thread::sleep_for(std::chrono::milliseconds(10));
 | 
	
		
			
				|  |  | +  gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(10));
 | 
	
		
			
				|  |  |    grpc_iocp_kick();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    // Wait for the threads to complete.
 | 
	
		
			
				|  |  | -  {
 | 
	
		
			
				|  |  | -    std::unique_lock<std::mutex> lock(m);
 | 
	
		
			
				|  |  | -    if (!cv.wait_for(lock, std::chrono::seconds(1),
 | 
	
		
			
				|  |  | -                     [&] { return complete == 3; }))
 | 
	
		
			
				|  |  | -      return EXIT_FAILURE;
 | 
	
		
			
				|  |  | +  gpr_timespec deadline = grpc_timeout_seconds_to_deadline(1);
 | 
	
		
			
				|  |  | +  gpr_mu_lock(¶ms.mu);
 | 
	
		
			
				|  |  | +  while (params.complete != 3 && !gpr_cv_wait(¶ms.cv, ¶ms.mu, deadline))
 | 
	
		
			
				|  |  | +    ;
 | 
	
		
			
				|  |  | +  if (params.complete != 3) {
 | 
	
		
			
				|  |  | +    gpr_mu_unlock(¶ms.mu);
 | 
	
		
			
				|  |  | +    for (auto& t : threads) t.Join();
 | 
	
		
			
				|  |  | +    return EXIT_FAILURE;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  for (auto& t : threads) t.join();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +  gpr_mu_unlock(¶ms.mu);
 | 
	
		
			
				|  |  | +  for (auto& t : threads) t.Join();
 | 
	
		
			
				|  |  |    return EXIT_SUCCESS;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  | +#else /* defined(GRPC_WINSOCK_SOCKET) */
 | 
	
		
			
				|  |  | +int main(int /*argc*/, char** /*argv*/) { return 0; }
 | 
	
		
			
				|  |  | +#endif
 |