Skip to content

Commit

Permalink
Merge pull request #16 from savonet/generational-global-root
Browse files Browse the repository at this point in the history
Use generational global roots.
  • Loading branch information
toots authored Nov 9, 2023
2 parents 870af78 + 7b8be47 commit 107871f
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 32 deletions.
5 changes: 5 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
0.5.1 (unreleased)
=====
* Use generational global roots to protect
encoder and decoder callbacks.

0.5.0 (2023-09-05)
=====
* Cleanup API, get rid of global roots,
Expand Down
2 changes: 1 addition & 1 deletion dune-project
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
(lang dune 2.8)
(version 0.5.0)
(version 0.5.1)
(name flac)
(source (github savonet/ocaml-flac))
(license GPL-2.0-or-later)
Expand Down
4 changes: 2 additions & 2 deletions src/flac_ogg_stubs.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ CAMLprim value ocaml_flac_encoder_ogg_create(value comments, value params,
ret = ocaml_flac_encoder_alloc(comments, params);
ocaml_flac_encoder *enc = Encoder_val(ret);

enc->callbacks = _enc_cb;
caml_modify_generational_global_root(&enc->callbacks, _enc_cb);

caml_release_runtime_system();
FLAC__stream_encoder_set_ogg_serial_number(enc->encoder, serialno);
Expand All @@ -78,7 +78,7 @@ CAMLprim value ocaml_flac_encoder_ogg_create(value comments, value params,
(void *)&enc->callbacks);
caml_acquire_runtime_system();

enc->callbacks = Val_none;
caml_modify_generational_global_root(&enc->callbacks, Val_none);

CAMLreturn(ret);
}
Expand Down
58 changes: 36 additions & 22 deletions src/flac_stubs.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ void ocaml_flac_register_thread() {
/* Convenience functions */
#ifdef BIGENDIAN
static inline int16_t bswap_16(int16_t x) {
return ((((x) >> 8) & 0xff) | (((x)&0xff) << 8));
return ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8));
}
#endif

Expand Down Expand Up @@ -192,6 +192,8 @@ static void finalize_decoder(value e) {
free(dec->callbacks.info);
if (dec->callbacks.meta != NULL)
FLAC__metadata_object_delete(dec->callbacks.meta);

caml_remove_generational_global_root(&dec->callbacks.callbacks);
free(dec);
}

