예제 #1
0
TEST_F(GQueueTest, insertSorted)
{
	int testData1 = 2;
	int testData2 = 0;
	int testData3 = 1;
	int testData4 = 3;
	int testUserData = 1337;

	compareLastUserData = NULL;
	g_queue_insert_sorted(queue, &testData1, test_compare_int_with_data, &testUserData);
	GList *first = queue->head;
	ASSERT_TRUE(compareLastUserData == NULL) << "user data should not have been passed when sorted inserting into empty queue";
	ASSERT_TRUE(first != NULL) << "queue head should not be NULL after inserting an element";
	ASSERT_EQ(first, queue->tail) << "queue tail should be equal to first element after inserting it";
	ASSERT_EQ(&testData1, first->data) << "first list element data should be set";
	ASSERT_TRUE(first->prev == NULL) << "first list element should not have a previous element";
	ASSERT_TRUE(first->next == NULL) << "first list element should not have a next element";
	ASSERT_EQ(1, queue->length) << "queue length should be one after inserting first element";

	compareLastUserData = NULL;
	g_queue_insert_sorted(queue, &testData2, test_compare_int_with_data, &testUserData);
	GList *second = queue->head;
	ASSERT_EQ(&testUserData, compareLastUserData) << "passed user data should have expected value";
	ASSERT_TRUE(second != NULL) << "queue head should not be NULL after inserting second element";
	ASSERT_NE(second, queue->tail) << "queue tail should not be equal to head after inserting second element";
	ASSERT_EQ(first, queue->tail) << "queue tail should be equal to first element after inserting second element";
	ASSERT_EQ(&testData2, second->data) << "second queue element data should be set";
	ASSERT_TRUE(second->prev == NULL) << "second queue element should not have a previous element";
	ASSERT_EQ(first, second->next) << "second queue element should have first as next element";
	ASSERT_EQ(second, first->prev) << "first queue element should have second as previous element";
	ASSERT_EQ(2, queue->length) << "queue length should be two after inserting second element";

	compareLastUserData = NULL;
	g_queue_insert_sorted(queue, &testData3, test_compare_int_with_data, &testUserData);
	GList *third = queue->head->next;
	ASSERT_EQ(&testUserData, compareLastUserData) << "passed user data should have expected value";
	ASSERT_EQ(second, queue->head) << "queue head element should still be equal to second element after inserting third element";
	ASSERT_EQ(first, queue->tail) << "queue tail should be equal to first element after inserting second element";
	ASSERT_EQ(&testData3, third->data) << "third list element data should be set";
	ASSERT_EQ(first, third->next) << "third list element should have first as next element";
	ASSERT_EQ(second, third->prev) << "third list element should have second as previous element";
	ASSERT_EQ(third, second->next) << "second list element should have third as next element";
	ASSERT_EQ(third, first->prev) << "first list element should have third as previous element";
	ASSERT_EQ(3, queue->length) << "queue length should be three after inserting third element";

	compareLastUserData = NULL;
	g_queue_insert_sorted(queue, &testData4, test_compare_int_with_data, &testUserData);
	GList *fourth = queue->tail;
	ASSERT_EQ(&testUserData, compareLastUserData) << "passed user data should have expected value";
	ASSERT_EQ(second, queue->head) << "queue head element should still be second after inserting fourth element";
	ASSERT_EQ(&testData4, fourth->data) << "fourth queue element data should be set";
	ASSERT_TRUE(fourth->next == NULL) << "fourth queue element should not have a next element";
	ASSERT_EQ(first, fourth->prev) << "fourth queue element should have first as previous element";
	ASSERT_EQ(fourth, first->next) << "first queue element should have fourth as next element";
	ASSERT_EQ(4, queue->length) << "queue length should be four after inserting fourth element";
}
예제 #2
0
파일: listbox.c 프로젝트: Distrotech/mc
/* Listbox item adding function */
static inline void
listbox_append_item (WListbox * l, WLEntry * e, listbox_append_t pos)
{
    if (l->list == NULL)
    {
        l->list = g_queue_new ();
        pos = LISTBOX_APPEND_AT_END;
    }

    switch (pos)
    {
    case LISTBOX_APPEND_AT_END:
        g_queue_push_tail (l->list, e);
        break;

    case LISTBOX_APPEND_BEFORE:
        g_queue_insert_before (l->list, g_queue_peek_nth_link (l->list, (guint) l->pos), e);
        break;

    case LISTBOX_APPEND_AFTER:
        g_queue_insert_after (l->list, g_queue_peek_nth_link (l->list, (guint) l->pos), e);
        break;

    case LISTBOX_APPEND_SORTED:
        g_queue_insert_sorted (l->list, e, (GCompareDataFunc) listbox_entry_cmp, NULL);
        break;

    default:
        break;
    }
}
예제 #3
0
파일: shd-tcp.c 프로젝트: icbaker/shadow
static void _tcp_bufferPacketOut(TCP* tcp, Packet* packet) {
	MAGIC_ASSERT(tcp);

	/* TCP wants to avoid congestion */
	g_queue_insert_sorted(tcp->throttledOutput, packet, (GCompareDataFunc)packet_compareTCPSequence, NULL);
	tcp->throttledOutputLength += packet_getPayloadLength(packet);
}
예제 #4
0
파일: shd-tcp.c 프로젝트: icbaker/shadow
static void _tcp_bufferPacketIn(TCP* tcp, Packet* packet) {
	MAGIC_ASSERT(tcp);

	/* TCP wants in-order data */
	g_queue_insert_sorted(tcp->unorderedInput, packet, (GCompareDataFunc)packet_compareTCPSequence, NULL);
	tcp->unorderedInputLength += packet_getPayloadLength(packet);
}
예제 #5
0
int partlist_insert_order(partlist *part, joblist *jlist, Job *job, int njobs) {
    int val = 0;
    int i;

    if (jlist[job->job].part != NULL) {
        fprintf(stderr, "Error: double insertion !!!!\n");
        val = 1;
        goto CLEAN;
    }

    jlist[job->job].part = part;
    g_queue_insert_sorted(part->list, job, (GCompareDataFunc)partition_order, NULL);

    for (i = job->job; i < njobs; ++i) {
        part->sumtimes[i] += job->processingime;
    }

    for (i = 0; i < job->job; ++i) {
        part->sumweights[i] += job->weight;
    }

    part->totcompweight += job->weight * part->sumtimes[job->job] +
                           job->processingime * part->sumweights[job->job];
    part->completiontime += job->processingime;
CLEAN:
    return val;
}
예제 #6
0
파일: dunst.c 프로젝트: buglloc/dunst
void update_lists()
{
    int limit;

    check_timeouts();

    if (pause_display) {
        while (displayed->length > 0) {
            g_queue_insert_sorted(queue, g_queue_pop_head(displayed),
                                  notification_cmp_data, NULL);
        }
        return;
    }

    if (xctx.geometry.h == 0) {
        limit = 0;
    } else if (xctx.geometry.h == 1) {
        limit = 1;
    } else if (settings.indicate_hidden) {
        limit = xctx.geometry.h - 1;
    } else {
        limit = xctx.geometry.h;
    }

    /* move notifications from queue to displayed */
    while (queue->length > 0) {

        if (limit > 0 && displayed->length >= limit) {
            /* the list is full */
            break;
        }

        notification *n = g_queue_pop_head(queue);

        if (!n)
            return;
        n->start = time(NULL);
        if (!n->redisplayed && n->script) {
            notification_run_script(n);
        }

        g_queue_insert_sorted(displayed, n, notification_cmp_data,
                              NULL);
    }
}
static GQueue* _torflowmanager_getMeasurableRelays(TorFlowManager* tfm) {
    GQueue* measurableRelays = g_queue_new();

    GHashTableIter iter;
    gpointer key, value;
    g_hash_table_iter_init(&iter, tfm->AllRelaysByFingerprint);
    while(g_hash_table_iter_next(&iter, &key, &value)) {
        TorFlowRelay* r = value;
        if(r && r->isFast && r->isRunning) {
            g_queue_insert_sorted(measurableRelays, r, torflowutil_compareRelaysData, NULL);
        }
    }

    return measurableRelays;
}
예제 #8
0
/*
 * Return 1 on success, if return 0 means the
 * packet will be dropped
 */
