Skip to content

Commit c6ecc4a

Browse files
committed
Add write barriers to PG::Tuple
1 parent 113ee1a commit c6ecc4a

File tree

1 file changed

+34
-31
lines changed

1 file changed

+34
-31
lines changed

ext/pg_tuple.c

Lines changed: 34 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ static const rb_data_type_t pg_tuple_type = {
128128
pg_compact_callback(pg_tuple_gc_compact),
129129
},
130130
0, 0,
131-
RUBY_TYPED_FREE_IMMEDIATELY,
131+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
132132
};
133133

134134
/*
@@ -159,9 +159,9 @@ pg_tuple_new(VALUE result, int row_num)
159159
sizeof(*this->values) * num_fields +
160160
sizeof(*this->values) * (dup_names ? 1 : 0));
161161

162-
this->result = result;
163-
this->typemap = p_result->typemap;
164-
this->field_map = field_map;
162+
RB_OBJ_WRITE(self, &this->result, result);
163+
RB_OBJ_WRITE(self, &this->typemap, p_result->typemap);
164+
RB_OBJ_WRITE(self, &this->field_map, field_map);
165165
this->row_num = row_num;
166166
this->num_fields = num_fields;
167167

@@ -173,7 +173,8 @@ pg_tuple_new(VALUE result, int row_num)
173173
/* Some of the column names are duplicated -> we need the keys as Array in addition.
174174
* Store it behind the values to save the space in the common case of no dups.
175175
*/
176-
this->values[num_fields] = rb_obj_freeze(rb_ary_new4(num_fields, p_result->fnames));
176+
VALUE keys_array = rb_obj_freeze(rb_ary_new4(num_fields, p_result->fnames));
177+
RB_OBJ_WRITE(self, &this->values[num_fields], keys_array);
177178
}
178179

179180
RTYPEDDATA_DATA(self) = this;
@@ -193,38 +194,41 @@ pg_tuple_get_this( VALUE self )
193194
}
194195

195196
static VALUE
196-
pg_tuple_materialize_field(t_pg_tuple *this, int col)
197+
pg_tuple_materialize_field(VALUE self, int col)
197198
{
199+
t_pg_tuple *this = RTYPEDDATA_DATA( self );
198200
VALUE value = this->values[col];
199201

200202
if( value == Qundef ){
201203
t_typemap *p_typemap = RTYPEDDATA_DATA( this->typemap );
202204

203205
pgresult_get(this->result); /* make sure we have a valid PGresult object */
204206
value = p_typemap->funcs.typecast_result_value(p_typemap, this->result, this->row_num, col);
205-
this->values[col] = value;
207+
RB_OBJ_WRITE(self, &this->values[col], value);
206208
}
207209

208210
return value;
209211
}
210212

211213
static void
212-
pg_tuple_detach(t_pg_tuple *this)
214+
pg_tuple_detach(VALUE self)
213215
{
214-
this->result = Qnil;
215-
this->typemap = Qnil;
216+
t_pg_tuple *this = RTYPEDDATA_DATA( self );
217+
RB_OBJ_WRITE(self, &this->result, Qnil);
218+
RB_OBJ_WRITE(self, &this->typemap, Qnil);
216219
this->row_num = -1;
217220
}
218221

219222
static void
220-
pg_tuple_materialize(t_pg_tuple *this)
223+
pg_tuple_materialize(VALUE self)
221224
{
225+
t_pg_tuple *this = RTYPEDDATA_DATA( self );
222226
int field_num;
223227
for(field_num = 0; field_num < this->num_fields; field_num++) {
224-
pg_tuple_materialize_field(this, field_num);
228+
pg_tuple_materialize_field(self, field_num);
225229
}
226230

227-
pg_tuple_detach(this);
231+
pg_tuple_detach(self);
228232
}
229233

