コード例 #1
0
ファイル: SDL_timer.c プロジェクト: inolen/redream
int
SDL_TimerInit(void)
{
    SDL_TimerData *data = &SDL_timer_data;

    if (!SDL_AtomicGet(&data->active)) {
        const char *name = "SDLTimer";
        data->timermap_lock = SDL_CreateMutex();
        if (!data->timermap_lock) {
            return -1;
        }

        data->sem = SDL_CreateSemaphore(0);
        if (!data->sem) {
            SDL_DestroyMutex(data->timermap_lock);
            return -1;
        }

        SDL_AtomicSet(&data->active, 1);

        /* Timer threads use a callback into the app, so we can't set a limited stack size here. */
        data->thread = SDL_CreateThreadInternal(SDL_TimerThread, name, 0, data);
        if (!data->thread) {
            SDL_TimerQuit();
            return -1;
        }

        SDL_AtomicSet(&data->nextID, 1);
    }
    return 0;
}
コード例 #2
0
static void
XAUDIO2_WaitDevice(_THIS)
{
    if (SDL_AtomicGet(&this->enabled)) {
        SDL_SemWait(this->hidden->semaphore);
    }
}
コード例 #3
0
ファイル: SDL_timer.c プロジェクト: inolen/redream
SDL_bool
SDL_RemoveTimer(SDL_TimerID id)
{
    SDL_TimerData *data = &SDL_timer_data;
    SDL_TimerMap *prev, *entry;
    SDL_bool canceled = SDL_FALSE;

    /* Find the timer */
    SDL_LockMutex(data->timermap_lock);
    prev = NULL;
    for (entry = data->timermap; entry; prev = entry, entry = entry->next) {
        if (entry->timerID == id) {
            if (prev) {
                prev->next = entry->next;
            } else {
                data->timermap = entry->next;
            }
            break;
        }
    }
    SDL_UnlockMutex(data->timermap_lock);

    if (entry) {
        if (!SDL_AtomicGet(&entry->timer->canceled)) {
            SDL_AtomicSet(&entry->timer->canceled, 1);
            canceled = SDL_TRUE;
        }
        SDL_free(entry);
    }
    return canceled;
}
コード例 #4
0
ファイル: testatomic.c プロジェクト: D-Quick/DQuick
static SDL_bool DequeueEvent_LockFree(SDL_EventQueue *queue, SDL_Event *event)
{
    SDL_EventQueueEntry *entry;
    unsigned queue_pos;
    unsigned entry_seq;
    int delta;
    SDL_bool status;

#ifdef TEST_SPINLOCK_FIFO
    /* This is a gate so an external thread can lock the queue */
    SDL_AtomicLock(&queue->lock);
    SDL_assert(SDL_AtomicGet(&queue->watcher) == 0);
    SDL_AtomicIncRef(&queue->rwcount);
    SDL_AtomicUnlock(&queue->lock);
#endif

    queue_pos = (unsigned)SDL_AtomicGet(&queue->dequeue_pos);
    for ( ; ; ) {
        entry = &queue->entries[queue_pos & WRAP_MASK];
        entry_seq = (unsigned)SDL_AtomicGet(&entry->sequence);

        delta = (int)(entry_seq - (queue_pos + 1));
        if (delta == 0) {
            /* The entry and the queue position match, try to increment the queue position */
            if (SDL_AtomicCAS(&queue->dequeue_pos, (int)queue_pos, (int)(queue_pos+1))) {
                /* We own the object, fill it! */
                *event = entry->event;
                SDL_AtomicSet(&entry->sequence, (int)(queue_pos+MAX_ENTRIES));
                status = SDL_TRUE;
                break;
            }
        } else if (delta < 0) {
            /* We ran into an old queue entry, which means we've hit empty */
            status = SDL_FALSE;
            break;
        } else {
            /* We ran into a new queue entry, get the new queue position */
            queue_pos = (unsigned)SDL_AtomicGet(&queue->dequeue_pos);
        }
    }

#ifdef TEST_SPINLOCK_FIFO
    SDL_AtomicDecRef(&queue->rwcount);
#endif
    return status;
}
コード例 #5
0
ファイル: SDL_androidaudio.c プロジェクト: GWRon/sdl.mod
/* Pause (block) all non already paused audio devices by taking their mixer lock */
void ANDROIDAUDIO_PauseDevices(void)
{
    /* TODO: Handle multiple devices? */
    struct SDL_PrivateAudioData *private;
    if(audioDevice != NULL && audioDevice->hidden != NULL) {
        private = (struct SDL_PrivateAudioData *) audioDevice->hidden;
        if (SDL_AtomicGet(&audioDevice->paused)) {
            /* The device is already paused, leave it alone */
            private->resume = SDL_FALSE;
        }
コード例 #6
0
ファイル: thread.c プロジェクト: dotlive/LearnLUA
static void
destroy(LuaThread *t)
{
	(void)SDL_AtomicDecRef(&t->ref);

	if (SDL_AtomicGet(&t->ref) == 0) {
		lua_close(t->L);
		free(t);
	}
}
コード例 #7
0
ファイル: SDL_pulseaudio.c プロジェクト: 0-wiz-0/mame
static void
PULSEAUDIO_PlayDevice(_THIS)
{
    /* Write the audio data */
    struct SDL_PrivateAudioData *h = this->hidden;
    if (SDL_AtomicGet(&this->enabled)) {
        if (PULSEAUDIO_pa_stream_write(h->stream, h->mixbuf, h->mixlen, NULL, 0LL, PA_SEEK_RELATIVE) < 0) {
            SDL_OpenedAudioDeviceDisconnected(this);
        }
    }
}
コード例 #8
0
ファイル: SDL_alsa_audio.c プロジェクト: 0-wiz-0/mame
static void
ALSA_PlayDevice(_THIS)
{
    const Uint8 *sample_buf = (const Uint8 *) this->hidden->mixbuf;
    const int frame_size = (((int) SDL_AUDIO_BITSIZE(this->spec.format)) / 8) *
                                this->spec.channels;
    snd_pcm_uframes_t frames_left = ((snd_pcm_uframes_t) this->spec.samples);

    swizzle_alsa_channels(this, this->hidden->mixbuf, frames_left);

    while ( frames_left > 0 && SDL_AtomicGet(&this->enabled) ) {
        int status;

        /* This wait is a work-around for a hang when USB devices are
           unplugged.  Normally it should not result in any waiting,
           but in the case of a USB unplug, it serves as a way to
           join the playback thread after the timeout occurs */
        status = ALSA_snd_pcm_wait(this->hidden->pcm_handle, 1000);
        if (status == 0) {
            /*fprintf(stderr, "ALSA timeout waiting for available buffer space\n");*/
            SDL_OpenedAudioDeviceDisconnected(this);
            return;
        }

        status = ALSA_snd_pcm_writei(this->hidden->pcm_handle,
                                         sample_buf, frames_left);

        if (status < 0) {
            if (status == -EAGAIN) {
                /* Apparently snd_pcm_recover() doesn't handle this case -
                   does it assume snd_pcm_wait() above? */
                SDL_Delay(1);
                continue;
            }
            status = ALSA_snd_pcm_recover(this->hidden->pcm_handle, status, 0);
            if (status < 0) {
                /* Hmm, not much we can do - abort */
                fprintf(stderr, "ALSA write failed (unrecoverable): %s\n",
                        ALSA_snd_strerror(status));
                SDL_OpenedAudioDeviceDisconnected(this);
                return;
            }
            continue;
        }
        sample_buf += status * frame_size;
        frames_left -= status;
    }
}
コード例 #9
0
ファイル: SDL_pulseaudio.c プロジェクト: 0-wiz-0/mame
static int
PULSEAUDIO_CaptureFromDevice(_THIS, void *buffer, int buflen)
{
    struct SDL_PrivateAudioData *h = this->hidden;
    const void *data = NULL;
    size_t nbytes = 0;

    while (SDL_AtomicGet(&this->enabled)) {
        if (h->capturebuf != NULL) {
            const int cpy = SDL_min(buflen, h->capturelen);
            SDL_memcpy(buffer, h->capturebuf, cpy);
            /*printf("PULSEAUDIO: fed %d captured bytes\n", cpy);*/
            h->capturebuf += cpy;
            h->capturelen -= cpy;
            if (h->capturelen == 0) {
                h->capturebuf = NULL;
                PULSEAUDIO_pa_stream_drop(h->stream);  /* done with this fragment. */
            }
            return cpy;  /* new data, return it. */
        }

        if (PULSEAUDIO_pa_context_get_state(h->context) != PA_CONTEXT_READY ||
            PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY ||
            PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) {
            SDL_OpenedAudioDeviceDisconnected(this);
            return -1;  /* uhoh, pulse failed! */
        }

        if (PULSEAUDIO_pa_stream_readable_size(h->stream) == 0) {
            continue;  /* no data available yet. */
        }

        /* a new fragment is available! */
        PULSEAUDIO_pa_stream_peek(h->stream, &data, &nbytes);
        SDL_assert(nbytes > 0);
        if (data == NULL) {  /* NULL==buffer had a hole. Ignore that. */
            PULSEAUDIO_pa_stream_drop(h->stream);  /* drop this fragment. */
        } else {
            /* store this fragment's data, start feeding it to SDL. */
            /*printf("PULSEAUDIO: captured %d new bytes\n", (int) nbytes);*/
            h->capturebuf = (const Uint8 *) data;
            h->capturelen = nbytes;
        }
    }

    return -1;  /* not enabled? */
}
コード例 #10
0
ファイル: object.cpp プロジェクト: jspenguin/glbumper
void Object::destroy() throw() {

    GC::collect_mutex.lock();

    // If another thread just dereferenced a weak pointer to this
    // object, we might now have references. Now that we have the
    // lock, check the refcount again.

    if (SDL_AtomicGet(&refcount) > 0) {
	GC::collect_mutex.unlock();
	return;
    }

    SDL_AtomicSet(&refcount, 0);

    untrack();

    weakptrbase* cur = weak;
    weakptrbase* old;
    while (cur) {
	old = cur;
	cur = cur->next;
	old->set_ref(NULL);
    }

    // Avoid stack overflow.

    if (trashlevel < max_trashlevel) {
	++trashlevel;

	delete this;
	
	if (trashlevel == 1) {
	    while (!trashcan.empty()) {
		Object* op = static_cast<Object*>(trashcan.next);
		op->remove();
		delete op;
	    }
	}

	--trashlevel;
	
    } else {
	moveto(&trashcan);
    }
    GC::collect_mutex.unlock();
}
コード例 #11
0
ファイル: SDL_pulseaudio.c プロジェクト: 0-wiz-0/mame
/* This function waits until it is possible to write a full sound buffer */
static void
PULSEAUDIO_WaitDevice(_THIS)
{
    struct SDL_PrivateAudioData *h = this->hidden;

    while (SDL_AtomicGet(&this->enabled)) {
        if (PULSEAUDIO_pa_context_get_state(h->context) != PA_CONTEXT_READY ||
            PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY ||
            PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) {
            SDL_OpenedAudioDeviceDisconnected(this);
            return;
        }
        if (PULSEAUDIO_pa_stream_writable_size(h->stream) >= h->mixlen) {
            return;
        }
    }
}
コード例 #12
0
ファイル: SDL_alsa_audio.c プロジェクト: 0-wiz-0/mame
static int
ALSA_CaptureFromDevice(_THIS, void *buffer, int buflen)
{
    Uint8 *sample_buf = (Uint8 *) buffer;
    const int frame_size = (((int) SDL_AUDIO_BITSIZE(this->spec.format)) / 8) *
                                this->spec.channels;
    const int total_frames = buflen / frame_size;
    snd_pcm_uframes_t frames_left = total_frames;

    SDL_assert((buflen % frame_size) == 0);

    while ( frames_left > 0 && SDL_AtomicGet(&this->enabled) ) {
        /* !!! FIXME: This works, but needs more testing before going live */
        /* ALSA_snd_pcm_wait(this->hidden->pcm_handle, -1); */
        int status = ALSA_snd_pcm_readi(this->hidden->pcm_handle,
                                        sample_buf, frames_left);

        if (status < 0) {
            /*printf("ALSA: capture error %d\n", status);*/
            if (status == -EAGAIN) {
                /* Apparently snd_pcm_recover() doesn't handle this case -
                   does it assume snd_pcm_wait() above? */
                SDL_Delay(1);
                continue;
            }
            status = ALSA_snd_pcm_recover(this->hidden->pcm_handle, status, 0);
            if (status < 0) {
                /* Hmm, not much we can do - abort */
                fprintf(stderr, "ALSA read failed (unrecoverable): %s\n",
                        ALSA_snd_strerror(status));
                return -1;
            }
            continue;
        }

        /*printf("ALSA: captured %d bytes\n", status * frame_size);*/
        sample_buf += status * frame_size;
        frames_left -= status;
    }

    swizzle_alsa_channels(this, buffer, total_frames - frames_left);

    return (total_frames - frames_left) * frame_size;
}
コード例 #13
0
ファイル: testatomic.c プロジェクト: D-Quick/DQuick
/* This thread periodically locks the queue for no particular reason */
static int FIFO_Watcher(void* _data)
{
    SDL_EventQueue *queue = (SDL_EventQueue *)_data;

    while (queue->active) {
        SDL_AtomicLock(&queue->lock);
        SDL_AtomicIncRef(&queue->watcher);
        while (SDL_AtomicGet(&queue->rwcount) > 0) {
            SDL_Delay(0);
        }
        /* Do queue manipulation here... */
        SDL_AtomicDecRef(&queue->watcher);
        SDL_AtomicUnlock(&queue->lock);

        /* Wait a bit... */
        SDL_Delay(1);
    }
    return 0;
}
コード例 #14
0
ファイル: SDL_directsound.c プロジェクト: 0-wiz-0/mame
static int
DSOUND_CaptureFromDevice(_THIS, void *buffer, int buflen)
{
    struct SDL_PrivateAudioData *h = this->hidden;
    DWORD junk, cursor, ptr1len, ptr2len;
    VOID *ptr1, *ptr2;

    SDL_assert(buflen == this->spec.size);

    while (SDL_TRUE) {
        if (SDL_AtomicGet(&this->shutdown)) {  /* in case the buffer froze... */
            SDL_memset(buffer, this->spec.silence, buflen);
            return buflen;
        }

        if (IDirectSoundCaptureBuffer_GetCurrentPosition(h->capturebuf, &junk, &cursor) != DS_OK) {
            return -1;
        }
        if ((cursor / this->spec.size) == h->lastchunk) {
            SDL_Delay(1);  /* FIXME: find out how much time is left and sleep that long */
        } else {
            break;
        }
    }

    if (IDirectSoundCaptureBuffer_Lock(h->capturebuf, h->lastchunk * this->spec.size, this->spec.size, &ptr1, &ptr1len, &ptr2, &ptr2len, 0) != DS_OK) {
        return -1;
    }

    SDL_assert(ptr1len == this->spec.size);
    SDL_assert(ptr2 == NULL);
    SDL_assert(ptr2len == 0);

    SDL_memcpy(buffer, ptr1, ptr1len);

    if (IDirectSoundCaptureBuffer_Unlock(h->capturebuf, ptr1, ptr1len, ptr2, ptr2len) != DS_OK) {
        return -1;
    }

    h->lastchunk = (h->lastchunk + 1) % h->num_buffers;

    return ptr1len;
}
コード例 #15
0
/* Since XInput doesn't offer a way to vibrate for X time, we hook into
 *  SDL_PumpEvents() to check if it's time to stop vibrating with some
 *  frequency.
 * In practice, this works for 99% of use cases. But in an ideal world,
 *  we do this in a separate thread so that:
 *    - we aren't bound to when the app chooses to pump the event queue.
 *    - we aren't adding more polling to the event queue
 *    - we can emulate all the haptic effects correctly (start on a delay,
 *      mix multiple effects, etc).
 *
 * Mostly, this is here to get rumbling to work, and all the other features
 *  are absent in the XInput path for now.  :(
 */
static int SDLCALL
SDL_RunXInputHaptic(void *arg)
{
    struct haptic_hwdata *hwdata = (struct haptic_hwdata *) arg;

    while (!SDL_AtomicGet(&hwdata->stopThread)) {
        SDL_Delay(50);
        SDL_LockMutex(hwdata->mutex);
        /* If we're currently running and need to stop... */
        if (hwdata->stopTicks) {
            if ((hwdata->stopTicks != SDL_HAPTIC_INFINITY) && SDL_TICKS_PASSED(SDL_GetTicks(), hwdata->stopTicks)) {
                XINPUT_VIBRATION vibration = { 0, 0 };
                hwdata->stopTicks = 0;
                XINPUTSETSTATE(hwdata->userid, &vibration);
            }
        }
        SDL_UnlockMutex(hwdata->mutex);
    }

    return 0;
}
コード例 #16
0
static void
XAUDIO2_WaitDone(_THIS)
{
    IXAudio2SourceVoice *source = this->hidden->source;
    XAUDIO2_VOICE_STATE state;
    SDL_assert(!SDL_AtomicGet(&this->enabled));  /* flag that stops playing. */
    IXAudio2SourceVoice_Discontinuity(source);
#if SDL_XAUDIO2_WIN8
    IXAudio2SourceVoice_GetState(source, &state, XAUDIO2_VOICE_NOSAMPLESPLAYED);
#else
    IXAudio2SourceVoice_GetState(source, &state);
#endif
    while (state.BuffersQueued > 0) {
        SDL_SemWait(this->hidden->semaphore);
#if SDL_XAUDIO2_WIN8
        IXAudio2SourceVoice_GetState(source, &state, XAUDIO2_VOICE_NOSAMPLESPLAYED);
#else
        IXAudio2SourceVoice_GetState(source, &state);
#endif
    }
}
コード例 #17
0
static void
XAUDIO2_PlayDevice(_THIS)
{
    XAUDIO2_BUFFER buffer;
    Uint8 *mixbuf = this->hidden->mixbuf;
    Uint8 *nextbuf = this->hidden->nextbuf;
    const int mixlen = this->hidden->mixlen;
    IXAudio2SourceVoice *source = this->hidden->source;
    HRESULT result = S_OK;

    if (!SDL_AtomicGet(&this->enabled)) { /* shutting down? */
        return;
    }

    /* Submit the next filled buffer */
    SDL_zero(buffer);
    buffer.AudioBytes = mixlen;
    buffer.pAudioData = nextbuf;
    buffer.pContext = this;

    if (nextbuf == mixbuf) {
        nextbuf += mixlen;
    } else {
        nextbuf = mixbuf;
    }
    this->hidden->nextbuf = nextbuf;

    result = IXAudio2SourceVoice_SubmitSourceBuffer(source, &buffer, NULL);
    if (result == XAUDIO2_E_DEVICE_INVALIDATED) {
        /* !!! FIXME: possibly disconnected or temporary lost. Recover? */
    }

    if (result != S_OK) {  /* uhoh, panic! */
        IXAudio2SourceVoice_FlushSourceBuffers(source);
        SDL_OpenedAudioDeviceDisconnected(this);
    }
}
コード例 #18
0
static void
ALSA_PlayDevice(_THIS)
{
    const Uint8 *sample_buf = (const Uint8 *) this->hidden->mixbuf;
    const int frame_size = (((int) SDL_AUDIO_BITSIZE(this->spec.format)) / 8) *
                                this->spec.channels;
    snd_pcm_uframes_t frames_left = ((snd_pcm_uframes_t) this->spec.samples);

    swizzle_alsa_channels(this, this->hidden->mixbuf, frames_left);

    while ( frames_left > 0 && SDL_AtomicGet(&this->enabled) ) {
        /* !!! FIXME: This works, but needs more testing before going live */
        /* ALSA_snd_pcm_wait(this->hidden->pcm_handle, -1); */
        int status = ALSA_snd_pcm_writei(this->hidden->pcm_handle,
                                         sample_buf, frames_left);

        if (status < 0) {
            if (status == -EAGAIN) {
                /* Apparently snd_pcm_recover() doesn't handle this case -
                   does it assume snd_pcm_wait() above? */
                SDL_Delay(1);
                continue;
            }
            status = ALSA_snd_pcm_recover(this->hidden->pcm_handle, status, 0);
            if (status < 0) {
                /* Hmm, not much we can do - abort */
                fprintf(stderr, "ALSA write failed (unrecoverable): %s\n",
                        ALSA_snd_strerror(status));
                SDL_OpenedAudioDeviceDisconnected(this);
                return;
            }
            continue;
        }
        sample_buf += status * frame_size;
        frames_left -= status;
    }
}
コード例 #19
0
ファイル: testatomic.c プロジェクト: D-Quick/DQuick
static
void runAdder(void)
{
    Uint32 start, end;
    int T=NThreads;
 
    start = SDL_GetTicks();
 
    threadDone = SDL_CreateSemaphore(0);

    SDL_AtomicSet(&threadsRunning, NThreads);

    while (T--)
        SDL_CreateThread(adder, "Adder", NULL);
 
    while (SDL_AtomicGet(&threadsRunning) > 0)
        SDL_SemWait(threadDone);
 
    SDL_DestroySemaphore(threadDone);

    end = SDL_GetTicks();
 
    printf("Finished in %f sec\n", (end - start) / 1000.f);
}
コード例 #20
0
ファイル: la_port_android.c プロジェクト: OxyDeadbeef/jl-lib
JNIEXPORT jint JNICALL
Java_com_libaldaron_LibAldaronActivity_nativeLaDraw(JNIEnv *env, jobject obj) {
	la_window_loop__(la_window);
	if(SDL_AtomicGet(&la_rmcexit) == 0) return 100;
	else return 0;
}
コード例 #21
0
ファイル: la_port_android.c プロジェクト: OxyDeadbeef/jl-lib
/**
 * This is the main entry point of a native application that is using
 * android_native_app_glue.  It runs in its own thread, with its own
 * event loop for receiving input events and doing other things.
 */
void android_main(struct android_app* state) {
	la_window_t* window = la_memory_allocate(sizeof(la_window_t));
	int ident;
	int events;
	struct android_poll_source* source;

	// Make sure glue isn't stripped.
	app_dummy();

	state->userData = window;
	state->onAppCmd = window_handle_cmd;
	state->onInputEvent = window_handle_input;
	window->app = state;

	// Prepare to monitor accelerometer
	window->sensorManager = ASensorManager_getInstance();
	window->accelerometerSensor = ASensorManager_getDefaultSensor(
		window->sensorManager, ASENSOR_TYPE_ACCELEROMETER);
	window->sensorEventQueue = ASensorManager_createEventQueue(
		window->sensorManager, state->looper, LOOPER_ID_USER, NULL, NULL);

//	if (state->savedState != NULL) {
		// We are starting with a previous saved state; restore from it.
//		window->state = *(struct saved_state*)state->savedState;
//	}

	// Run main():
	la_window = window;

	// TODO: is needed?
	SDL_AtomicSet(&la_rmcexit, 1);
	// Window thread ( Drawing + Events ).
	while (SDL_AtomicGet(&la_rmcexit)) {
		// Poll Events
		ident = ALooper_pollAll(0, NULL, &events, (void**)&source);

		// Process this event.
		if (source != NULL) {
			source->process(state, source);
		}

		// If a sensor has data, process it now.
		if (ident == LOOPER_ID_USER) {
			if (window->accelerometerSensor != NULL) {
				ASensorEvent event;
				while (ASensorEventQueue_getEvents(
						window->sensorEventQueue,
						&event, 1) > 0)
				{
					window->input.accel.x =
						event.acceleration.x;
					window->input.accel.y =
						event.acceleration.y;
					window->input.accel.z =
						event.acceleration.z;
				}
			}
		}
		// Run the cross-platform window loop.
		if(window->context) la_window_loop__(window);
		// Update the screen.
		la_port_swap_buffers(window);
	}
	la_print("port-android quitting....");
	// The cross-platform window kill.
	la_window_kill__(window);
	// The window is being hidden or closed, clean it up.
	window_term_display(window);
	la_print("port-android quitted....");
	exit(0);
	return;
}
コード例 #22
0
ファイル: object.cpp プロジェクト: jspenguin/glbumper
inline void GC::update_refs(GCList* containers) {
    for (GCList *gc = containers->next; gc != containers; gc = gc->next) {
	Object* op = static_cast<Object*>(gc);
	op->gc_refs = SDL_AtomicGet(&op->refcount);
    }
}
コード例 #23
0
ファイル: object.cpp プロジェクト: jspenguin/glbumper
Object::~Object() {
    --num_objects;

    if (SDL_AtomicGet(&refcount) > 0)
	cerr << "Foo! deleting object " << str() << " with references!"<<endl;
}
コード例 #24
0
ファイル: object.cpp プロジェクト: jspenguin/glbumper
void Object::track() throw() {
    GC::collect_mutex.lock();

    if ((gc_refs == GC_TRACK_NOT_NEEDED) || !(gc_refs == GC_UNTRACKED || gc_refs == GC_NEW) || SDL_AtomicGet(&refcount) == -1) {
	GC::collect_mutex.unlock();
	return;
    }

    generations[0].count++; // number of allocated GC objects
    if (generations[0].count > generations[0].threshold &&
	GC::enabled &&
	!GC::collecting &&
	generations[0].threshold) {
	
	GC::collecting = true;
	GC::collect_generations();
	GC::collecting = false;
    }

    gc_refs = GC_REACHABLE;
    next = &generations[0];
    prev = generations[0].prev;
    prev->next = this;
    generations[0].prev = this;

    GC::collect_mutex.unlock();
}
コード例 #25
0
ファイル: SDL_timer.c プロジェクト: inolen/redream
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 (!SDL_AtomicGet(&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 (SDL_AtomicGet(&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;

                SDL_AtomicSet(&current->canceled, 1);
            }
        }

        /* 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;
}
コード例 #26
0
ファイル: testatomic.c プロジェクト: D-Quick/DQuick
static
void RunEpicTest()
{
    int b;
    atomicValue v;
 
    printf("\nepic test---------------------------------------\n\n");

    printf("Size asserted to be >= 32-bit\n");
    SDL_assert(sizeof(atomicValue)>=4);
 
    printf("Check static initializer\n");
    v=SDL_AtomicGet(&good);
    SDL_assert(v==42);
 
    SDL_assert(bad==42);
 
    printf("Test negative values\n");
    SDL_AtomicSet(&good, -5);
    v=SDL_AtomicGet(&good);
    SDL_assert(v==-5);
 
    printf("Verify maximum value\n");
    SDL_AtomicSet(&good, CountTo);
    v=SDL_AtomicGet(&good);
    SDL_assert(v==CountTo);
 
    printf("Test compare and exchange\n");
 
    b=SDL_AtomicCAS(&good, 500, 43);
    SDL_assert(!b); /* no swap since CountTo!=500 */
    v=SDL_AtomicGet(&good);
    SDL_assert(v==CountTo); /* ensure no swap */
 
    b=SDL_AtomicCAS(&good, CountTo, 44);
    SDL_assert(!!b); /* will swap */
    v=SDL_AtomicGet(&good);
    SDL_assert(v==44);
 
    printf("Test Add\n");
 
    v=SDL_AtomicAdd(&good, 1);
    SDL_assert(v==44);
    v=SDL_AtomicGet(&good);
    SDL_assert(v==45);
 
    v=SDL_AtomicAdd(&good, 10);
    SDL_assert(v==45);
    v=SDL_AtomicGet(&good);
    SDL_assert(v==55);
 
    printf("Test Add (Negative values)\n");
 
    v=SDL_AtomicAdd(&good, -20);
    SDL_assert(v==55);
    v=SDL_AtomicGet(&good);
    SDL_assert(v==35);
 
    v=SDL_AtomicAdd(&good, -50); /* crossing zero down */
    SDL_assert(v==35);
    v=SDL_AtomicGet(&good);
    SDL_assert(v==-15);
 
    v=SDL_AtomicAdd(&good, 30); /* crossing zero up */
    SDL_assert(v==-15);
    v=SDL_AtomicGet(&good);
    SDL_assert(v==15);
 
    printf("Reset before count down test\n");
    SDL_AtomicSet(&good, CountTo);
    v=SDL_AtomicGet(&good);
    SDL_assert(v==CountTo);
 
    bad=CountTo;
    SDL_assert(bad==CountTo);
 
    printf("Counting down from %d, Expect %d remaining\n",CountTo,Expect);
    runAdder();
 
    v=SDL_AtomicGet(&good);
    printf("Atomic %d Non-Atomic %d\n",v,bad);
    SDL_assert(v==Expect);
    SDL_assert(bad!=Expect);
}
コード例 #27
0
ファイル: SDL_timer.c プロジェクト: inolen/redream
SDL_TimerID
SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void *param)
{
    SDL_TimerData *data = &SDL_timer_data;
    SDL_Timer *timer;
    SDL_TimerMap *entry;

    SDL_AtomicLock(&data->lock);
    if (!SDL_AtomicGet(&data->active)) {
        if (SDL_TimerInit() < 0) {
            SDL_AtomicUnlock(&data->lock);
            return 0;
        }
    }

    timer = data->freelist;
    if (timer) {
        data->freelist = timer->next;
    }
    SDL_AtomicUnlock(&data->lock);

    if (timer) {
        SDL_RemoveTimer(timer->timerID);
    } else {
        timer = (SDL_Timer *)SDL_malloc(sizeof(*timer));
        if (!timer) {
            SDL_OutOfMemory();
            return 0;
        }
    }
    timer->timerID = SDL_AtomicIncRef(&data->nextID);
    timer->callback = callback;
    timer->param = param;
    timer->interval = interval;
    timer->scheduled = SDL_GetTicks() + interval;
    SDL_AtomicSet(&timer->canceled, 0);

    entry = (SDL_TimerMap *)SDL_malloc(sizeof(*entry));
    if (!entry) {
        SDL_free(timer);
        SDL_OutOfMemory();
        return 0;
    }
    entry->timer = timer;
    entry->timerID = timer->timerID;

    SDL_LockMutex(data->timermap_lock);
    entry->next = data->timermap;
    data->timermap = entry;
    SDL_UnlockMutex(data->timermap_lock);

    /* Add the timer to the pending list for the timer thread */
    SDL_AtomicLock(&data->lock);
    timer->next = data->pending;
    data->pending = timer;
    SDL_AtomicUnlock(&data->lock);

    /* Wake up the timer thread if necessary */
    SDL_SemPost(data->sem);

    return entry->timerID;
}
コード例 #28
0
ファイル: testatomic.c プロジェクト: D-Quick/DQuick
static
void RunBasicTest()
{
    int value;
    SDL_SpinLock lock = 0;

    SDL_atomic_t v;
    SDL_bool tfret = SDL_FALSE;

    printf("\nspin lock---------------------------------------\n\n");

    SDL_AtomicLock(&lock);
    printf("AtomicLock                   lock=%d\n", lock);
    SDL_AtomicUnlock(&lock);
    printf("AtomicUnlock                 lock=%d\n", lock);

    printf("\natomic -----------------------------------------\n\n");
     
    SDL_AtomicSet(&v, 0);
    tfret = SDL_AtomicSet(&v, 10) == 0;
    printf("AtomicSet(10)        tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v));
    tfret = SDL_AtomicAdd(&v, 10) == 10;
    printf("AtomicAdd(10)        tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v));

    SDL_AtomicSet(&v, 0);
    SDL_AtomicIncRef(&v);
    tfret = (SDL_AtomicGet(&v) == 1);
    printf("AtomicIncRef()       tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v));
    SDL_AtomicIncRef(&v);
    tfret = (SDL_AtomicGet(&v) == 2);
    printf("AtomicIncRef()       tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v));
    tfret = (SDL_AtomicDecRef(&v) == SDL_FALSE);
    printf("AtomicDecRef()       tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v));
    tfret = (SDL_AtomicDecRef(&v) == SDL_TRUE);
    printf("AtomicDecRef()       tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v));

    SDL_AtomicSet(&v, 10);
    tfret = (SDL_AtomicCAS(&v, 0, 20) == SDL_FALSE);
    printf("AtomicCAS()          tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v));
    value = SDL_AtomicGet(&v);
    tfret = (SDL_AtomicCAS(&v, value, 20) == SDL_TRUE);
    printf("AtomicCAS()          tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v));
}
コード例 #29
0
ファイル: testatomic.c プロジェクト: D-Quick/DQuick
static void RunFIFOTest(SDL_bool lock_free)
{
    SDL_EventQueue queue;
    WriterData writerData[NUM_WRITERS];
    ReaderData readerData[NUM_READERS];
    Uint32 start, end;
    int i, j;
    int grand_total;
 
    printf("\nFIFO test---------------------------------------\n\n");
    printf("Mode: %s\n", lock_free ? "LockFree" : "Mutex");

    readersDone = SDL_CreateSemaphore(0);
    writersDone = SDL_CreateSemaphore(0);

    SDL_memset(&queue, 0xff, sizeof(queue));

    InitEventQueue(&queue);
    if (!lock_free) {
        queue.mutex = SDL_CreateMutex();
    }

    start = SDL_GetTicks();
 
#ifdef TEST_SPINLOCK_FIFO
    /* Start a monitoring thread */
    if (lock_free) {
        SDL_CreateThread(FIFO_Watcher, "FIFOWatcher", &queue);
    }
#endif

    /* Start the readers first */
    printf("Starting %d readers\n", NUM_READERS);
    SDL_zero(readerData);
    SDL_AtomicSet(&readersRunning, NUM_READERS);
    for (i = 0; i < NUM_READERS; ++i) {
        char name[64];
        SDL_snprintf(name, sizeof (name), "FIFOReader%d", i);
        readerData[i].queue = &queue;
        readerData[i].lock_free = lock_free;
        SDL_CreateThread(FIFO_Reader, name, &readerData[i]);
    }

    /* Start up the writers */
    printf("Starting %d writers\n", NUM_WRITERS);
    SDL_zero(writerData);
    SDL_AtomicSet(&writersRunning, NUM_WRITERS);
    for (i = 0; i < NUM_WRITERS; ++i) {
        char name[64];
        SDL_snprintf(name, sizeof (name), "FIFOWriter%d", i);
        writerData[i].queue = &queue;
        writerData[i].index = i;
        writerData[i].lock_free = lock_free;
        SDL_CreateThread(FIFO_Writer, name, &writerData[i]);
    }
 
    /* Wait for the writers */
    while (SDL_AtomicGet(&writersRunning) > 0) {
        SDL_SemWait(writersDone);
    }
 
    /* Shut down the queue so readers exit */
    queue.active = SDL_FALSE;

    /* Wait for the readers */
    while (SDL_AtomicGet(&readersRunning) > 0) {
        SDL_SemWait(readersDone);
    }

    end = SDL_GetTicks();
 
    SDL_DestroySemaphore(readersDone);
    SDL_DestroySemaphore(writersDone);

    if (!lock_free) {
        SDL_DestroyMutex(queue.mutex);
    }
 
    printf("Finished in %f sec\n", (end - start) / 1000.f);

    printf("\n");
    for (i = 0; i < NUM_WRITERS; ++i) {
        printf("Writer %d wrote %d events, had %d waits\n", i, EVENTS_PER_WRITER, writerData[i].waits);
    }
    printf("Writers wrote %d total events\n", NUM_WRITERS*EVENTS_PER_WRITER);

    /* Print a breakdown of which readers read messages from which writer */
    printf("\n");
    grand_total = 0;
    for (i = 0; i < NUM_READERS; ++i) {
        int total = 0;
        for (j = 0; j < NUM_WRITERS; ++j) {
            total += readerData[i].counters[j];
        }
        grand_total += total;
        printf("Reader %d read %d events, had %d waits\n", i, total, readerData[i].waits);
        printf("  { ");
        for (j = 0; j < NUM_WRITERS; ++j) {
            if (j > 0) {
                printf(", ");
            }
            printf("%d", readerData[i].counters[j]);
        }
        printf(" }\n");
    }
    printf("Readers read %d total events\n", grand_total);
}
コード例 #30
0
static void
HandleAudioProcess(_THIS)
{
    Uint8 *buf = NULL;
    int byte_len = 0;
    int bytes = SDL_AUDIO_BITSIZE(this->spec.format) / 8;

    /* Only do something if audio is enabled */
    if (!SDL_AtomicGet(&this->enabled) || SDL_AtomicGet(&this->paused)) {
        return;
    }

    if (this->convert.needed) {
        const int bytes_in = SDL_AUDIO_BITSIZE(this->convert.src_format) / 8;

        if (this->hidden->conv_in_len != 0) {
            this->convert.len = this->hidden->conv_in_len * bytes_in * this->spec.channels;
        }

        (*this->spec.callback) (this->spec.userdata,
                                 this->convert.buf,
                                 this->convert.len);
        SDL_ConvertAudio(&this->convert);
        buf = this->convert.buf;
        byte_len = this->convert.len_cvt;

        /* size mismatch*/
        if (byte_len != this->spec.size) {
            if (!this->hidden->mixbuf) {
                this->hidden->mixlen = this->spec.size > byte_len ? this->spec.size * 2 : byte_len * 2;
                this->hidden->mixbuf = SDL_malloc(this->hidden->mixlen);
            }

            /* copy existing data */
            byte_len = copyData(this);

            /* read more data*/
            while (byte_len < this->spec.size) {
                (*this->spec.callback) (this->spec.userdata,
                                         this->convert.buf,
                                         this->convert.len);
                SDL_ConvertAudio(&this->convert);
                byte_len = copyData(this);
            }

            byte_len = this->spec.size;
            buf = this->hidden->mixbuf + this->hidden->read_off;
            this->hidden->read_off += byte_len;
        }

    } else {
        if (!this->hidden->mixbuf) {
            this->hidden->mixlen = this->spec.size;
            this->hidden->mixbuf = SDL_malloc(this->hidden->mixlen);
        }
        (*this->spec.callback) (this->spec.userdata,
                                 this->hidden->mixbuf,
                                 this->hidden->mixlen);
        buf = this->hidden->mixbuf;
        byte_len = this->hidden->mixlen;
    }

    if (buf) {
        EM_ASM_ARGS({
            var numChannels = SDL2.audio.currentOutputBuffer['numberOfChannels'];
            for (var c = 0; c < numChannels; ++c) {
                var channelData = SDL2.audio.currentOutputBuffer['getChannelData'](c);
                if (channelData.length != $1) {
                    throw 'Web Audio output buffer length mismatch! Destination size: ' + channelData.length + ' samples vs expected ' + $1 + ' samples!';
                }

                for (var j = 0; j < $1; ++j) {
                    channelData[j] = HEAPF32[$0 + ((j*numChannels + c) << 2) >> 2];
                }
            }
        }, buf, byte_len / bytes / this->spec.channels);
    }