Ejemplo n.º 1
0
int
SDL_SetTimer(Uint32 ms, SDL_TimerCallback callback)
{
    int retval;

#ifdef DEBUG_TIMERS
    printf("SDL_SetTimer(%d)\n", ms);
#endif
    retval = 0;

    if (SDL_timer_threaded) {
        SDL_mutexP(SDL_timer_mutex);
    }
    if (SDL_timer_running) {    /* Stop any currently running timer */
        if (SDL_timer_threaded) {
            while (SDL_timers) {
                SDL_TimerID freeme = SDL_timers;
                SDL_timers = SDL_timers->next;
                SDL_free(freeme);
            }
            SDL_timer_running = 0;
            list_changed = SDL_TRUE;
        } else {
            SDL_SYS_StopTimer();
            SDL_timer_running = 0;
        }
    }
    if (ms) {
        if (SDL_timer_threaded) {
            if (SDL_AddTimerInternal
                (ms, callback_wrapper, (void *) callback) == NULL) {
                retval = -1;
            }
        } else {
            SDL_timer_running = 1;
            SDL_alarm_interval = ms;
            SDL_alarm_callback = callback;
            retval = SDL_SYS_StartTimer();
        }
    }
    if (SDL_timer_threaded) {
        SDL_mutexV(SDL_timer_mutex);
    }

    return retval;
}
Ejemplo n.º 2
0
SDL_TimerID SDL_AddTimer(Uint32 interval, SDL_NewTimerCallback callback, void *param)
{
	SDL_TimerID t;
	if ( ! SDL_timer_mutex ) {
		if ( SDL_timer_started ) {
			SDL_SetError("This platform doesn't support multiple timers");
		} else {
			SDL_SetError("You must call SDL_Init(SDL_INIT_TIMER) first");
		}
		return NULL;
	}
	if ( ! SDL_timer_threaded ) {
		SDL_SetError("Multiple timers require threaded events!");
		return NULL;
	}
	SDL_mutexP(SDL_timer_mutex);
	t = SDL_AddTimerInternal(interval, callback, param);
	SDL_mutexV(SDL_timer_mutex);
	return t;
}
Ejemplo n.º 3
0
static int
SDL_TimerThread(void *_data)
{
    SDL_TimerData *data = (SDL_TimerData *)_data;
    SDL_Timer *pending;
    SDL_Timer *current;
    SDL_Timer *freelist_head = NULL;
    SDL_Timer *freelist_tail = NULL;
    Uint32 tick, now, interval, delay;

    /* Threaded timer loop:
     *  1. Queue timers added by other threads
     *  2. Handle any timers that should dispatch this cycle
     *  3. Wait until next dispatch time or new timer arrives
     */
    for ( ; ; ) {
        /* Pending and freelist maintenance */
        SDL_AtomicLock(&data->lock);
        {
            /* Get any timers ready to be queued */
            pending = data->pending;
            data->pending = NULL;

            /* Make any unused timer structures available */
            if (freelist_head) {
                freelist_tail->next = data->freelist;
                data->freelist = freelist_head;
            }
        }
        SDL_AtomicUnlock(&data->lock);

        /* Sort the pending timers into our list */
        while (pending) {
            current = pending;
            pending = pending->next;
            SDL_AddTimerInternal(data, current);
        }
        freelist_head = NULL;
        freelist_tail = NULL;

        /* Check to see if we're still running, after maintenance */
        if (!data->active) {
            break;
        }

        /* Initial delay if there are no timers */
        delay = SDL_MUTEX_MAXWAIT;

        tick = SDL_GetTicks();

        /* Process all the pending timers for this tick */
        while (data->timers) {
            current = data->timers;

            if ((Sint32)(tick-current->scheduled) < 0) {
                /* Scheduled for the future, wait a bit */
                delay = (current->scheduled - tick);
                break;
            }

            /* We're going to do something with this timer */
            data->timers = current->next;

            if (current->canceled) {
                interval = 0;
            } else {
                interval = current->callback(current->interval, current->param);
            }

            if (interval > 0) {
                /* Reschedule this timer */
                current->scheduled = tick + interval;
                SDL_AddTimerInternal(data, current);
            } else {
                if (!freelist_head) {
                    freelist_head = current;
                }
                if (freelist_tail) {
                    freelist_tail->next = current;
                }
                freelist_tail = current;

                current->canceled = SDL_TRUE;
            }
        }

        /* Adjust the delay based on processing time */
        now = SDL_GetTicks();
        interval = (now - tick);
        if (interval > delay) {
            delay = 0;
        } else {
            delay -= interval;
        }

        /* Note that each time a timer is added, this will return
           immediately, but we process the timers added all at once.
           That's okay, it just means we run through the loop a few
           extra times.
         */
        SDL_SemWaitTimeout(data->sem, delay);
    }
    return 0;
}