add code to unregister endpoints
diff --git a/src/core/lib/iomgr/network_status_tracker.c b/src/core/lib/iomgr/network_status_tracker.c
index 6e43236..f4f8e97 100644
--- a/src/core/lib/iomgr/network_status_tracker.c
+++ b/src/core/lib/iomgr/network_status_tracker.c
@@ -33,6 +33,7 @@
#include "src/core/lib/iomgr/endpoint.h"
#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
typedef struct endpoint_ll_node {
grpc_endpoint *ep;
@@ -40,9 +41,13 @@
} endpoint_ll_node;
static endpoint_ll_node *head = NULL;
+static gpr_mu g_endpoint_mutex;
+static bool g_init_done = false;
-// TODO(makarandd): Install callback with OS to monitor network status.
void grpc_initialize_network_status_monitor() {
+ g_init_done = true;
+ gpr_mu_init(&g_endpoint_mutex);
+ // TODO(makarandd): Install callback with OS to monitor network status.
}
void grpc_destroy_network_status_monitor() {
@@ -51,9 +56,15 @@
gpr_free(curr);
curr = next;
}
+ gpr_mu_destroy(&g_endpoint_mutex);
}
void grpc_network_status_register_endpoint(grpc_endpoint *ep) {
+ if (!g_init_done) {
+ grpc_initialize_network_status_monitor();
+ }
+ gpr_mu_lock(&g_endpoint_mutex);
+ gpr_log(GPR_DEBUG, "Register endpoint %p", ep);
if (head == NULL) {
head = (endpoint_ll_node *)gpr_malloc(sizeof(endpoint_ll_node));
head->ep = ep;
@@ -64,19 +75,50 @@
head->ep = ep;
head->next = prev_head;
}
+ gpr_mu_unlock(&g_endpoint_mutex);
+}
+
+void grpc_network_status_unregister_endpoint(grpc_endpoint *ep) {
+ gpr_mu_lock(&g_endpoint_mutex);
+ GPR_ASSERT(head);
+ gpr_log(GPR_DEBUG, "Unregister endpoint %p", ep);
+ bool found = false;
+ endpoint_ll_node *prev = head;
+ // if we're unregistering the head, just move head to the next
+ if (ep == head->ep) {
+ head = head->next;
+ gpr_free(prev);
+ found = true;
+ } else {
+ for (endpoint_ll_node *curr = head->next; curr != NULL; curr = curr->next) {
+ if (ep == curr->ep) {
+ prev->next = curr->next;
+ gpr_free(curr);
+ found = true;
+ break;
+ }
+ prev = curr;
+ }
+ }
+ gpr_mu_unlock(&g_endpoint_mutex);
+ GPR_ASSERT(found);
}
// Walk the linked-list from head and execute shutdown. It is possible that
// other threads might be in the process of shutdown as well, but that has
-// no side effect.
+// no side effect since endpoint shutdown is idempotent.
void grpc_network_status_shutdown_all_endpoints() {
+ gpr_mu_lock(&g_endpoint_mutex);
if (head == NULL) {
+ gpr_mu_unlock(&g_endpoint_mutex);
return;
}
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
for (endpoint_ll_node *curr = head; curr != NULL; curr = curr->next) {
+ gpr_log(GPR_DEBUG, "Shutting down endpoint %p", curr->ep);
curr->ep->vtable->shutdown(&exec_ctx, curr->ep);
}
+ gpr_mu_unlock(&g_endpoint_mutex);
grpc_exec_ctx_finish(&exec_ctx);
}