Skip to content

Commit 9c60a85

Browse files
committed
Merge pull request #381 from sodabrew/client-refcount
Add two refactor commits to the refcount branch
2 parents 02da91a + 84d6c0b commit 9c60a85

File tree

3 files changed

+30
-41
lines changed

3 files changed

+30
-41
lines changed

ext/mysql2/client.c

Lines changed: 7 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -182,15 +182,14 @@ static VALUE nogvl_close(void *ptr) {
182182
return Qnil;
183183
}
184184

185-
static void rb_mysql_client_free(void * ptr) {
185+
static void rb_mysql_client_free(void *ptr) {
186186
mysql_client_wrapper *wrapper = (mysql_client_wrapper *)ptr;
187187

188-
wrapper->freed = 1;
189-
nogvl_close(wrapper);
190-
188+
wrapper->refcount--;
191189
if (wrapper->refcount == 0) {
190+
nogvl_close(wrapper);
192191
xfree(wrapper->client);
193-
xfree(ptr);
192+
xfree(wrapper);
194193
}
195194
}
196195

@@ -203,8 +202,7 @@ static VALUE allocate(VALUE klass) {
203202
wrapper->reconnect_enabled = 0;
204203
wrapper->connected = 0; /* means that a database connection is open */
205204
wrapper->initialized = 0; /* means that that the wrapper is initialized */
206-
wrapper->refcount = 0;
207-
wrapper->freed = 0;
205+
wrapper->refcount = 1;
208206
wrapper->client = (MYSQL*)xmalloc(sizeof(MYSQL));
209207
return obj;
210208
}
@@ -366,9 +364,6 @@ static VALUE nogvl_use_result(void *ptr) {
366364
static VALUE rb_mysql_client_async_result(VALUE self) {
367365
MYSQL_RES * result;
368366
VALUE resultObj;
369-
#ifdef HAVE_RUBY_ENCODING_H
370-
mysql2_result_wrapper * result_wrapper;
371-
#endif
372367
GET_CLIENT(self);
373368

374369
/* if we're not waiting on a result, do nothing */
@@ -398,14 +393,7 @@ static VALUE rb_mysql_client_async_result(VALUE self) {
398393
return Qnil;
399394
}
400395

401-
resultObj = rb_mysql_result_to_obj(wrapper, result);
402-
/* pass-through query options for result construction later */
403-
rb_iv_set(resultObj, "@query_options", rb_hash_dup(rb_iv_get(self, "@current_query_options")));
404-
405-
#ifdef HAVE_RUBY_ENCODING_H
406-
GetMysql2Result(resultObj, result_wrapper);
407-
result_wrapper->encoding = wrapper->encoding;
408-
#endif
396+
resultObj = rb_mysql_result_to_obj(self, wrapper->encoding, rb_hash_dup(rb_iv_get(self, "@current_query_options")), result);
409397
return resultObj;
410398
}
411399

@@ -931,10 +919,6 @@ static VALUE rb_mysql_client_store_result(VALUE self)
931919
{
932920
MYSQL_RES * result;
933921
VALUE resultObj;
934-
#ifdef HAVE_RUBY_ENCODING_H
935-
mysql2_result_wrapper * result_wrapper;
936-
#endif
937-
938922
GET_CLIENT(self);
939923

940924
result = (MYSQL_RES *)rb_thread_blocking_region(nogvl_store_result, wrapper, RUBY_UBF_IO, 0);
@@ -947,14 +931,7 @@ static VALUE rb_mysql_client_store_result(VALUE self)
947931
return Qnil;
948932
}
949933

950-
resultObj = rb_mysql_result_to_obj(wrapper, result);
951-
/* pass-through query options for result construction later */
952-
rb_iv_set(resultObj, "@query_options", rb_hash_dup(rb_iv_get(self, "@current_query_options")));
953-
954-
#ifdef HAVE_RUBY_ENCODING_H
955-
GetMysql2Result(resultObj, result_wrapper);
956-
result_wrapper->encoding = wrapper->encoding;
957-
#endif
934+
resultObj = rb_mysql_result_to_obj(self, wrapper->encoding, rb_hash_dup(rb_iv_get(self, "@current_query_options")), result);
958935
return resultObj;
959936

960937
}

ext/mysql2/result.c

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -64,27 +64,33 @@ static void rb_mysql_result_mark(void * wrapper) {
6464
rb_gc_mark(w->fields);
6565
rb_gc_mark(w->rows);
6666
rb_gc_mark(w->encoding);
67+
rb_gc_mark(w->client);
6768
}
6869
}
6970