230234
/*
@@ -286,7 +290,7 @@ pg_tuple_fetch(int argc, VALUE *argv, VALUE self)
286290
field_num = NUM2INT(index);
287291
}
288292

289-
return pg_tuple_materialize_field(this, field_num);
293+
return pg_tuple_materialize_field(self, field_num);
290294
}
291295

292296
/*
@@ -324,7 +328,7 @@ pg_tuple_aref(VALUE self, VALUE key)
324328
field_num = NUM2INT(index);
325329
}
326330

327-
return pg_tuple_materialize_field(this, field_num);
331+
return pg_tuple_materialize_field(self, field_num);
328332
}
329333

330334
static VALUE
@@ -335,10 +339,9 @@ pg_tuple_num_fields_for_enum(VALUE self, VALUE args, VALUE eobj)
335339
}
336340

337341
static int
338-
pg_tuple_yield_key_value(VALUE key, VALUE index, VALUE _this)
342+
pg_tuple_yield_key_value(VALUE key, VALUE index, VALUE self)
339343
{
340-
t_pg_tuple *this = (t_pg_tuple *)_this;
341-
VALUE value = pg_tuple_materialize_field(this, NUM2INT(index));
344+
VALUE value = pg_tuple_materialize_field(self, NUM2INT(index));
342345
rb_yield_values(2, key, value);
343346
return ST_CONTINUE;
344347
}
@@ -360,16 +363,16 @@ pg_tuple_each(VALUE self)
360363
field_names = pg_tuple_get_field_names(this);
361364

362365
if( field_names == Qfalse ){
363-
rb_hash_foreach(this->field_map, pg_tuple_yield_key_value, (VALUE)this);
366+
rb_hash_foreach(this->field_map, pg_tuple_yield_key_value, self);
364367
} else {
365368
int i;
366369
for( i = 0; i < this->num_fields; i++ ){
367-
VALUE value = pg_tuple_materialize_field(this, i);
370+
VALUE value = pg_tuple_materialize_field(self, i);
368371
rb_yield_values(2, RARRAY_AREF(field_names, i), value);
369372
}
370373
}
371374

372-
pg_tuple_detach(this);
375+
pg_tuple_detach(self);
373376
return self;
374377
}
375378

@@ -388,11 +391,11 @@ pg_tuple_each_value(VALUE self)
388391
RETURN_SIZED_ENUMERATOR(self, 0, NULL, pg_tuple_num_fields_for_enum);
389392

390393
for(field_num = 0; field_num < this->num_fields; field_num++) {
391-
VALUE value = pg_tuple_materialize_field(this, field_num);
394+
VALUE value = pg_tuple_materialize_field(self, field_num);
392395
rb_yield(value);
393396
}
394397

395-
pg_tuple_detach(this);
398+
pg_tuple_detach(self);
396399
return self;
397400
}
398401

@@ -409,7 +412,7 @@ pg_tuple_values(VALUE self)
409412
{
410413
t_pg_tuple *this = pg_tuple_get_this(self);
411414

412-
pg_tuple_materialize(this);
415+
pg_tuple_materialize(self);
413416
return rb_ary_new4(this->num_fields, &this->values[0]);
414417
}
415418

@@ -462,7 +465,7 @@ pg_tuple_dump(VALUE self)
462465
VALUE a;
463466
t_pg_tuple *this = pg_tuple_get_this(self);
464467

465-
pg_tuple_materialize(this);
468+
pg_tuple_materialize(self);
466469

467470
field_names = pg_tuple_get_field_names(this);
468471
if( field_names == Qfalse )
@@ -520,26 +523,26 @@ pg_tuple_load(VALUE self, VALUE a)
520523
sizeof(*this->values) * num_fields +
521524
sizeof(*this->values) * (dup_names ? 1 : 0));
522525

523-
this->result = Qnil;
524-
this->typemap = Qnil;
526+
RB_OBJ_WRITE(self, &this->result, Qnil);
527+
RB_OBJ_WRITE(self, &this->typemap, Qnil);
525528
this->row_num = -1;
526529
this->num_fields = num_fields;
527-
this->field_map = field_map;
530+
RB_OBJ_WRITE(self, &this->field_map, field_map);
528531

529532
for( i = 0; i < num_fields; i++ ){
530533
VALUE v = RARRAY_AREF(values, i);
531534
if( v == Qundef )
532535
rb_raise(rb_eTypeError, "field %d is not materialized", i);
533-
this->values[i] = v;
536+
RB_OBJ_WRITE(self, &this->values[i], v);
534537
}
535538

536539
if( dup_names ){
537-
this->values[num_fields] = field_names;
540+
RB_OBJ_WRITE(self, &this->values[num_fields], field_names);
538541
}
539542

540543
RTYPEDDATA_DATA(self) = this;
541544

542-
rb_copy_generic_ivar(self, a);
545+
rb_copy_generic_ivar(self, a);
543546

544547
return self;
545548
}

0 commit comments

Comments
 (0)