コード例 #1
0
int thorium_cfs_scheduler_dequeue(struct thorium_scheduler *self, struct thorium_actor **actor)
{
    struct thorium_cfs_scheduler *concrete_self;
    void *key;
    void *value;
    uint64_t virtual_runtime;
    int size;

    key = NULL;
    value = NULL;
    virtual_runtime = 0;

    concrete_self = self->concrete_self;
    size = core_red_black_tree_size(&concrete_self->tree);

    if (size == 0) {
        return 0;
    }

#ifdef SHOW_TIMELINE
    if (size >= 10 && self->node == 0 && self->worker == 1) {
            /*
        printf("[cfs_scheduler] %d actor are in the timeline\n", size);
        */
        thorium_cfs_scheduler_print(self);
    }
#endif

    /*
     * This is O(N)
     */
    key = core_red_black_tree_get_lowest_key(&concrete_self->tree);

    /*
     * This is O(1) because the tree always keep a cache of the last node.
     */
    value = core_red_black_tree_get(&concrete_self->tree, key);

    /*
     * This is also O(1) because the tree keeps a cache of the last node.
     */
    core_red_black_tree_delete(&concrete_self->tree, key);

    core_memory_copy(&virtual_runtime, key, sizeof(virtual_runtime));
    core_memory_copy(actor, value, sizeof(struct thorium_actor *));

#if 0
    printf("CFS dequeue -> virtual_runtime= %" PRIu64 " actor= %d\n",
                    virtual_runtime, thorium_actor_name(*actor));
#endif

    return 1;
}
コード例 #2
0
ファイル: message_multiplexer.c プロジェクト: bioparr/biosal
/*
 * This is O(n), that is if all thorium nodes have a buffer to flush.
 */
void thorium_message_multiplexer_test(struct thorium_message_multiplexer *self)
{
    /*
     * Check if the multiplexer has waited enough.
     */

    int index;
    struct thorium_multiplexed_buffer *multiplexed_buffer;
    int buffer_is_ready;

#if defined(THORIUM_MULTIPLEXER_USE_TREE) || defined(THORIUM_MULTIPLEXER_USE_HEAP)
    uint64_t *lowest_key;
    int *index_bucket;
#endif

    if (CORE_BITMAP_GET_FLAG(self->flags, FLAG_DISABLED)) {
        return;
    }

#ifdef THORIUM_MULTIPLEXER_TRACK_BUFFERS_WITH_CONTENT
    /*
     * Nothing to do, there is nothing to flush
     * in the system.
     */
    if (core_set_empty(&self->buffers_with_content)) {
        return;
    }
#endif

#if 1
    /*
     * Don't flush anything if the outbound ring is full,
     * which means there is congestion.
     *
     * This means that the throughput is at its maximum value. In that case,
     * it is better to generate even larger messages.
     */
    if (thorium_worker_has_outbound_traffic_congestion(self->worker)) {
        return;
    }

#endif

#ifdef DEBUG_MULTIPLEXER_TEST
    if (size >= DEBUG_MINIMUM_COUNT)
        thorium_printf("DEBUG multiplexer_test buffers with content: %d\n",
                    size);
#endif

#ifdef CHECK_PREDICTED_TRAFFIC_REDUCTION
    /*
     * 0.95 corresponds to 20 actor messages in 1 network message.
     * 0.90 corresponds to 10 actor messages in 1 network message.
     */
    acceptable_traffic_reduction = 0.90;
#endif

    /*
     * Get the destination with the oldest buffer.
     * If this one has not waited enough, then any other more recent
     * buffer has not waited enough neither.
     */
    while (1) {
#ifdef THORIUM_MULTIPLEXER_USE_TREE
        lowest_key = core_red_black_tree_get_lowest_key(&self->timeline);
        /*
        * The timeline is empty.
        */
        if (lowest_key == NULL)
            return;

#elif defined(THORIUM_MULTIPLEXER_USE_HEAP)
        lowest_key = NULL;
        core_binary_heap_get_root(&self->timeline, (void **)&lowest_key,
                            (void **)&index_bucket);
        /*
        * The timeline is empty.
        */
        if (lowest_key == NULL)
            return;

#elif defined(THORIUM_MULTIPLEXER_USE_QUEUE)

        if (!core_queue_dequeue(&self->timeline, &index)) {
            return;
        }

#endif

        /*
        * Get the index.
        * The index is the destination.
        */
#ifdef THORIUM_MULTIPLEXER_USE_TREE
        index_bucket = core_red_black_tree_get(&self->timeline, lowest_key);
        index = *index_bucket;
#endif

        multiplexed_buffer = core_vector_at(&self->buffers, index);

        buffer_is_ready = thorium_message_multiplexer_buffer_is_ready(self, multiplexed_buffer);

        /*
        * The oldest item is too recent.
        * Therefore, all the others are too recent too
        * because the timeline is ordered.
        */
        if (!buffer_is_ready) {
#ifdef THORIUM_MULTIPLEXER_USE_QUEUE
            core_queue_enqueue(&self->timeline, &index);
#endif
            return;
        }

#ifdef CHECK_OUTBOUND_THROUGHPUT
        /*
        * Don't flush now since the transport layer has already reached its maximum
        * throughput.
        */
        if (thorium_worker_has_reached_maximum_outbound_throughput(self->worker)
                      && traffic_reduction < acceptable_traffic_reduction) {
#ifdef THORIUM_MULTIPLEXER_USE_QUEUE
            core_queue_enqueue(&self->timeline, &index);
#endif
            return;
        }
#endif

    /*
     * Remove the object from the timeline.
     */

#ifdef THORIUM_MULTIPLEXER_USE_TREE
        core_red_black_tree_delete(&self->timeline, lowest_key);
#elif defined(THORIUM_MULTIPLEXER_USE_HEAP)
        core_binary_heap_delete_root(&self->timeline);
#endif

#ifdef VERIFY_TARGET
        /*
        * Verify if the buffer can grow more.
        */
        if (!thorium_multiplexed_buffer_has_reached_target(multiplexed_buffer)) {
            thorium_multiplexed_buffer_set_time(multiplexed_buffer, time);

            core_red_black_tree_add_key_and_value(&self->timeline, &time, &index);

            return;
        }
#endif

        /*
        * The item won't have content in the case were _flush()
        * was called elsewhere with FORCE_YES_SIZE.
        */
#ifdef THORIUM_MULTIPLEXER_TRACK_BUFFERS_WITH_CONTENT
        if (core_set_find(&self->buffers_with_content, &index)) {
#endif
            thorium_message_multiplexer_flush(self, index, FORCE_YES_TIME);

#ifdef THORIUM_MULTIPLEXER_TRACK_BUFFERS_WITH_CONTENT
        }
#endif

        /*
         * Otherwise, keep flushing stuff.
         * This will eventually end anyway.
         */
    }
}