static int colo_insert_packet(GQueue *queue, Packet *pkt)
{
    if (g_queue_get_length(queue) <= MAX_QUEUE_SIZE) {
        if (pkt->ip->ip_p == IPPROTO_TCP) {
            g_queue_insert_sorted(queue,
                                  pkt,
                                  (GCompareDataFunc)seq_sorter,
                                  NULL);
        } else {
            g_queue_push_tail(queue, pkt);
        }
        return 1;
    }
    return 0;
}
예제 #9
0
/**
 * g_async_queue_push_sorted_unlocked:
 * @queue: a #GAsyncQueue
 * @data: the @data to push into the @queue
 * @func: the #GCompareDataFunc is used to sort @queue. This function
 *     is passed two elements of the @queue. The function should return
 *     0 if they are equal, a negative value if the first element
 *     should be higher in the @queue or a positive value if the first
 *     element should be lower in the @queue than the second element.
 * @user_data: user data passed to @func.
 * 
 * Inserts @data into @queue using @func to determine the new
 * position.
 * 
 * This function requires that the @queue is sorted before pushing on
 * new elements.
 * 
 * This function is called while holding the @queue's lock.
 * 
 * For an example of @func see g_async_queue_sort(). 
 *
 * Since: 2.10
 **/
void
g_async_queue_push_sorted_unlocked (GAsyncQueue      *queue,
				    gpointer          data,
				    GCompareDataFunc  func,
				    gpointer          user_data)
{
  SortData sd;
  
  g_return_if_fail (queue != NULL);

  sd.func = func;
  sd.user_data = user_data;

  g_queue_insert_sorted (queue->queue, 
			 data, 
			 (GCompareDataFunc)g_async_queue_invert_compare, 
			 &sd);
  if (queue->waiting_threads > 0)
    g_cond_signal (queue->cond);
}
예제 #10
0
파일: activity.c 프로젝트: perezerah/sleepd
/** 
* @brief Insert an activity into sorted list. 
* 
* @param  activity 
* @return false if the activity cannot be created (if activities are frozen).
*/
static bool 
_activity_insert(const char *activity_id, int duration_ms)
{
    bool ret = true;

    pthread_mutex_lock(&activity_mutex);

    if (gFrozen)
    {
        ret = false;
        goto end;
    }

    Activity *activity = _activity_new(activity_id, duration_ms);

    g_queue_insert_sorted(activity_roster, activity,
            (GCompareDataFunc)_activity_compare, NULL);

end:
    pthread_mutex_unlock(&activity_mutex);
    return ret;
}
예제 #11
0
int random_assignment(Job *jobarray, int njobs, int nmachines,
                      solution *new_sol, GRand *rand_) {
    int i, val = 0;
    double n;
    partlist *temp = (partlist *) NULL;
    Job *j = (Job *) NULL;
    GQueue *queue = (GQueue *) NULL;
    queue = g_queue_new();

    for (i = 0; i < nmachines; ++i) {
        g_queue_push_head(queue, new_sol->part + i);
    }

    for (i = 0; i < njobs; ++i) {
        j = jobarray + i;
        n = g_rand_double_range(rand_, 0.0, 1.0);

        if (n < 0.8) {
            temp = (partlist *) g_queue_pop_head(queue);
        } else if (n >= 0.8 && n < 0.95) {
            temp = (partlist *) g_queue_pop_nth(queue, 1);
        } else {
            if(nmachines > 2) {
                temp = (partlist *)g_queue_pop_nth(queue, 2);
            } else {
                temp = (partlist *)g_queue_pop_nth(queue, 1);
            }
        }

        val = partlist_insert(temp, new_sol->vlist, j);
        CCcheck_val_2(val, "Failed in partlist_insert_order");
        g_queue_insert_sorted(queue, temp, compare_func1, NULL);
    }

CLEAN:
    g_queue_free(queue);
    return val;
}
예제 #12
0
void
rpmostree_print_package_diffs (GVariant *variant)
{
  GQueue queue = G_QUEUE_INIT;
  GVariantIter iter;
  GVariant *child;

  /* GVariant format should be a(sua{sv}) */

  g_return_if_fail (variant != NULL);

  g_variant_iter_init (&iter, variant);

  /* Queue takes ownership of the child variant. */
  while ((child = g_variant_iter_next_value (&iter)) != NULL)
    g_queue_insert_sorted (&queue, child, pkg_diff_variant_compare, NULL);

  while (!g_queue_is_empty (&queue))
    {
      child = g_queue_pop_head (&queue);
      pkg_diff_variant_print (child);
      g_variant_unref (child);
    }
}
예제 #13
0
static void _parser_addAction(Parser* parser, Action* action) {
	MAGIC_ASSERT(parser);
	g_queue_insert_sorted(parser->actions, action, action_compare, NULL);
}
예제 #14
0
파일: notification.c 프로젝트: vivien/dunst
/*
 * Initialize the given notification and add it to
 * the queue. Replace notification with id if id > 0.
 */
