|
|
|
@ -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 |
|
|
|
|