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; }
static void InitEventQueue(SDL_EventQueue *queue) { int i; for (i = 0; i < MAX_ENTRIES; ++i) { SDL_AtomicSet(&queue->entries[i].sequence, i); } SDL_AtomicSet(&queue->enqueue_pos, 0); SDL_AtomicSet(&queue->dequeue_pos, 0); #ifdef TEST_SPINLOCK_FIFO queue->lock = 0; SDL_AtomicSet(&queue->rwcount, 0); #endif queue->active = SDL_TRUE; }
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; }
int SDL_TimerInit(void) { SDL_TimerData *data = &SDL_timer_data; if (!data->active) { 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; } data->active = SDL_TRUE; /* !!! FIXME: this is nasty. */ #if (defined(__WIN32__) && !defined(_WIN32_WCE)) && !defined(HAVE_LIBC) #undef SDL_CreateThread data->thread = SDL_CreateThread(SDL_TimerThread, data, NULL, NULL); #else data->thread = SDL_CreateThread(SDL_TimerThread, data); #endif if (!data->thread) { SDL_TimerQuit(); return -1; } SDL_AtomicSet(&data->nextID, 1); } return 0; }
/* * Clean up after system specific haptic stuff */ void SDL_SYS_HapticQuit(void) { SDL_hapticlist_item *item; SDL_hapticlist_item *next = NULL; SDL_Haptic *hapticitem = NULL; extern SDL_Haptic *SDL_haptics; for (hapticitem = SDL_haptics; hapticitem; hapticitem = hapticitem->next) { if ((hapticitem->hwdata->bXInputHaptic) && (hapticitem->hwdata->thread)) { /* we _have_ to stop the thread before we free the XInput DLL! */ SDL_AtomicSet(&hapticitem->hwdata->stopThread, 1); SDL_WaitThread(hapticitem->hwdata->thread, NULL); hapticitem->hwdata->thread = NULL; } } for (item = SDL_hapticlist; item; item = next) { /* Opened and not closed haptics are leaked, this is on purpose. * Close your haptic devices after usage. */ /* !!! FIXME: (...is leaking on purpose a good idea?) - No, of course not. */ next = item->next; SDL_free(item->name); SDL_free(item); } SDL_XINPUT_HapticQuit(); SDL_DINPUT_HapticQuit(); numhaptics = 0; SDL_hapticlist = NULL; SDL_hapticlist_tail = NULL; }
DxVsyncSource::DxVsyncSource(Pacer* pacer) : m_Pacer(pacer), m_Thread(nullptr), m_Gdi32Handle(nullptr) { SDL_AtomicSet(&m_Stopping, 0); }
void SDL_XINPUT_HapticClose(SDL_Haptic * haptic) { SDL_AtomicSet(&haptic->hwdata->stopThread, 1); SDL_WaitThread(haptic->hwdata->thread, NULL); SDL_DestroyMutex(haptic->hwdata->mutex); }
int jrq_Init( JobRingQueue* queue, size_t size ) { assert( queue != NULL ); assert( size > 0 ); queue->size = size; queue->ringBuffer = mem_Allocate( sizeof( queue->ringBuffer[0] ) * size ); if( queue->ringBuffer == NULL ) { return -1; } memset( queue->ringBuffer, 0, size * sizeof( queue->ringBuffer[0] ) ); SDL_AtomicSet( &( queue->head ), 0 ); SDL_AtomicSet( &( queue->tail ), 0 ); SDL_AtomicSet( &( queue->busy ), 0 ); return 0; }
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)); }
DxVsyncSource::~DxVsyncSource() { if (m_Thread != nullptr) { SDL_AtomicSet(&m_Stopping, 1); SDL_WaitThread(m_Thread, nullptr); } if (m_Gdi32Handle != nullptr) { FreeLibrary(m_Gdi32Handle); } }
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(); }
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; }
void la_port_input(la_window_t* window) { // Touch Input window->input.touch.x = al_safe_get_float(&window->mouse_x); window->input.touch.y = al_safe_get_float(&window->mouse_y); window->input.touch.p = 0; if(safe_get_uint8(&window->in.touch.h)) { la_print("Just touch %d", safe_get_uint8(&window->in.touch.p)); window->input.touch.h = 1; window->input.touch.p = safe_get_uint8(&window->in.touch.p); // Not just pressed anymore safe_set_uint8(&window->in.touch.h, 0); }else{ window->input.touch.h = 0; } // if(safe_get_uint8(&window->in.back)) { la_print("Back"); safe_set_uint8(&window->in.back, 0); SDL_AtomicSet(&la_rmcexit, 0); } }
void Audio_init () { SDL_AudioSpec want; want.freq = 44100; want.format = AUDIO_S16LSB; want.channels = 2; want.samples = 2048; want.callback = Audio_mixer; want.userdata = NULL; if (App_get_option_IV("info")) { int i; printf("Audio devices:\n"); for (i = 0; i < SDL_GetNumAudioDevices(0); i++) { const char* name = SDL_GetAudioDeviceName(i, 0); printf("\t%s\n", name); } const char* cur = SDL_GetCurrentAudioDriver(); printf("Current audio driver:\n\t%s\n", cur); printf("Audio drivers:\n"); for (i = 0; i < SDL_GetNumAudioDrivers(); i++) { const char* name = SDL_GetAudioDriver(i); printf("\t%s\n", name); } } _audio.device = SDL_OpenAudioDevice(NULL, 0, &want, &_audio.spec, SDL_AUDIO_ALLOW_ANY_CHANGE); if (_audio.device <= 0) error("Could not open audio device"); if (!App_get_option_IV("mute")) _audio.volume = SDL_MIX_MAXVOLUME; (void)SDL_AtomicSet(&_audio.playback_rate, 1); SDL_PauseAudioDevice(_audio.device, 0); }
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); }
/** * 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; }
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(¤t->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(¤t->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; }
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); }
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; }
SampleData(void* _data, unsigned int _freq, unsigned int _len): audio_data(_data), sampling(_freq), length(_len) { SDL_AtomicSet(&refcnt, 1); }
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); }