7071
/* this may be called manually or during GC */
7172
static void rb_mysql_result_free_result(mysql2_result_wrapper * wrapper) {
7273
if (wrapper && wrapper->resultFreed != 1) {
74+
/* FIXME: this may call flush_use_result, which can hit the socket */
7375
mysql_free_result(wrapper->result);
7476
wrapper->resultFreed = 1;
77+
}
78+
}
79+
80+
/* this is called during GC */
81+
static void rb_mysql_result_free(void *ptr) {
82+
mysql2_result_wrapper * wrapper = ptr;
83+
rb_mysql_result_free_result(wrapper);
84+
85+
// If the GC gets to client first it will be nil
86+
if (wrapper->client != Qnil) {
7587
wrapper->client_wrapper->refcount--;
76-
if (wrapper->client_wrapper->refcount == 0 && wrapper->client_wrapper->freed) {
88+
if (wrapper->client_wrapper->refcount == 0) {
7789
xfree(wrapper->client_wrapper->client);
7890
xfree(wrapper->client_wrapper);
7991
}
8092
}
81-
}
8293

83-
/* this is called during GC */
84-
static void rb_mysql_result_free(void * wrapper) {
85-
mysql2_result_wrapper * w = wrapper;
86-
/* FIXME: this may call flush_use_result, which can hit the socket */
87-
rb_mysql_result_free_result(w);
8894
xfree(wrapper);
8995
}
9096

@@ -567,7 +573,7 @@ static VALUE rb_mysql_result_count(VALUE self) {
567573
}
568574

569575
/* Mysql2::Result */
570-
VALUE rb_mysql_result_to_obj(mysql_client_wrapper *client_wrapper, MYSQL_RES *r) {
576+
VALUE rb_mysql_result_to_obj(VALUE client, VALUE encoding, VALUE options, MYSQL_RES *r) {
571577
VALUE obj;
572578
mysql2_result_wrapper * wrapper;
573579
obj = Data_Make_Struct(cMysql2Result, mysql2_result_wrapper, rb_mysql_result_mark, rb_mysql_result_free, wrapper);
@@ -578,11 +584,16 @@ VALUE rb_mysql_result_to_obj(mysql_client_wrapper *client_wrapper, MYSQL_RES *r)
578584
wrapper->result = r;
579585
wrapper->fields = Qnil;
580586
wrapper->rows = Qnil;
581-
wrapper->encoding = Qnil;
587+
wrapper->encoding = encoding;
582588
wrapper->streamingComplete = 0;
583-
wrapper->client_wrapper = client_wrapper;
589+
wrapper->client = client;
590+
wrapper->client_wrapper = DATA_PTR(client);
584591
wrapper->client_wrapper->refcount++;
592+
585593
rb_obj_call_init(obj, 0, NULL);
594+
595+
rb_iv_set(obj, "@query_options", options);
596+
586597
return obj;
587598
}
588599

ext/mysql2/result.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22
#define MYSQL2_RESULT_H
33

44
void init_mysql2_result();
5-
VALUE rb_mysql_result_to_obj(mysql_client_wrapper *client_wrapper, MYSQL_RES * r);
5+
VALUE rb_mysql_result_to_obj(VALUE client, VALUE encoding, VALUE options, MYSQL_RES *r);
66

77
typedef struct {
88
VALUE fields;
99
VALUE rows;
10+
VALUE client;
1011
VALUE encoding;
1112
unsigned int numberOfFields;
1213
unsigned long numberOfRows;

0 commit comments

Comments
 (0)