*fixed an iterator disposing issue by referencing a collection weakly.
This commit is contained in:
parent
1a5667fdb5
commit
b6f4d53e2e
@ -339,6 +339,7 @@ typedef unsigned _ref_count_t;
|
|||||||
|
|
||||||
typedef struct _ref_t {
|
typedef struct _ref_t {
|
||||||
_ref_count_t* count;
|
_ref_count_t* count;
|
||||||
|
_ref_count_t* weak_count;
|
||||||
_unref_func_t on_unref;
|
_unref_func_t on_unref;
|
||||||
_data_e type;
|
_data_e type;
|
||||||
struct mb_interpreter_t* s;
|
struct mb_interpreter_t* s;
|
||||||
@ -391,6 +392,7 @@ typedef struct _list_t {
|
|||||||
} _list_t;
|
} _list_t;
|
||||||
|
|
||||||
typedef struct _list_it_t {
|
typedef struct _list_it_t {
|
||||||
|
_ref_t weak_ref;
|
||||||
_list_t* list;
|
_list_t* list;
|
||||||
bool_t locking;
|
bool_t locking;
|
||||||
union {
|
union {
|
||||||
@ -406,6 +408,7 @@ typedef struct _dict_t {
|
|||||||
} _dict_t;
|
} _dict_t;
|
||||||
|
|
||||||
typedef struct _dict_it_t {
|
typedef struct _dict_it_t {
|
||||||
|
_ref_t weak_ref;
|
||||||
_dict_t* dict;
|
_dict_t* dict;
|
||||||
bool_t locking;
|
bool_t locking;
|
||||||
unsigned int curr_bucket;
|
unsigned int curr_bucket;
|
||||||
@ -1396,6 +1399,8 @@ static bool_t _write_on_ref_object(_lock_t* lk, _ref_t* ref, void* obj);
|
|||||||
|
|
||||||
static _ref_count_t _ref(_ref_t* ref, void* data);
|
static _ref_count_t _ref(_ref_t* ref, void* data);
|
||||||
static bool_t _unref(_ref_t* ref, void* data);
|
static bool_t _unref(_ref_t* ref, void* data);
|
||||||
|
static _ref_count_t _weak_ref(_ref_t* ref, void* data, _ref_t* weak);
|
||||||
|
static bool_t _weak_unref(_ref_t* ref, void* data, _ref_t* weak);
|
||||||
static void _create_ref(_ref_t* ref, _unref_func_t dtor, _data_e t, mb_interpreter_t* s);
|
static void _create_ref(_ref_t* ref, _unref_func_t dtor, _data_e t, mb_interpreter_t* s);
|
||||||
static void _destroy_ref(_ref_t* ref);
|
static void _destroy_ref(_ref_t* ref);
|
||||||
|
|
||||||
@ -5174,7 +5179,7 @@ static _ref_count_t _ref(_ref_t* ref, void* data) {
|
|||||||
|
|
||||||
static bool_t _unref(_ref_t* ref, void* data) {
|
static bool_t _unref(_ref_t* ref, void* data) {
|
||||||
/* Decrease the reference of a stub by 1 */
|
/* Decrease the reference of a stub by 1 */
|
||||||
bool_t result = false;
|
bool_t result = true;
|
||||||
|
|
||||||
result = --(*ref->count) == _NONE_REF;
|
result = --(*ref->count) == _NONE_REF;
|
||||||
mb_assert(*ref->count >= _NONE_REF);
|
mb_assert(*ref->count >= _NONE_REF);
|
||||||
@ -5188,6 +5193,37 @@ static bool_t _unref(_ref_t* ref, void* data) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static _ref_count_t _weak_ref(_ref_t* ref, void* data, _ref_t* weak) {
|
||||||
|
/* Increase the weak reference of a stub by 1 */
|
||||||
|
_ref_count_t before = *ref->weak_count;
|
||||||
|
|
||||||
|
mb_unrefvar(data);
|
||||||
|
|
||||||
|
++(*ref->weak_count);
|
||||||
|
mb_assert(*ref->weak_count > before && "Too many referencing, weak_count overflow, please redefine _ref_count_t.");
|
||||||
|
memcpy(weak, ref, sizeof(_ref_t));
|
||||||
|
|
||||||
|
return *ref->weak_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool_t _weak_unref(_ref_t* ref, void* data, _ref_t* weak) {
|
||||||
|
/* Decrease the weak reference of a stub by 1 */
|
||||||
|
bool_t result = true;
|
||||||
|
mb_unrefvar(ref);
|
||||||
|
mb_unrefvar(data);
|
||||||
|
|
||||||
|
result = --(*weak->weak_count) == _NONE_REF;
|
||||||
|
mb_assert(*weak->weak_count >= _NONE_REF);
|
||||||
|
if(weak->count && *weak->count == _NONE_REF)
|
||||||
|
result = false;
|
||||||
|
if(weak->count && *weak->count == _NONE_REF && weak->weak_count && *weak->weak_count == _NONE_REF) {
|
||||||
|
safe_free(weak->weak_count);
|
||||||
|
safe_free(weak->count);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static void _create_ref(_ref_t* ref, _unref_func_t dtor, _data_e t, mb_interpreter_t* s) {
|
static void _create_ref(_ref_t* ref, _unref_func_t dtor, _data_e t, mb_interpreter_t* s) {
|
||||||
/* Create a reference stub, initialize the reference count with zero */
|
/* Create a reference stub, initialize the reference count with zero */
|
||||||
if(ref->count)
|
if(ref->count)
|
||||||
@ -5195,6 +5231,8 @@ static void _create_ref(_ref_t* ref, _unref_func_t dtor, _data_e t, mb_interpret
|
|||||||
|
|
||||||
ref->count = (_ref_count_t*)mb_malloc(sizeof(_ref_count_t));
|
ref->count = (_ref_count_t*)mb_malloc(sizeof(_ref_count_t));
|
||||||
*ref->count = _NONE_REF;
|
*ref->count = _NONE_REF;
|
||||||
|
ref->weak_count = (_ref_count_t*)mb_malloc(sizeof(_ref_count_t));
|
||||||
|
*ref->weak_count = _NONE_REF;
|
||||||
ref->on_unref = dtor;
|
ref->on_unref = dtor;
|
||||||
ref->type = t;
|
ref->type = t;
|
||||||
ref->s = s;
|
ref->s = s;
|
||||||
@ -5202,10 +5240,13 @@ static void _create_ref(_ref_t* ref, _unref_func_t dtor, _data_e t, mb_interpret
|
|||||||
|
|
||||||
static void _destroy_ref(_ref_t* ref) {
|
static void _destroy_ref(_ref_t* ref) {
|
||||||
/* Destroy a reference stub */
|
/* Destroy a reference stub */
|
||||||
if(!ref->count)
|
if(!ref->count || !ref->weak_count)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if(*ref->weak_count == _NONE_REF) {
|
||||||
|
safe_free(ref->weak_count);
|
||||||
safe_free(ref->count);
|
safe_free(ref->count);
|
||||||
|
}
|
||||||
ref->on_unref = 0;
|
ref->on_unref = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6036,6 +6077,7 @@ static _list_it_t* _create_list_it(_list_t* coll, bool_t lock) {
|
|||||||
result->curr.node = coll->list;
|
result->curr.node = coll->list;
|
||||||
if(lock)
|
if(lock)
|
||||||
_lock_ref_object(&coll->lock, &coll->ref, coll);
|
_lock_ref_object(&coll->lock, &coll->ref, coll);
|
||||||
|
_weak_ref(&coll->ref, coll, &result->weak_ref);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -6046,6 +6088,7 @@ static bool_t _destroy_list_it(_list_it_t* it) {
|
|||||||
|
|
||||||
mb_assert(it);
|
mb_assert(it);
|
||||||
|
|
||||||
|
if(_weak_unref(&it->list->ref, it->list, &it->weak_ref))
|
||||||
_unlock_ref_object(&it->list->lock, &it->list->ref, it->list);
|
_unlock_ref_object(&it->list->lock, &it->list->ref, it->list);
|
||||||
safe_free(it);
|
safe_free(it);
|
||||||
|
|
||||||
@ -6093,6 +6136,7 @@ static _dict_it_t* _create_dict_it(_dict_t* coll, bool_t lock) {
|
|||||||
result->curr_node = (_ls_node_t*)(intptr_t)~0;
|
result->curr_node = (_ls_node_t*)(intptr_t)~0;
|
||||||
if(lock)
|
if(lock)
|
||||||
_lock_ref_object(&coll->lock, &coll->ref, coll);
|
_lock_ref_object(&coll->lock, &coll->ref, coll);
|
||||||
|
_weak_ref(&coll->ref, coll, &result->weak_ref);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -6103,6 +6147,7 @@ static bool_t _destroy_dict_it(_dict_it_t* it) {
|
|||||||
|
|
||||||
mb_assert(it);
|
mb_assert(it);
|
||||||
|
|
||||||
|
if(_weak_unref(&it->dict->ref, it->dict, &it->weak_ref))
|
||||||
_unlock_ref_object(&it->dict->lock, &it->dict->ref, it->dict);
|
_unlock_ref_object(&it->dict->lock, &it->dict->ref, it->dict);
|
||||||
safe_free(it);
|
safe_free(it);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user