Run callbacks without GVL
This commit is contained in:
parent
83237e2303
commit
bd5507d7f6
|
|
@ -129,8 +129,18 @@ abort_ruby_whisper_callback_container_is_present(ruby_whisper_abort_callback_con
|
|||
return !NIL_P(container->callback) || !NIL_P(container->callbacks);
|
||||
}
|
||||
|
||||
static void new_segment_callback(struct whisper_context *ctx, struct whisper_state *state, int n_new, void *user_data) {
|
||||
const ruby_whisper_callback_container *container = (ruby_whisper_callback_container *)user_data;
|
||||
typedef struct {
|
||||
const ruby_whisper_callback_container *container;
|
||||
struct whisper_state *state;
|
||||
int n_new;
|
||||
} call_new_segment_callbacks_args;
|
||||
|
||||
static void*
|
||||
call_new_segment_callbacks(void *v_args) {
|
||||
call_new_segment_callbacks_args *args = (call_new_segment_callbacks_args *)v_args;
|
||||
const ruby_whisper_callback_container *container = args->container;
|
||||
struct whisper_state *state = args->state;
|
||||
int n_new = args->n_new;
|
||||
|
||||
// Currently, doesn't support state because
|
||||
// those require to resolve GC-related problems.
|
||||
|
|
@ -138,11 +148,11 @@ static void new_segment_callback(struct whisper_context *ctx, struct whisper_sta
|
|||
rb_funcall(container->callback, id_call, 4, *container->context, Qnil, INT2NUM(n_new), container->user_data);
|
||||
}
|
||||
if (NIL_P(container->callbacks)) {
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
const long callbacks_len = RARRAY_LEN(container->callbacks);
|
||||
if (0 == callbacks_len) {
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
const int n_segments = whisper_full_n_segments_from_state(state);
|
||||
for (int i = n_new; i > 0; i--) {
|
||||
|
|
@ -153,56 +163,165 @@ static void new_segment_callback(struct whisper_context *ctx, struct whisper_sta
|
|||
rb_funcall(cb, id_call, 1, segment);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void new_segment_callback(struct whisper_context *ctx, struct whisper_state *state, int n_new, void *user_data) {
|
||||
const ruby_whisper_callback_container *container = (ruby_whisper_callback_container *)user_data;
|
||||
if (!ruby_whisper_callback_container_is_present(container)) {
|
||||
return;
|
||||
}
|
||||
|
||||
call_new_segment_callbacks_args args = {
|
||||
container,
|
||||
state,
|
||||
n_new
|
||||
};
|
||||
rb_thread_call_with_gvl(call_new_segment_callbacks, (void *)&args);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
const ruby_whisper_callback_container *container;
|
||||
struct whisper_state *state;
|
||||
int progress_cur;
|
||||
} call_progress_callbacks_args;
|
||||
|
||||
static void*
|
||||
call_progress_callbacks(void *v_args) {
|
||||
call_progress_callbacks_args *args = (call_progress_callbacks_args *)v_args;
|
||||
const ruby_whisper_callback_container *container = args->container;
|
||||
int progress_cur = args->progress_cur;
|
||||
|
||||
// Currently, doesn't support state because
|
||||
// those require to resolve GC-related problems.
|
||||
if (!NIL_P(args->container->callback)) {
|
||||
rb_funcall(container->callback, id_call, 4, *container->context, Qnil, INT2NUM(progress_cur), container->user_data);
|
||||
}
|
||||
if (NIL_P(container->callbacks)) {
|
||||
return NULL;
|
||||
}
|
||||
const long callbacks_len = RARRAY_LEN(container->callbacks);
|
||||
if (0 == callbacks_len) {
|
||||
return NULL;
|
||||
}
|
||||
for (int j = 0; j < callbacks_len; j++) {
|
||||
VALUE cb = rb_ary_entry(container->callbacks, j);
|
||||
rb_funcall(cb, id_call, 1, INT2NUM(progress_cur));
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void progress_callback(struct whisper_context *ctx, struct whisper_state *state, int progress_cur, void *user_data) {
|
||||
const ruby_whisper_callback_container *container = (ruby_whisper_callback_container *)user_data;
|
||||
const VALUE progress = INT2NUM(progress_cur);
|
||||
// Currently, doesn't support state because
|
||||
// those require to resolve GC-related problems.
|
||||
if (!NIL_P(container->callback)) {
|
||||
rb_funcall(container->callback, id_call, 4, *container->context, Qnil, progress, container->user_data);
|
||||
}
|
||||
if (NIL_P(container->callbacks)) {
|
||||
if (!ruby_whisper_callback_container_is_present(container)) {
|
||||
return;
|
||||
}
|
||||
const long callbacks_len = RARRAY_LEN(container->callbacks);
|
||||
if (0 == callbacks_len) {
|
||||
return;
|
||||
}
|
||||
for (int j = 0; j < callbacks_len; j++) {
|
||||
VALUE cb = rb_ary_entry(container->callbacks, j);
|
||||
rb_funcall(cb, id_call, 1, progress);
|
||||
}
|
||||
|
||||
call_progress_callbacks_args args = {
|
||||
container,
|
||||
state,
|
||||
progress_cur
|
||||
};
|
||||
rb_thread_call_with_gvl(call_progress_callbacks, (void *)&args);
|
||||
}
|
||||
|
||||
static bool encoder_begin_callback(struct whisper_context *ctx, struct whisper_state *state, void *user_data) {
|
||||
const ruby_whisper_callback_container *container = (ruby_whisper_callback_container *)user_data;
|
||||
bool is_aborted = false;
|
||||
VALUE result;
|
||||
typedef struct {
|
||||
const ruby_whisper_callback_container *container;
|
||||
struct whisper_state *state;
|
||||
bool is_continued;
|
||||
} call_encoder_begin_callbacks_args;
|
||||
|
||||
static void*
|
||||
call_encoder_begin_callbacks(void *v_args) {
|
||||
call_encoder_begin_callbacks_args *args = (call_encoder_begin_callbacks_args *)v_args;
|
||||
const ruby_whisper_callback_container *container = args->container;
|
||||
VALUE result = Qnil;
|
||||
|
||||
// Currently, doesn't support state because
|
||||
// those require to resolve GC-related problems.
|
||||
if (!NIL_P(container->callback)) {
|
||||
result = rb_funcall(container->callback, id_call, 3, *container->context, Qnil, container->user_data);
|
||||
if (result == Qfalse) {
|
||||
is_aborted = true;
|
||||
args->is_continued = false;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (!NIL_P(container->callbacks)) {
|
||||
const long callbacks_len = RARRAY_LEN(container->callbacks);
|
||||
if (0 == callbacks_len) {
|
||||
return !is_aborted;
|
||||
return NULL;
|
||||
}
|
||||
for (int j = 0; j < callbacks_len; j++) {
|
||||
VALUE cb = rb_ary_entry(container->callbacks, j);
|
||||
result = rb_funcall(cb, id_call, 0);
|
||||
if (result == Qfalse) {
|
||||
is_aborted = true;
|
||||
args->is_continued = false;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return !is_aborted;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool encoder_begin_callback(struct whisper_context *ctx, struct whisper_state *state, void *user_data) {
|
||||
const ruby_whisper_callback_container *container = (ruby_whisper_callback_container *)user_data;
|
||||
if (!ruby_whisper_callback_container_is_present(container)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
call_encoder_begin_callbacks_args args = {
|
||||
container,
|
||||
state,
|
||||
true
|
||||
};
|
||||
rb_thread_call_with_gvl(call_encoder_begin_callbacks, (void *)&args);
|
||||
|
||||
return args.is_continued;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
const ruby_whisper_abort_callback_container *container;
|
||||
struct whisper_state *state;
|
||||
bool is_interrupted;
|
||||
} call_abort_callbacks_args;
|
||||
|
||||
static void*
|
||||
call_abort_callbacks(void *v_args) {
|
||||
call_abort_callbacks_args *args = (call_abort_callbacks_args *)v_args;
|
||||
const ruby_whisper_abort_callback_container *container = args->container;
|
||||
|
||||
if (container->is_interrupted) {
|
||||
args->is_interrupted = true;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!NIL_P(container->callback)) {
|
||||
VALUE result = rb_funcall(container->callback, id_call, 1, container->user_data);
|
||||
if (!NIL_P(result) && Qfalse != result) {
|
||||
args->is_interrupted = true;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (NIL_P(container->callbacks)) {
|
||||
return NULL;
|
||||
}
|
||||
const long callbacks_len = RARRAY_LEN(container->callbacks);
|
||||
if (0 == callbacks_len) {
|
||||
return NULL;
|
||||
}
|
||||
for (int j = 0; j < callbacks_len; j++) {
|
||||
VALUE cb = rb_ary_entry(container->callbacks, j);
|
||||
VALUE result = rb_funcall(cb, id_call, 1, container->user_data);
|
||||
if (!NIL_P(result) && Qfalse != result) {
|
||||
args->is_interrupted = true;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool abort_callback(void * user_data) {
|
||||
|
|
@ -212,27 +331,14 @@ static bool abort_callback(void * user_data) {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (!NIL_P(container->callback)) {
|
||||
VALUE result = rb_funcall(container->callback, id_call, 1, container->user_data);
|
||||
if (!NIL_P(result) && Qfalse != result) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (NIL_P(container->callbacks)) {
|
||||
return false;
|
||||
}
|
||||
const long callbacks_len = RARRAY_LEN(container->callbacks);
|
||||
if (0 == callbacks_len) {
|
||||
return false;
|
||||
}
|
||||
for (int j = 0; j < callbacks_len; j++) {
|
||||
VALUE cb = rb_ary_entry(container->callbacks, j);
|
||||
VALUE result = rb_funcall(cb, id_call, 1, container->user_data);
|
||||
if (!NIL_P(result) && Qfalse != result) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
call_abort_callbacks_args args = {
|
||||
container,
|
||||
NULL,
|
||||
false
|
||||
};
|
||||
rb_thread_call_with_gvl(call_abort_callbacks, (void *)&args);
|
||||
|
||||
return args.is_interrupted;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
interface _MemoryView
|
||||
def initialize: (string) -> void
|
||||
end
|
||||
|
||||
module Whisper
|
||||
interface _Samples
|
||||
def length: () -> Integer
|
||||
|
|
|
|||
Loading…
Reference in New Issue