Skip to content

Commit ef628ce

Browse files
casperisfinebyroot
andauthored
Modernize Ruby C API ussage (#23)
Convert the old `Data_` API calls into `TypedData`. This allows for write barriers, immediate free etc. Also undefined the allocators of the Data classes to avoid a warning on recent rubies. Co-authored-by: Jean Boussier <jean.boussier@gmail.com>
1 parent ab3035d commit ef628ce

File tree

2 files changed

+46
-12
lines changed

2 files changed

+46
-12
lines changed

ext/xxhash/xxhash.c

+46-10
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,30 @@ VALUE xxhash_xxh32(VALUE mod, VALUE input, VALUE seed)
6767
return ULL2NUM(XXH32(StringValuePtr(input), (size_t)RSTRING_LEN(input), (unsigned int)NUM2ULL(seed)));
6868
}
6969

70-
void xxhash32_streaming_hash_free(xxhash_xxh32_t* storage)
70+
static void xxhash32_streaming_hash_free(void *ptr)
7171
{
72+
xxhash_xxh32_t* storage = (xxhash_xxh32_t*)ptr;
7273
// Digest frees the memory.
7374
XXH32_freeState(storage->state);
7475
xfree(storage);
7576
}
7677

78+
static size_t xxhash32_streaming_hash_memsize(const void *ptr)
79+
{
80+
// Ideally we'd include sizeof(XXH32_state_t) too, but the type is opaque.
81+
return sizeof(xxhash_xxh32_t);
82+
}
83+
84+
static const rb_data_type_t xxhash_xxh32_type = {
85+
.wrap_struct_name = "xxhash/xxhash32_streaming_hash",
86+
.function = {
87+
.dmark = NULL,
88+
.dfree = xxhash32_streaming_hash_free,
89+
.dsize = xxhash32_streaming_hash_memsize,
90+
},
91+
.flags = RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY
92+
};
93+
7794
VALUE xxhash32_streaming_hash_new(VALUE klass, VALUE seed)
7895
{
7996
XXH_errorcode code;
@@ -86,14 +103,14 @@ VALUE xxhash32_streaming_hash_new(VALUE klass, VALUE seed)
86103
rb_raise(rb_eRuntimeError, "Error during reset.");
87104
return Qnil;
88105
}
89-
return Data_Wrap_Struct(klass, 0, xxhash32_streaming_hash_free, storage);
106+
return TypedData_Wrap_Struct(klass, &xxhash_xxh32_type, storage);
90107
}
91108