int notification_init(notification * n, int id)
{

    if (n == NULL)
        return -1;

    if (strcmp("DUNST_COMMAND_PAUSE", n->summary) == 0) {
        pause_display = true;
        return 0;
    }

    if (strcmp("DUNST_COMMAND_RESUME", n->summary) == 0) {
        pause_display = false;
        return 0;
    }

    n->script = NULL;
    n->text_to_render = NULL;

    n->format = settings.format;

    rule_apply_all(n);

    n->urls = notification_extract_markup_urls(&(n->body));

    n->msg = string_replace("%a", n->appname, g_strdup(n->format));
    n->msg = string_replace("%s", n->summary, n->msg);
    if (n->icon) {
        n->msg = string_replace("%I", basename(n->icon), n->msg);
        n->msg = string_replace("%i", n->icon, n->msg);
    }
    n->msg = string_replace("%b", n->body, n->msg);
    if (n->progress) {
        char pg[10];
        sprintf(pg, "[%3d%%]", n->progress - 1);
        n->msg = string_replace("%p", pg, n->msg);
    } else {
        n->msg = string_replace("%p", "", n->msg);
    }

    if (!settings.allow_markup)
        n->msg = notification_fix_markup(n->msg);
    else if (!settings.ignore_newline) {
        n->msg = string_replace("<br>", "\n", n->msg);
        n->msg = string_replace("<br />", "\n", n->msg);
    }

    while (strstr(n->msg, "\\n") != NULL)
        n->msg = string_replace("\\n", "\n", n->msg);

    if (settings.ignore_newline)
        while (strstr(n->msg, "\n") != NULL)
            n->msg = string_replace("\n", " ", n->msg);

    n->msg = g_strstrip(n->msg);

    n->dup_count = 0;

    /* check if n is a duplicate */
    if (settings.stack_duplicates) {
        for (GList * iter = g_queue_peek_head_link(queue); iter;
                iter = iter->next) {
            notification *orig = iter->data;
            if (strcmp(orig->appname, n->appname) == 0
                    && strcmp(orig->summary, n->summary) == 0
                    && strcmp(orig->body, n->body) == 0) {
                /* If the progress differs this was probably intended to replace the notification
                 * but notify-send was used. So don't increment dup_count in this case
                 */
                if (orig->progress == n->progress) {
                    orig->dup_count++;
                } else {
                    orig->progress = n->progress;
                }
                /* notifications that differ only in progress hints should be expected equal,
                 * but we want the latest message, with the latest hint value
                 */
                free(orig->msg);
                orig->msg = strdup(n->msg);
                notification_free(n);
                wake_up();
                return orig->id;
            }
        }

        for (GList * iter = g_queue_peek_head_link(displayed); iter;
                iter = iter->next) {
            notification *orig = iter->data;
            if (strcmp(orig->appname, n->appname) == 0
                    && strcmp(orig->summary, n->summary) == 0
                    && strcmp(orig->body, n->body) == 0) {
                /* notifications that differ only in progress hints should be expected equal,
                 * but we want the latest message, with the latest hint value
                 */
                free(orig->msg);
                orig->msg = strdup(n->msg);
                /* If the progress differs this was probably intended to replace the notification
                 * but notify-send was used. So don't increment dup_count in this case
                 */
                if (orig->progress == n->progress) {
                    orig->dup_count++;
                } else {
                    orig->progress = n->progress;
                }
                orig->start = time(NULL);
                notification_free(n);
                wake_up();
                return orig->id;
            }
        }
    }

    /* urgency > CRIT -> array out of range */
    n->urgency = n->urgency > CRIT ? CRIT : n->urgency;

    if (!n->color_strings[ColFG]) {
        n->color_strings[ColFG] = xctx.color_strings[ColFG][n->urgency];
    }

    if (!n->color_strings[ColBG]) {
        n->color_strings[ColBG] = xctx.color_strings[ColBG][n->urgency];
    }

    n->timeout =
        n->timeout == -1 ? settings.timeouts[n->urgency] : n->timeout;
    n->start = 0;

    if (n->icon == NULL) {
        n->icon = settings.icons[n->urgency];
    }
    else if (strlen(n->icon) <= 0) {
        free(n->icon);
        n->icon = settings.icons[n->urgency];
    }

    if (n->category == NULL) {
        n->category = "";
    }

    n->timestamp = time(NULL);

    n->redisplayed = false;

    n->first_render = true;

    if (id == 0) {
        n->id = ++next_notification_id;
    } else {
        notification_close_by_id(id, -1);
        n->id = id;
    }

    if (strlen(n->msg) == 0) {
        notification_close(n, 2);
        printf("skipping notification: %s %s\n", n->body, n->summary);
    } else {
        g_queue_insert_sorted(queue, n, notification_cmp_data, NULL);
    }

    char *tmp = g_strconcat(n->summary, " ", n->body, NULL);

    char *tmp_urls = extract_urls(tmp);
    if (tmp_urls != NULL) {
        if (n->urls != NULL) {
            n->urls = string_append(n->urls, tmp_urls, "\n");
            free(tmp_urls);
        } else {
            n->urls = tmp_urls;
        }
    }

    if (n->actions) {
        n->actions->dmenu_str = NULL;
        for (int i = 0; i < n->actions->count; i += 2) {
            char *human_readable = n->actions->actions[i + 1];
            string_replace_char('[', '(', human_readable); // kill square brackets
            string_replace_char(']', ')', human_readable);

            n->actions->dmenu_str =
                string_append(n->actions->dmenu_str,
                              g_strdup_printf("#%s [%s]", human_readable,
                                              n->appname),
                              "\n");
        }
    }

    free(tmp);

    if (settings.print_notifications)
        notification_print(n);

    return n->id;
}
예제 #15
0
파일: shd-host.c 프로젝트: HackerJLY/shadow
static void _host_returnPreviousDescriptorHandle(Host* host, gint handle) {
    MAGIC_ASSERT(host);
    if(handle >= 3) {
        g_queue_insert_sorted(host->availableDescriptors, GINT_TO_POINTER(handle), _host_compareDescriptors, NULL);
    }
}
예제 #16
0
int32_t
ppb_message_loop_run_int(PP_Resource message_loop, int nested, int increase_depth)
{
    if (this_thread_message_loop != message_loop) {
        trace_error("%s, not attached to current thread\n", __func__);
        return PP_ERROR_WRONG_THREAD;
    }

    struct pp_message_loop_s *ml = pp_resource_acquire(message_loop, PP_RESOURCE_MESSAGE_LOOP);
    if (!ml) {
        trace_error("%s, bad resource\n", __func__);
        return PP_ERROR_BADRESOURCE;
    }

    // prevent nested loops
    if (!nested && ml->running) {
        trace_error("%s, trying to run nested loop without declaring as nested\n", __func__);
        pp_resource_release(message_loop);
        return PP_ERROR_INPROGRESS;
    }

    struct {
        int running;
        int teardown;
    } saved_state = {
        .running = ml->running,
        .teardown = ml->teardown,
    };

    ml->running = 1;
    ml->teardown = 0;
    if (increase_depth)
        ml->depth++;

    int teardown = 0;
    int destroy_ml = 0;
    int depth = ml->depth;
    pp_resource_ref(message_loop);
    GAsyncQueue *async_q = ml->async_q;
    GQueue *int_q = ml->int_q;
    pp_resource_release(message_loop);

    while (1) {
        struct timespec now;
        struct message_loop_task_s *task = g_queue_peek_head(int_q);
        gint64 timeout = 1000 * 1000;
        if (task) {
            clock_gettime(CLOCK_REALTIME, &now);
            timeout = (task->when.tv_sec - now.tv_sec) * 1000 * 1000 +
                      (task->when.tv_nsec - now.tv_nsec) / 1000;
            if (timeout <= 0) {
                // remove task from the queue
                g_queue_pop_head(int_q);

                // check if depth is correct
                if (task->depth > 0 && task->depth < depth) {
                    // wrong, reschedule it a bit later
                    task->when = add_ms(now, 10);
                    g_queue_insert_sorted(int_q, task, time_compare_func, NULL);
                    continue;
                }

                if (task->terminate) {
                    if (depth > 1) {
                        // exit at once, all remaining task will be processed by outer loop
                        g_slice_free(struct message_loop_task_s, task);
                        break;
                    }

                    // it's the outermost loop, we should wait for all tasks to be run
                    ml = pp_resource_acquire(message_loop, PP_RESOURCE_MESSAGE_LOOP);
                    if (ml) {
                        ml->teardown = 1;
                        teardown = 1;
                        destroy_ml = task->should_destroy_ml;
                        pp_resource_release(message_loop);
                    }

                    g_slice_free(struct message_loop_task_s, task);
                    continue;
                }

                // run task
                const struct PP_CompletionCallback ccb = task->ccb;
                if (ccb.func) {
                    ccb.func(ccb.user_data, task->result_to_pass);
                }

                // free task
                g_slice_free(struct message_loop_task_s, task);
                continue;   // run cycle again
            }
        } else if (teardown) {
            // teardown, no tasks in queue left
            break;
        }

        task = g_async_queue_timeout_pop(async_q, timeout);
        if (task)
            g_queue_insert_sorted(int_q, task, time_compare_func, NULL);
    }

    // mark thread as non-running
    ml = pp_resource_acquire(message_loop, PP_RESOURCE_MESSAGE_LOOP);
    if (ml) {
        if (increase_depth)
            ml->depth--;
        ml->running = 0;
        if (nested) {
            ml->running = saved_state.running;
            ml->teardown = saved_state.teardown;
        }
        pp_resource_release(message_loop);
    }
    pp_resource_unref(message_loop);
    if (destroy_ml)
        pp_resource_unref(message_loop);
    return PP_OK;
}

