blob: 281e41c9a88724f56fdafa928f55456ac23c0367 [file] [log] [blame]
murgatroid999b83bd72016-01-05 09:50:04 -08001/*
2 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02003 * Copyright 2016 gRPC authors.
murgatroid999b83bd72016-01-05 09:50:04 -08004 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02005 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
murgatroid999b83bd72016-01-05 09:50:04 -08008 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02009 * http://www.apache.org/licenses/LICENSE-2.0
murgatroid999b83bd72016-01-05 09:50:04 -080010 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +020011 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
murgatroid999b83bd72016-01-05 09:50:04 -080016 *
17 */
18
Nicolas "Pixel" Nobled51d1212016-01-31 11:33:19 +010019#include <ruby/ruby.h>
Nicolas "Pixel" Noble9fcdc872016-05-05 06:15:34 +020020
murgatroid999b83bd72016-01-05 09:50:04 -080021#include "rb_event_thread.h"
Craig Tiller5b1c5f22017-04-19 09:52:18 -070022#include "rb_grpc_imports.generated.h"
murgatroid999b83bd72016-01-05 09:50:04 -080023
24#include <stdbool.h>
25
murgatroid999b83bd72016-01-05 09:50:04 -080026#include <grpc/support/alloc.h>
Craig Tiller5b1c5f22017-04-19 09:52:18 -070027#include <grpc/support/log.h>
murgatroid999b83bd72016-01-05 09:50:04 -080028#include <grpc/support/sync.h>
29#include <grpc/support/time.h>
Craig Tiller5b1c5f22017-04-19 09:52:18 -070030#include <ruby/thread.h>
murgatroid999b83bd72016-01-05 09:50:04 -080031
32typedef struct grpc_rb_event {
33 // callback will be called with argument while holding the GVL
Craig Tillerbaa14a92017-11-03 09:09:36 -070034 void (*callback)(void*);
35 void* argument;
murgatroid999b83bd72016-01-05 09:50:04 -080036
Craig Tillerbaa14a92017-11-03 09:09:36 -070037 struct grpc_rb_event* next;
murgatroid999b83bd72016-01-05 09:50:04 -080038} grpc_rb_event;
39
40typedef struct grpc_rb_event_queue {
Craig Tillerbaa14a92017-11-03 09:09:36 -070041 grpc_rb_event* head;
42 grpc_rb_event* tail;
murgatroid999b83bd72016-01-05 09:50:04 -080043
murgatroid99cc2b8d42016-01-07 17:32:34 -080044 gpr_mu mu;
45 gpr_cv cv;
murgatroid999b83bd72016-01-05 09:50:04 -080046
47 // Indicates that the thread should stop waiting
48 bool abort;
49} grpc_rb_event_queue;
50
51static grpc_rb_event_queue event_queue;
52
Craig Tillerbaa14a92017-11-03 09:09:36 -070053void grpc_rb_event_queue_enqueue(void (*callback)(void*), void* argument) {
54 grpc_rb_event* event = gpr_malloc(sizeof(grpc_rb_event));
murgatroid999b83bd72016-01-05 09:50:04 -080055 event->callback = callback;
56 event->argument = argument;
57 event->next = NULL;
murgatroid99cc2b8d42016-01-07 17:32:34 -080058 gpr_mu_lock(&event_queue.mu);
murgatroid999b83bd72016-01-05 09:50:04 -080059 if (event_queue.tail == NULL) {
60 event_queue.head = event_queue.tail = event;
61 } else {
62 event_queue.tail->next = event;
63 event_queue.tail = event;
64 }
murgatroid99cc2b8d42016-01-07 17:32:34 -080065 gpr_cv_signal(&event_queue.cv);
66 gpr_mu_unlock(&event_queue.mu);
murgatroid999b83bd72016-01-05 09:50:04 -080067}
68
Craig Tillerbaa14a92017-11-03 09:09:36 -070069static grpc_rb_event* grpc_rb_event_queue_dequeue() {
70 grpc_rb_event* event;
murgatroid999b83bd72016-01-05 09:50:04 -080071 if (event_queue.head == NULL) {
72 event = NULL;
73 } else {
74 event = event_queue.head;
75 if (event_queue.head->next == NULL) {
76 event_queue.head = event_queue.tail = NULL;
77 } else {
78 event_queue.head = event_queue.head->next;
79 }
80 }
81 return event;
82}
83
84static void grpc_rb_event_queue_destroy() {
murgatroid99cc2b8d42016-01-07 17:32:34 -080085 gpr_mu_destroy(&event_queue.mu);
86 gpr_cv_destroy(&event_queue.cv);
murgatroid999b83bd72016-01-05 09:50:04 -080087}
88
Craig Tillerbaa14a92017-11-03 09:09:36 -070089static void* grpc_rb_wait_for_event_no_gil(void* param) {
90 grpc_rb_event* event = NULL;
Nicolas "Pixel" Noble7b92db62016-01-26 22:46:34 +010091 (void)param;
murgatroid99cc2b8d42016-01-07 17:32:34 -080092 gpr_mu_lock(&event_queue.mu);
Alexander Polcynb2c0b7b2017-04-27 00:26:25 -070093 while (!event_queue.abort) {
94 if ((event = grpc_rb_event_queue_dequeue()) != NULL) {
95 gpr_mu_unlock(&event_queue.mu);
96 return event;
97 }
Craig Tiller5b1c5f22017-04-19 09:52:18 -070098 gpr_cv_wait(&event_queue.cv, &event_queue.mu,
murgatroid999b83bd72016-01-05 09:50:04 -080099 gpr_inf_future(GPR_CLOCK_REALTIME));
murgatroid999b83bd72016-01-05 09:50:04 -0800100 }
murgatroid99cc2b8d42016-01-07 17:32:34 -0800101 gpr_mu_unlock(&event_queue.mu);
Alexander Polcynb2c0b7b2017-04-27 00:26:25 -0700102 return NULL;
murgatroid999b83bd72016-01-05 09:50:04 -0800103}
104
Craig Tillerbaa14a92017-11-03 09:09:36 -0700105static void grpc_rb_event_unblocking_func(void* arg) {
Nicolas "Pixel" Noble7b92db62016-01-26 22:46:34 +0100106 (void)arg;
murgatroid99cc2b8d42016-01-07 17:32:34 -0800107 gpr_mu_lock(&event_queue.mu);
murgatroid999b83bd72016-01-05 09:50:04 -0800108 event_queue.abort = true;
murgatroid99cc2b8d42016-01-07 17:32:34 -0800109 gpr_cv_signal(&event_queue.cv);
110 gpr_mu_unlock(&event_queue.mu);
murgatroid999b83bd72016-01-05 09:50:04 -0800111}
112
113/* This is the implementation of the thread that handles auth metadata plugin
114 * events */
115static VALUE grpc_rb_event_thread(VALUE arg) {
Craig Tillerbaa14a92017-11-03 09:09:36 -0700116 grpc_rb_event* event;
Nicolas "Pixel" Noble7b92db62016-01-26 22:46:34 +0100117 (void)arg;
Craig Tiller5b1c5f22017-04-19 09:52:18 -0700118 while (true) {
Craig Tillerbaa14a92017-11-03 09:09:36 -0700119 event = (grpc_rb_event*)rb_thread_call_without_gvl(
Craig Tiller5b1c5f22017-04-19 09:52:18 -0700120 grpc_rb_wait_for_event_no_gil, NULL, grpc_rb_event_unblocking_func,
121 NULL);
murgatroid999b83bd72016-01-05 09:50:04 -0800122 if (event == NULL) {
123 // Indicates that the thread needs to shut down
124 break;
125 } else {
126 event->callback(event->argument);
127 gpr_free(event);
128 }
129 }
130 grpc_rb_event_queue_destroy();
131 return Qnil;
132}
133
134void grpc_rb_event_queue_thread_start() {
murgatroid999b83bd72016-01-05 09:50:04 -0800135 event_queue.head = event_queue.tail = NULL;
136 event_queue.abort = false;
murgatroid99cc2b8d42016-01-07 17:32:34 -0800137 gpr_mu_init(&event_queue.mu);
138 gpr_cv_init(&event_queue.cv);
murgatroid999b83bd72016-01-05 09:50:04 -0800139
140 rb_thread_create(grpc_rb_event_thread, NULL);
141}