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)); }
/* * SDL.createThread(name, source) * * Create a separate thread of execution. It creates a new Lua state that * does not share any data frmo the parent process. * * Arguments: * name, the thread name * source, a path to a Lua file or a function to call * * Returns: * The thread object or nil * The error message */ static int l_thread_create(lua_State *L) { const char *name = luaL_checkstring(L, 1); int ret, iv; LuaThread *thread; if ((thread = calloc(1, sizeof (LuaThread))) == NULL) return commonPushErrno(L, 1); thread->L = luaL_newstate(); luaL_openlibs(thread->L); ret = threadDump(L, thread->L, 2); /* If return number is 2, it is nil and the error */ if (ret == 2) goto failure; /* Iterate over the arguments to pass to the callback */ for (iv = 3; iv <= lua_gettop(L); ++iv) { Variant *v = variantGet(L, iv); if (v == NULL) { commonPushErrno(L, 1); goto failure; } variantPush(thread->L, v); variantFree(v); } thread->ptr = SDL_CreateThread((SDL_ThreadFunction)callback, name, thread); if (thread->ptr == NULL) { commonPushSDLError(L, 1); goto failure; } SDL_AtomicIncRef(&thread->ref); return commonPush(L, "p", ThreadName, thread); failure: lua_close(thread->L); free(thread); return 2; }
static int callback(LuaThread *t) { int ret = -1; SDL_AtomicIncRef(&t->ref); if (lua_pcall(t->L, lua_gettop(t->L) - 1, 1, 0) != LUA_OK) SDL_LogCritical(SDL_LOG_CATEGORY_SYSTEM, "%s", lua_tostring(t->L, -1)); else ret = lua_tointeger(t->L, -1); destroy(t); return ret; }
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; }
internal bool32 SDLDoNextWorkQueueEntry(platform_work_queue *Queue) { bool32 WeShouldSleep = false; int OriginalNextEntryToRead = Queue->NextEntryToRead.value; int NewNextEntryToRead = (OriginalNextEntryToRead + 1) % ArrayCount(Queue->Entries); if (OriginalNextEntryToRead != Queue->NextEntryToWrite.value) { if (SDL_AtomicCAS(&Queue->NextEntryToRead, OriginalNextEntryToRead, NewNextEntryToRead)) { platform_work_queue_entry Entry = Queue->Entries[OriginalNextEntryToRead]; Entry.Callback(Queue, Entry.Data); SDL_AtomicIncRef(&Queue->CompletionCount); } } else { WeShouldSleep = true; } return WeShouldSleep; }
/* 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; }
Task* taskmgr_submit(TaskManager *mgr, TaskParams params) { assert(params.callback != NULL); Task *task = calloc(1, sizeof(Task)); task->callback = params.callback; task->userdata_free_callback = params.userdata_free_callback; task->userdata = params.userdata; task->prio = params.prio; task->status = TASK_PENDING; if(!(task->mutex = SDL_CreateMutex())) { log_sdl_error(LOG_WARN, "SDL_CreateMutex"); goto fail; } if(!(task->cond = SDL_CreateCond())) { log_sdl_error(LOG_WARN, "SDL_CreateCond"); goto fail; } SDL_LockMutex(mgr->mutex); if(params.topmost) { alist_insert_at_priority_head(&mgr->queue, task, task->prio, task_prio_func); } else { alist_insert_at_priority_tail(&mgr->queue, task, task->prio, task_prio_func); } task->in_queue = true; SDL_AtomicIncRef(&mgr->numtasks); SDL_CondSignal(mgr->cond); SDL_UnlockMutex(mgr->mutex); return task; fail: task_free(task); return NULL; }
SDL_TimerID SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void *param) { SDL_TimerData *data = &SDL_timer_data; SDL_Timer *timer; SDL_TimerMap *entry; if (!data->active) { int status = 0; SDL_AtomicLock(&data->lock); if (!data->active) { status = SDL_TimerInit(); } SDL_AtomicUnlock(&data->lock); if (status < 0) { return 0; } } SDL_AtomicLock(&data->lock); 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; timer->canceled = SDL_FALSE; entry = (SDL_TimerMap *)SDL_malloc(sizeof(*entry)); if (!entry) { SDL_free(timer); SDL_OutOfMemory(); return 0; } entry->timer = timer; entry->timerID = timer->timerID; SDL_mutexP(data->timermap_lock); entry->next = data->timermap; data->timermap = entry; SDL_mutexV(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; }
void ref() { SDL_AtomicIncRef(&refcnt); }
SDL_TLSID SDL_TLSCreate() { static SDL_atomic_t SDL_tls_id; return SDL_AtomicIncRef(&SDL_tls_id)+1; }