Skip to content

Commit 6f5405d

Browse files
committed
use CAS for fast_transcoder_entry_table
1 parent 87d8d9c commit 6f5405d

2 files changed

Lines changed: 22 additions & 8 deletions

File tree

include/ruby/internal/encoding/encoding.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ enum ruby_encoding_consts {
6767
#define ENCODING_INLINE_MAX RUBY_ENCODING_INLINE_MAX /**< @old{RUBY_ENCODING_INLINE_MAX} */
6868
#define ENCODING_SHIFT RUBY_ENCODING_SHIFT /**< @old{RUBY_ENCODING_SHIFT} */
6969
#define ENCODING_MASK RUBY_ENCODING_MASK /**< @old{RUBY_ENCODING_MASK} */
70+
#define ENCODING_NAMELEN_MAX 63
7071

7172
/**
7273
* Destructively assigns the passed encoding to the passed object. The object

transcode.c

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030
#define ENABLE_ECONV_NEWLINE_OPTION 1
3131
#define SRC_ENC_TO_DST_ENC_KEY_SIZE 128
32+
STATIC_ASSERT(encoding_namelen, SRC_ENC_TO_DST_ENC_KEY_SIZE > (ENCODING_NAMELEN_MAX * 2 + 1));
3233

3334
/* VALUE rb_cEncoding = rb_define_class("Encoding", rb_cObject); */
3435
static VALUE rb_eUndefinedConversionError;
@@ -211,7 +212,7 @@ rb_free_transcoder_table(void)
211212
}
212213

213214
static void
214-
gen_src_to_dst_encodings_key(const char key_buf[SRC_ENC_TO_DST_ENC_KEY_SIZE], const char *sname, const char *dname)
215+
gen_src_to_dst_encodings_key(const char *key_buf, const char *sname, const char *dname)
215216
{
216217
char *p = (char*)key_buf;
217218
size_t slen = strlen(sname);
@@ -231,6 +232,7 @@ make_transcoder_entry(const char *sname, const char *dname)
231232
st_table *table2;
232233
transcoder_entry_t *entry = NULL;
233234

235+
// TODO: we should be able to remove this table soon
234236
RB_VM_LOCKING() {
235237
if (!st_lookup(transcoder_table, (st_data_t)sname, &val)) {
236238
val = (st_data_t)st_init_strcasetable();
@@ -251,10 +253,20 @@ make_transcoder_entry(const char *sname, const char *dname)
251253
}
252254
char key_buf[SRC_ENC_TO_DST_ENC_KEY_SIZE] = { 0 };
253255
gen_src_to_dst_encodings_key(key_buf, sname, dname);
254-
VALUE tbl = fast_transcoder_entry_table;
255-
VALUE new_tbl = rb_managed_id_table_dup(tbl);
256-
rb_managed_id_table_insert(new_tbl, rb_intern(key_buf), (VALUE)entry);
257-
RUBY_ATOMIC_VALUE_SET(fast_transcoder_entry_table, new_tbl); // TODO: use CAS
256+
ID key = rb_intern(key_buf);
257+
while (1) {
258+
VALUE tbl = fast_transcoder_entry_table;
259+
VALUE entry_got;
260+
if (rb_managed_id_table_lookup(tbl, key, &entry_got)) {
261+
break;
262+
} else {
263+
VALUE new_tbl = rb_managed_id_table_dup(tbl);
264+
rb_managed_id_table_insert(new_tbl, key, (VALUE)entry);
265+
if (RUBY_ATOMIC_VALUE_CAS(fast_transcoder_entry_table, tbl, new_tbl) == tbl) {
266+
break;
267+
}
268+
}
269+
}
258270
return entry;
259271
}
260272

@@ -266,11 +278,11 @@ get_transcoder_entry(const char *sname, const char *dname)
266278
char key_buf[SRC_ENC_TO_DST_ENC_KEY_SIZE] = { 0 };
267279
gen_src_to_dst_encodings_key(key_buf, sname, dname);
268280
VALUE entry_val;
269-
// TODO: once we CAS in `make_transcoder_entry`, we no longer need to check regular transcoder_table after
270281
if (rb_managed_id_table_lookup(fast_transcoder_entry_table, rb_intern(key_buf), &entry_val)) {
271282
return (transcoder_entry_t*)entry_val;
272283
}
273284

285+
// TODO: we should be able to remove this table soon
274286
RB_VM_LOCKING() {
275287
if (st_lookup(transcoder_table, (st_data_t)sname, &val)) {
276288
table2 = (st_table *)val;
@@ -1065,11 +1077,12 @@ rb_econv_open0(rb_encoding *senc, const char *sname, rb_encoding *denc, const ch
10651077
int num_trans;
10661078
rb_econv_t *ec;
10671079

1080+
// load encodings, if necessary
10681081
if (*sname && (!senc || !senc->max_enc_len)) {
1069-
rb_enc_find_index(sname); // loads encoding
1082+
rb_enc_find_index(sname);
10701083
}
10711084
if (*dname && (!denc || !denc->max_enc_len)) {
1072-
rb_enc_find_index(dname); // loads encoding
1085+
rb_enc_find_index(dname);
10731086
}
10741087

10751088
if (*sname == '\0' && *dname == '\0') {

0 commit comments

Comments
 (0)