- Code: Select all
typedef struct _shutdown_task {
cef_task_t task;
int ref_count;
} shutdown_task_t;
typedef struct _shutdown_task {
cef_task_t task;
int ref_count;
} shutdown_task_t;
typedef struct _shutdown_task {
cef_task_t task;
atomic_int ref_count;
} shutdown_task_t;
static void CEF_CALLBACK add_ref_shutdown_task(struct _cef_base_ref_counted_t* base) {
/**
* The shutdown_task to be referenced. Convert from base structure to our wrap structure
*/
shutdown_task_t* task = (shutdown_task_t*)base;
if (task == NULL)
return;
fprintf(stderr, "add_ref_shutdown_task.\n");
/* increment the reference count */
atomic_fetch_add(&task->ref_count, 1);
}
static int CEF_CALLBACK release_shutdown_task(struct _cef_base_ref_counted_t* base) {
shutdown_task_t* task = (shutdown_task_t*)base;
fprintf(stderr, "release_shutdown_task.\n");
if ( atomic_fetch_sub(&task->ref_count, 1) == 1) {
free(task);
task = NULL;
return 1;
}
return 0;
}
static int CEF_CALLBACK has_one_ref(struct _cef_base_ref_counted_t* base) {
shutdown_task_t* task = (shutdown_task_t*)base;
return task->ref_count == 1 ? 1 : 0;
}
static void CEF_CALLBACK shutdown_execute(struct _cef_task_t* task) {
fprintf(stderr, "shutdown.\n");
cef_quit_message_loop();
}
shutdown_task_t* create_shutdown_task() {
shutdown_task_t* task = (shutdown_task_t*)calloc(1, sizeof(shutdown_task_t));
task->task.base.size = sizeof(shutdown_task_t);
task->task.base.add_ref = add_ref_shutdown_task;
task->task.base.release = release_shutdown_task;
task->task.base.has_one_ref = has_one_ref;
task->task.execute = shutdown_execute;
task->ref_count = 1;
return task;
}
shutdown_task_t* task = create_shutdown_task();
cef_post_task(TID_UI, &task->task);
I usually see
add_ref_shutdown_task.
release_shutdown_task.
free(): invalid pointer
magreenblatt wrote:I usually see
add_ref_shutdown_task.
release_shutdown_task.
free(): invalid pointer
This is strange, because the reference count in your code starts at 1. So I would expect the free() after 2 calls to release_shutdown_task.
add_ref_shutdown_task.
release_shutdown_task.
add_ref_shutdown_task.
release_shutdown_task.
shutdown.
release_shutdown_task.
aleitner wrote:Sometimes it does succeed and we seeadd_ref_shutdown_task.
release_shutdown_task.
add_ref_shutdown_task.
release_shutdown_task.
shutdown.
release_shutdown_task.
aleitner wrote:
- Code: Select all
// release
static int CEF_CALLBACK release_shutdown_task(struct _cef_base_ref_counted_t* base) {
shutdown_task_t* task = (shutdown_task_t*)base;
fprintf(stderr, "release_shutdown_task.\n");
--task->ref_count;
if (task->ref_count == 0) {
if (task)
free(task);
return 1;
}
return 0;
}
static int CEF_CALLBACK release_shutdown_task(struct _cef_base_ref_counted_t* base) {
shutdown_task_t* task = (shutdown_task_t*)base;
int ref = --task->ref_count;
if (ref == 0) {
if (task)
free(task);
return 0;
}
return ref;
}
Returns true (1) if the resulting reference count is 0.
shutdown_task_t* task = create_shutdown_task();
cef_post_task(TID_UI, &task->task);
shutdown_task_t* task = create_shutdown_task();
cef_post_task(TID_UI, &task->task);
free(task);
Returns true (1) if the resulting reference count is 0.
I am still curious on what the advantage of implementing reference counting is over just manually calling free()
Users browsing this forum: No registered users and 196 guests