int32_t
ppb_message_loop_post_work_with_result(PP_Resource message_loop,
                                       struct PP_CompletionCallback callback, int64_t delay_ms,
                                       int32_t result_to_pass, int depth)
{
    if (callback.func == NULL) {
        trace_error("%s, callback.func == NULL\n", __func__);
        return PP_ERROR_BADARGUMENT;
    }

    struct pp_message_loop_s *ml = pp_resource_acquire(message_loop, PP_RESOURCE_MESSAGE_LOOP);
    if (!ml) {
        trace_error("%s, bad resource\n", __func__);
        return PP_ERROR_BADRESOURCE;
    }

    if (ml->running && ml->teardown) {
        // message loop is in a teardown state
        pp_resource_release(message_loop);
        trace_error("%s, quit request received, no additional work could be posted\n", __func__);
        return PP_ERROR_FAILED;
    }

    struct message_loop_task_s *task = g_slice_alloc0(sizeof(*task));

    task->result_to_pass = result_to_pass;
    task->ccb = callback;
    task->depth = depth;

    // calculate absolute time callback should be run at
    clock_gettime(CLOCK_REALTIME, &task->when);
    task->when.tv_sec += delay_ms / 1000;
    task->when.tv_nsec += (delay_ms % 1000) * 1000 * 1000;
    while (task->when.tv_nsec >= 1000 * 1000 * 1000) {
        task->when.tv_sec += 1;
        task->when.tv_nsec -= 1000 * 1000 * 1000;
    }

    g_async_queue_push(ml->async_q, task);
    pp_resource_release(message_loop);
    return PP_OK;
}