Expand Down Expand Up @@ -441,10 +443,12 @@ value ocaml_flac_decoder_alloc() {
caml_raise_out_of_memory();

dec->decoder = FLAC__stream_decoder_new();
dec->callbacks.callbacks = NULL;
dec->callbacks.callbacks = Val_none;
dec->callbacks.info = NULL;
dec->callbacks.meta = NULL;

caml_register_generational_global_root(&dec->callbacks.callbacks);

// Accept vorbis comments
FLAC__stream_decoder_set_metadata_respond(dec->decoder,
FLAC__METADATA_TYPE_VORBIS_COMMENT);
Expand All @@ -463,7 +467,7 @@ CAMLprim value ocaml_flac_decoder_create(value callbacks) {
ans = ocaml_flac_decoder_alloc();
ocaml_flac_decoder *dec = Decoder_val(ans);

dec->callbacks.callbacks = &callbacks;
caml_modify_generational_global_root(&dec->callbacks.callbacks, callbacks);

// Intialize decoder
caml_release_runtime_system();
Expand All @@ -473,7 +477,7 @@ CAMLprim value ocaml_flac_decoder_create(value callbacks) {
dec_metadata_callback, dec_error_callback, (void *)&dec->callbacks);
caml_acquire_runtime_system();

dec->callbacks.callbacks = NULL;
caml_modify_generational_global_root(&dec->callbacks.callbacks, Val_none);

CAMLreturn(ans);
}
Expand All @@ -482,14 +486,15 @@ CAMLprim value ocaml_flac_decoder_init(value d, value c) {
CAMLparam2(d, c);

ocaml_flac_decoder *dec = Decoder_val(d);
dec->callbacks.callbacks = &c;

caml_modify_generational_global_root(&dec->callbacks.callbacks, c);

// Process metadata
caml_release_runtime_system();
FLAC__stream_decoder_process_until_end_of_metadata(dec->decoder);
caml_acquire_runtime_system();

dec->callbacks.callbacks = NULL;
caml_modify_generational_global_root(&dec->callbacks.callbacks, Val_none);

CAMLreturn(Val_unit);
}
Expand All @@ -498,11 +503,12 @@ CAMLprim value ocaml_flac_decoder_state(value d, value c) {
CAMLparam2(d, c);

ocaml_flac_decoder *dec = Decoder_val(d);
dec->callbacks.callbacks = &c;

caml_modify_generational_global_root(&dec->callbacks.callbacks, c);

int ret = FLAC__stream_decoder_get_state(dec->decoder);

dec->callbacks.callbacks = NULL;
caml_modify_generational_global_root(&dec->callbacks.callbacks, Val_none);

CAMLreturn(val_of_state(ret));
}
Expand Down Expand Up @@ -556,14 +562,15 @@ CAMLprim value ocaml_flac_decoder_process(value d, value c) {
CAMLparam2(d, c);

ocaml_flac_decoder *dec = Decoder_val(d);
dec->callbacks.callbacks = &c;

caml_modify_generational_global_root(&dec->callbacks.callbacks, c);

// Process one frame
caml_release_runtime_system();
FLAC__stream_decoder_process_single(dec->decoder);
caml_acquire_runtime_system();

dec->callbacks.callbacks = NULL;
caml_modify_generational_global_root(&dec->callbacks.callbacks, Val_none);

CAMLreturn(Val_unit);
}
Expand All @@ -575,14 +582,15 @@ CAMLprim value ocaml_flac_decoder_seek(value d, value c, value pos) {
FLAC_API FLAC__bool ret;

ocaml_flac_decoder *dec = Decoder_val(d);
dec->callbacks.callbacks = &c;

caml_modify_generational_global_root(&dec->callbacks.callbacks, c);

// Process one frame
caml_release_runtime_system();
ret = FLAC__stream_decoder_seek_absolute(dec->decoder, offset);
caml_acquire_runtime_system();

dec->callbacks.callbacks = NULL;
caml_modify_generational_global_root(&dec->callbacks.callbacks, Val_none);

if (ret == true)
CAMLreturn(Val_true);
Expand All @@ -596,14 +604,15 @@ CAMLprim value ocaml_flac_decoder_reset(value d, value c) {
FLAC_API FLAC__bool ret;

ocaml_flac_decoder *dec = Decoder_val(d);
dec->callbacks.callbacks = &c;

caml_modify_generational_global_root(&dec->callbacks.callbacks, c);

// Process one frame
caml_release_runtime_system();
ret = FLAC__stream_decoder_reset(dec->decoder);
caml_acquire_runtime_system();

dec->callbacks.callbacks = NULL;
caml_modify_generational_global_root(&dec->callbacks.callbacks, Val_none);

if (ret == true)
CAMLreturn(Val_true);
Expand All @@ -617,14 +626,15 @@ CAMLprim value ocaml_flac_decoder_flush(value d, value c) {
FLAC_API FLAC__bool ret;

ocaml_flac_decoder *dec = Decoder_val(d);
dec->callbacks.callbacks = &c;

caml_modify_generational_global_root(&dec->callbacks.callbacks, c);

// Process one frame
caml_release_runtime_system();
ret = FLAC__stream_decoder_flush(dec->decoder);
caml_acquire_runtime_system();

dec->callbacks.callbacks = NULL;
caml_modify_generational_global_root(&dec->callbacks.callbacks, Val_none);

if (ret == true)
CAMLreturn(Val_true);
Expand All @@ -644,6 +654,8 @@ static void finalize_encoder(value e) {
free(enc->buf);
if (enc->lines != NULL)
free(enc->lines);

caml_remove_generational_global_root(&enc->callbacks);
free(enc);
}

Expand Down Expand Up @@ -763,6 +775,8 @@ value ocaml_flac_encoder_alloc(value comments, value params) {
caml_enc->buf = NULL;
caml_enc->lines = NULL;

caml_register_generational_global_root(&caml_enc->callbacks);

// Fill custom value
ret = caml_alloc_custom(&encoder_ops, sizeof(ocaml_flac_encoder *), 1, 0);
Encoder_val(ret) = caml_enc;
Expand Down Expand Up @@ -802,15 +816,15 @@ CAMLprim value ocaml_flac_encoder_create(value comments, value params,
ret = ocaml_flac_encoder_alloc(comments, params);
ocaml_flac_encoder *enc = Encoder_val(ret);

enc->callbacks = callbacks;
caml_modify_generational_global_root(&enc->callbacks, callbacks);

caml_release_runtime_system();
FLAC__stream_encoder_init_stream(enc->encoder, enc_write_callback,
enc_seek_callback, enc_tell_callback, NULL,
(void *)&enc->callbacks);
caml_acquire_runtime_system();

enc->callbacks = Val_none;
caml_modify_generational_global_root(&enc->callbacks, Val_none);

CAMLreturn(ret);
}
Expand Down Expand Up @@ -865,14 +879,14 @@ CAMLprim value ocaml_flac_encoder_process(value _enc, value cb, value data,
sample_from_double(Double_field(Field(data, c), i), Int_val(bps));
}

enc->callbacks = cb;
caml_modify_generational_global_root(&enc->callbacks, cb);

caml_release_runtime_system();
FLAC__stream_encoder_process(enc->encoder,
(const FLAC__int32 *const *)enc->buf, samples);
caml_acquire_runtime_system();

enc->callbacks = Val_none;
caml_modify_generational_global_root(&enc->callbacks, Val_none);

CAMLreturn(Val_unit);
}
Expand All @@ -882,13 +896,13 @@ CAMLprim value ocaml_flac_encoder_finish(value _enc, value c) {

ocaml_flac_encoder *enc = Encoder_val(_enc);

enc->callbacks = c;
caml_modify_generational_global_root(&enc->callbacks, c);

caml_release_runtime_system();
FLAC__stream_encoder_finish(enc->encoder);
caml_acquire_runtime_system();

enc->callbacks = Val_none;
caml_modify_generational_global_root(&enc->callbacks, Val_none);

CAMLreturn(Val_unit);
}
14 changes: 7 additions & 7 deletions src/flac_stubs.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ value flac_Val_some(value v);

typedef struct ocaml_flac_decoder_callbacks {
/* This is used for callback from caml. */
value *callbacks;
value callbacks;
FLAC__StreamMetadata_StreamInfo *info;
FLAC__StreamMetadata *meta;
} ocaml_flac_decoder_callbacks;
Expand All @@ -44,12 +44,12 @@ typedef struct ocaml_flac_decoder {
ocaml_flac_decoder_callbacks callbacks;
} ocaml_flac_decoder;

#define Dec_read(v) Field(*v, 0)
#define Dec_seek(v) Field(*v, 1)
#define Dec_tell(v) Field(*v, 2)
#define Dec_length(v) Field(*v, 3)
#define Dec_eof(v) Field(*v, 4)
#define Dec_write(v) Field(*v, 5)
#define Dec_read(v) Field(v, 0)
#define Dec_seek(v) Field(v, 1)
#define Dec_tell(v) Field(v, 2)
#define Dec_length(v) Field(v, 3)
#define Dec_eof(v) Field(v, 4)
#define Dec_write(v) Field(v, 5)

/* Caml abstract value containing the decoder. */
#define Decoder_val(v) (*((ocaml_flac_decoder **)Data_custom_val(v)))
Expand Down

0 comments on commit 107871f

Please sign in to comment.