|
28 | 28 | #include "id.h" |
29 | 29 |
|
30 | 30 | #define ENABLE_ECONV_NEWLINE_OPTION 1 |
31 | | -#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)); |
| 31 | +#define SRC_ENC_TO_DST_ENC_KEY_SIZE (ENCODING_NAMELEN_MAX * 2 + 2) |
33 | 32 |
|
34 | 33 | /* VALUE rb_cEncoding = rb_define_class("Encoding", rb_cObject); */ |
35 | 34 | static VALUE rb_eUndefinedConversionError; |
@@ -1088,26 +1087,30 @@ rb_econv_open0(rb_encoding *senc, const char *sname, rb_encoding *denc, const ch |
1088 | 1087 | toarg.entries = NULL; |
1089 | 1088 | toarg.num_additional = 0; |
1090 | 1089 | char key_buf[SRC_ENC_TO_DST_ENC_KEY_SIZE] = { 0 }; |
1091 | | - char *key; |
| 1090 | + char *key = NULL; |
1092 | 1091 | gen_src_to_dst_encodings_key(key_buf, sname, dname); |
1093 | 1092 | VALUE managed_val; |
1094 | | - VALUE tbl = RUBY_ATOMIC_VALUE_LOAD(fast_transcoder_path_table); |
1095 | | - if (rb_managed_st_table_lookup(tbl, (st_data_t)key_buf, &managed_val)) { |
1096 | | - entries = (transcoder_entry_t **)managed_val; |
1097 | | - } else { |
1098 | | - num_trans = transcode_search_path(sname, dname, trans_open_i, (void *)&toarg); |
1099 | | - entries = toarg.entries; |
1100 | | - if (num_trans < 0) { |
1101 | | - xfree(entries); |
1102 | | - return NULL; |
| 1093 | + while (1) { |
| 1094 | + VALUE tbl = fast_transcoder_path_table; |
| 1095 | + if (rb_managed_st_table_lookup(tbl, (st_data_t)key_buf, &managed_val)) { |
| 1096 | + entries = (transcoder_entry_t **)managed_val; |
| 1097 | + break; |
| 1098 | + } else { |
| 1099 | + if (!entries) { |
| 1100 | + num_trans = transcode_search_path(sname, dname, trans_open_i, (void *)&toarg); |
| 1101 | + entries = toarg.entries; |
| 1102 | + if (num_trans < 0) { |
| 1103 | + xfree(entries); |
| 1104 | + return NULL; |
| 1105 | + } |
| 1106 | + } |
| 1107 | + VALUE new_tbl = rb_managed_st_table_dup(tbl); |
| 1108 | + if (!key) key = strdup(key_buf); |
| 1109 | + rb_managed_st_table_insert(new_tbl, (st_data_t)key, (VALUE)entries); |
| 1110 | + if (RUBY_ATOMIC_VALUE_CAS(fast_transcoder_path_table, tbl, new_tbl) == tbl) { |
| 1111 | + break; |
| 1112 | + } |
1103 | 1113 | } |
1104 | | - // No need for CAS loop if it's not most recent `fast_transcoder_table`, some values |
1105 | | - // can be lost. It will just go through the slow path next time for the lost src/dst encoding |
1106 | | - // pairs |
1107 | | - VALUE new_tbl = rb_managed_st_table_dup(tbl); |
1108 | | - key = strdup(key_buf); |
1109 | | - rb_managed_st_table_insert(new_tbl, (st_data_t)key, (VALUE)entries); |
1110 | | - RUBY_ATOMIC_VALUE_SET(fast_transcoder_path_table, new_tbl); |
1111 | 1114 | } |
1112 | 1115 | } |
1113 | 1116 |
|
|
0 commit comments