Пример #1
0
void workerpool_run_single(workerpool_t *wp)
{
    for (int i = 0; i < zarray_size(wp->tasks); i++) {
        struct task *task;
        zarray_get_volatile(wp->tasks, i, &task);
        task->f(task->p);
    }

    zarray_clear(wp->tasks);
}
Пример #2
0
// Do a quick swap:
void vx_buffer_swap(vx_buffer_t * buffer)
{
    pthread_mutex_lock(&buffer->mutex);
    {
        // It's possible that the serialization is running behind,
        // and may not have already serialized the pending_objs
        // In that case, they are discarded here, momentarily blocking
        // the calling thread.
        if (zarray_size(buffer->pending_objs) > 0) {
            // *+*+ corresponding decrement (if falling behind)
            zarray_vmap(buffer->pending_objs, vx_object_dec_destroy);
            zarray_clear(buffer->pending_objs);
            static int once = 1;
            if (once) {
                once = 0;
                printf("NFO: World serialization fell behind\n");
            }
        }

        // swap
        zarray_t * tmp = buffer->pending_objs;
        buffer->pending_objs = buffer->back_objs;
        buffer->back_objs = tmp;
    }
    pthread_mutex_unlock(&buffer->mutex);

    // Now flag a swap on the serialization thread
    pthread_mutex_lock(&buffer->world->queue_mutex);
    {
        // Ensure that the string is already in the queue, or add it if
        // it isn't. Duplicates are prohibited
        int index = -1;
        for (int i = 0, sz = zarray_size(buffer->world->buffer_queue); i < sz; i++) {
            char * test = NULL;
            zarray_get(buffer->world->buffer_queue, i, &test);

            if (strcmp(test, buffer->name) == 0) {
                index = i;
                break;
            }
        }
        if (index < 0) {
            zarray_add(buffer->world->buffer_queue, &buffer->name);
            pthread_cond_signal(&buffer->world->queue_cond);
        }
    }
    pthread_mutex_unlock(&buffer->world->queue_mutex);

}
Пример #3
0
// runs all added tasks, waits for them to complete.
void workerpool_run(workerpool_t *wp)
{
    if (wp->nthreads > 1) {
        wp->end_count = 0;

        pthread_mutex_lock(&wp->mutex);
        pthread_cond_broadcast(&wp->startcond);

        while (wp->end_count < wp->nthreads) {
//            printf("caught %d\n", wp->end_count);
            pthread_cond_wait(&wp->endcond, &wp->mutex);
        }

        pthread_mutex_unlock(&wp->mutex);

        wp->taskspos = 0;

        zarray_clear(wp->tasks);

    } else {
        workerpool_run_single(wp);
    }
}
Пример #4
0
static void * movie_run(void * params)
{
    state_t * state = params;

    zarray_t * frames = zarray_create(sizeof(movie_frame_t*));

    char * last_filename = NULL;
    char * current_filename = NULL;

    gzFile gzMovie = NULL;
    int movie_frames = 0;
    int lost_frames = 0;
    uint64_t movie_start_mtime = 0;

    while (state->rendering) {


        pthread_mutex_lock(&state->movie_mutex);
        while (state->rendering && current_filename == state->movie_file && zarray_size(state->movie_pending) == 0)
            pthread_cond_wait(&state->movie_cond, &state->movie_mutex);

        if (!state->rendering) // exit signaled while waiting on cond
            break;

        for (int i = 0; i < zarray_size(state->movie_pending); i++) {
            movie_frame_t * tmp = NULL;
            zarray_get(state->movie_pending, i, &tmp);
            zarray_add(frames, &tmp);
        }
        zarray_clear(state->movie_pending);
        current_filename = state->movie_file;

        pthread_mutex_unlock(&state->movie_mutex);


        // Depending on setup, execute different actions
        // 1) Open 2) Close 3) Write a frame

        if (zarray_size(frames) > 0 && current_filename != NULL) {

            // Write the most recent frame, dump the rest
            movie_frame_t * movie_img = NULL;
            zarray_get(frames, zarray_size(frames)-1, &movie_img);
            zarray_remove_index(frames, zarray_size(frames)-1, 0);

            char header[256];
            sprintf(header, "#mtime=%"PRIu64"\nP6 %d %d %d\n", movie_img->mtime, movie_img->width, movie_img->height, 255);
            int header_len = strlen(header);
            int imglen = movie_img->stride*movie_img->height;// RGB format

            gzwrite(gzMovie, header, header_len);
            gzwrite(gzMovie, movie_img->buf, imglen);
            int res = gzflush(gzMovie, Z_SYNC_FLUSH);

            if (res != Z_OK) {
                int errval = 0;
                printf("Error writing movie %s. Closing file\n", gzerror(gzMovie, &errval));
                gzclose(gzMovie);
                free(current_filename);
                current_filename = NULL;
            }
            movie_frames++;
            movie_frame_destroy (movie_img);
        }
        // cleanup the frames:
        lost_frames += zarray_size(frames);
        zarray_vmap(frames, movie_frame_destroy);
        zarray_clear(frames);


        // Got a new filename, need to start recording
        if (current_filename != NULL && last_filename == NULL)
        {

            gzMovie = gzopen(current_filename, "w3");
            movie_frames = 0;
            lost_frames = 0;
            movie_start_mtime = vx_mtime();

            printf("NFO: Starting movie at %s\n", current_filename);

            if (gzMovie == NULL) {
                printf("WRN: Unable to start movie at %s\n", current_filename);
                free(current_filename); // XXX Would need to edit
                                        // state->movie_file ?
                current_filename = NULL;
            }
        }


        if (current_filename == NULL && last_filename != NULL)
        {

            gzclose(gzMovie);

            printf("NFO: Wrote/lost %d/%d movie frames at %.2f fps to %s\n",
                   movie_frames, lost_frames, 1e3 * movie_frames / (vx_mtime() - movie_start_mtime), last_filename);

            free(last_filename);
        }


        last_filename = current_filename;
    }

    // XXX Cleanup? might shutdown while recording?

    return NULL;
}
Пример #5
0
// Call this only from the serialization thread
//
static void delayed_swap(vx_buffer_t * buffer)
{
    if (!buffer->front_objs)
        return; // buffer has not yet finished initialization
    if (verbose) printf("DBG: swap %s\n", buffer->name);

    pthread_mutex_lock(&buffer->mutex);
    {
        // clear existing front
        buffer->front_codes->pos = 0; // reset

        // *+*+ corresponding decrement (if keeping up)
        zarray_vmap(buffer->front_objs, vx_object_dec_destroy);
        zarray_clear(buffer->front_objs);


        // swap out the pending objects without tying up this mutex for too long
        zarray_t * tmp = buffer->front_objs;
        buffer->front_objs = buffer->pending_objs;
        buffer->pending_objs = tmp; // empty
    }
    pthread_mutex_unlock(&buffer->mutex);

    vx_world_t * world = buffer->world;
    zhash_t * old_resources = buffer->front_resc;

    // Serialize each object into resources and opcodes
    vx_code_output_stream_t * codes = buffer->front_codes;

    codes->write_uint32(codes, OP_BUFFER_CODES);
    codes->write_uint32(codes, world->worldID);
    codes->write_str(codes, buffer->name);
    codes->write_uint32(codes, buffer->draw_order); // XXX We should move this op code elsewhere

    zhash_t * resources = zhash_create(sizeof(uint64_t),sizeof(vx_resc_t*), zhash_uint64_hash, zhash_uint64_equals);

    for (int i = 0; i < zarray_size(buffer->front_objs); i++) {
        vx_object_t * obj = NULL;
        zarray_get(buffer->front_objs, i, &obj);
        obj->append(obj, resources, codes);
    }

    // *&&* we will hold on to these until next swap() call
    zhash_vmap_values(resources, vx_resc_inc_ref);

    zhash_t * all_resources = zhash_copy(resources);
    addAll(all_resources, old_resources);

    // Claim use of the union of the last frame, and the current frame
    // this avoids a race condition where another buffer (maybe in another world)
    // could force deallocation of some resources before the new render codes arrive
    if (verbose) printf("DBG: claim union via codes\n");
    if (verbose > 1)  {
        printf("  claimed %d IDS ", zhash_size(all_resources));
        zhash_vmap_values(all_resources, _print_id);
        printf("\n");
    }
    send_buffer_resource_codes(buffer, all_resources);

    if (verbose) printf("DBG: Send actual resources\n");
    if (verbose > 1)  {
        printf("  send %d IDS ", zhash_size(all_resources));
        zhash_vmap_values(all_resources, _print_id);
        printf("\n");
    }
    notify_listeners_send_resources(world, all_resources);

    if (verbose) printf("DBG: send render codes\n");
    notify_listeners_codes(world, codes);

    // Claim the actual set of resources which are in use now, which may result in some
    // resources being deleted from the gl context
    if (verbose) printf("DBG: reduce claim to actual in use\n");
    if (verbose > 1)  {
        printf("  actual %d IDS ", zhash_size(resources));
        zhash_vmap_values(resources, _print_id);
        printf("\n\n");
    }
    send_buffer_resource_codes(buffer, resources);



    buffer->front_resc = resources; // set of current resources

    zhash_destroy(all_resources);

    // *&&* corresponding decrement of resources
    zhash_vmap_values(old_resources, vx_resc_dec_destroy);
    zhash_destroy(old_resources);

}