int32_t
ppb_message_loop_post_work(PP_Resource message_loop, struct PP_CompletionCallback callback,
                           int64_t delay_ms)
{
    return ppb_message_loop_post_work_with_result(message_loop, callback, delay_ms, PP_OK, 0);
}

int32_t
ppb_message_loop_post_quit_depth(PP_Resource message_loop, PP_Bool should_destroy, int depth)
{
    struct pp_message_loop_s *ml = pp_resource_acquire(message_loop, PP_RESOURCE_MESSAGE_LOOP);
    if (!ml) {
        trace_error("%s, bad resource\n", __func__);
        return PP_ERROR_BADRESOURCE;
    }

    struct message_loop_task_s *task = g_slice_alloc0(sizeof(*task));

    task->terminate = 1;
    task->depth = depth;
    task->should_destroy_ml = should_destroy;
    task->result_to_pass = PP_OK;

    clock_gettime(CLOCK_REALTIME, &task->when); // run as early as possible

    g_async_queue_push(ml->async_q, task);
    pp_resource_release(message_loop);
    return PP_OK;
}

int32_t
ppb_message_loop_post_quit(PP_Resource message_loop, PP_Bool should_destroy)
{
    int depth = ppb_message_loop_get_depth(message_loop);
    return ppb_message_loop_post_quit_depth(message_loop, should_destroy, depth);
}