92109
VALUE xxhash32_streaming_hash_reset(VALUE self)
93110
{
94111
XXH_errorcode code;
95112
xxhash_xxh32_t* storage;
96-
Data_Get_Struct(self, xxhash_xxh32_t, storage);
113+
TypedData_Get_Struct(self, xxhash_xxh32_t, &xxhash_xxh32_type, storage);
97114

98115
code = XXH32_reset(storage->state, storage->seed);
99116
if(code != XXH_OK) {
@@ -107,7 +124,7 @@ VALUE xxhash32_streaming_hash_update(VALUE self, VALUE data)
107124
{
108125
XXH_errorcode code;
109126
xxhash_xxh32_t* storage;
110-
Data_Get_Struct(self, xxhash_xxh32_t, storage);
127+
TypedData_Get_Struct(self, xxhash_xxh32_t, &xxhash_xxh32_type, storage);
111128

112129
code = XXH32_update(storage->state, StringValuePtr(data), (size_t)RSTRING_LEN(data));
113130
if(code != XXH_OK) {
@@ -119,7 +136,7 @@ VALUE xxhash32_streaming_hash_update(VALUE self, VALUE data)
119136
VALUE xxhash32_streaming_hash_digest(VALUE self)
120137
{
121138
xxhash_xxh32_t* storage;
122-
Data_Get_Struct(self, xxhash_xxh32_t, storage);
139+
TypedData_Get_Struct(self, xxhash_xxh32_t, &xxhash_xxh32_type, storage);
123140

124141
// Do not free memory now.
125142
return ULL2NUM(XXH32_digest(storage->state));
@@ -130,13 +147,30 @@ VALUE xxhash_xxh64(VALUE mod, VALUE input, VALUE seed)
130147
return ULL2NUM(XXH64(StringValuePtr(input), (size_t)RSTRING_LEN(input), (unsigned int)NUM2ULL(seed)));
131148
}
132149

133-
void xxhash64_streaming_hash_free(xxhash_xxh64_t* storage)
150+
static void xxhash64_streaming_hash_free(void *ptr)
134151
{
152+
xxhash_xxh64_t* storage = (xxhash_xxh64_t*)ptr;
135153
// Digest frees the memory.
136154
XXH64_freeState(storage->state);
137155
xfree(storage);
138156
}
139157

158+
static size_t xxhash64_streaming_hash_memsize(const void *ptr)
159+
{
160+
// Ideally we'd include sizeof(XXH64_state_t) too, but the type is opaque.
161+
return sizeof(xxhash_xxh64_t);
162+
}
163+
164+
static const rb_data_type_t xxhash_xxh64_type = {
165+
.wrap_struct_name = "xxhash/xxhash64_streaming_hash",
166+
.function = {
167+
.dmark = NULL,
168+
.dfree = xxhash64_streaming_hash_free,
169+
.dsize = xxhash64_streaming_hash_memsize,
170+
},
171+
.flags = RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY
172+
};
173+
140174
VALUE xxhash64_streaming_hash_new(VALUE klass, VALUE seed)
141175
{
142176
XXH_errorcode code;
@@ -150,14 +184,14 @@ VALUE xxhash64_streaming_hash_new(VALUE klass, VALUE seed)
150184
rb_raise(rb_eRuntimeError, "Error during reset.");
151185
return Qnil;
152186
}
153-
return Data_Wrap_Struct(klass, 0, xxhash64_streaming_hash_free, storage);
187+
return TypedData_Wrap_Struct(klass, &xxhash_xxh64_type, storage);
154188
}
155189

156190
VALUE xxhash64_streaming_hash_reset(VALUE self)
157191
{
158192
XXH_errorcode code;
159193
xxhash_xxh64_t* storage;
160-
Data_Get_Struct(self, xxhash_xxh64_t, storage);
194+
TypedData_Get_Struct(self, xxhash_xxh64_t, &xxhash_xxh64_type, storage);
161195

162196
code = XXH64_reset(storage->state, storage->seed);
163197
if(code != XXH_OK) {
@@ -170,7 +204,7 @@ VALUE xxhash64_streaming_hash_update(VALUE self, VALUE data)
170204
{
171205
XXH_errorcode code;
172206
xxhash_xxh64_t* storage;
173-
Data_Get_Struct(self, xxhash_xxh64_t, storage);
207+
TypedData_Get_Struct(self, xxhash_xxh64_t, &xxhash_xxh64_type, storage);
174208

175209
code = XXH64_update(storage->state, StringValuePtr(data), (size_t)RSTRING_LEN(data));
176210
if(code != XXH_OK) {
@@ -182,7 +216,7 @@ VALUE xxhash64_streaming_hash_update(VALUE self, VALUE data)
182216
VALUE xxhash64_streaming_hash_digest(VALUE self)
183217
{
184218
xxhash_xxh64_t* storage;
185-
Data_Get_Struct(self, xxhash_xxh64_t, storage);
219+
TypedData_Get_Struct(self, xxhash_xxh64_t, &xxhash_xxh64_type, storage);
186220

187221
// Do not free memory now.
188222
return ULL2NUM(XXH64_digest(storage->state));
@@ -209,13 +243,15 @@ void Init_xxhash(void)
209243
rb_define_singleton_method(mInternal, "xxh64_file", (ruby_method*) &xxhash_xxh64_file, 2);
210244

211245
cStreamingHash = rb_define_class_under(mInternal, "StreamingHash32", rb_cObject);
246+
rb_undef_alloc_func(cStreamingHash);
212247

213248
rb_define_singleton_method(cStreamingHash, "new", (ruby_method*) &xxhash32_streaming_hash_new, 1);
214249
rb_define_method(cStreamingHash, "update", (ruby_method*) &xxhash32_streaming_hash_update, 1);
215250
rb_define_method(cStreamingHash, "digest", (ruby_method*) &xxhash32_streaming_hash_digest, 0);
216251
rb_define_method(cStreamingHash, "reset", (ruby_method*) &xxhash32_streaming_hash_reset, 0);
217252

218253
cStreamingHash64 = rb_define_class_under(mInternal, "StreamingHash64", rb_cObject);
254+
rb_undef_alloc_func(cStreamingHash64);
219255

220256
rb_define_singleton_method(cStreamingHash64, "new", (ruby_method*) &xxhash64_streaming_hash_new, 1);
221257
rb_define_method(cStreamingHash64, "update", (ruby_method*) &xxhash64_streaming_hash_update, 1);

ext/xxhash/xxhash.h

-2
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,12 @@ typedef VALUE (ruby_method)();
1919

2020
VALUE xxhash_xxh32(VALUE mod, VALUE input, VALUE seed);
2121
VALUE xxhash_xxh32_file(VALUE mod, VALUE filename, VALUE seed);
22-
void xxhash32_streaming_hash_free(xxhash_xxh32_t* state);
2322
VALUE xxhash32_streaming_hash_new(VALUE klass, VALUE seed);
2423
VALUE xxhash32_streaming_hash_update(VALUE self, VALUE data);
2524
VALUE xxhash32_streaming_hash_reset(VALUE self);
2625
VALUE xxhash32_streaming_hash_digest(VALUE self);
2726
VALUE xxhash_xxh64(VALUE mod, VALUE input, VALUE seed);
2827
VALUE xxhash_xxh64_file(VALUE mod, VALUE filename, VALUE seed);
29-
void xxhash64_streaming_hash_free(xxhash_xxh64_t* state);
3028
VALUE xxhash64_streaming_hash_new(VALUE klass, VALUE seed);
3129
VALUE xxhash64_streaming_hash_update(VALUE self, VALUE data);
3230
VALUE xxhash64_streaming_hash_reset(VALUE self);

0 commit comments

Comments
 (0)