static void destroy(LuaThread *t) { (void)SDL_AtomicDecRef(&t->ref); if (SDL_AtomicGet(&t->ref) == 0) { lua_close(t->L); free(t); } }
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)); }
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; }
/* 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; }
void unref() { if(SDL_AtomicDecRef(&refcnt)) delete this; }
static int taskmgr_thread(void *arg) { TaskManager *mgr = arg; attr_unused SDL_threadID tid = SDL_ThreadID(); if(SDL_SetThreadPriority(mgr->thread_prio) < 0) { log_sdl_error(LOG_WARN, "SDL_SetThreadPriority"); } bool running; bool aborted; do { SDL_LockMutex(mgr->mutex); running = mgr->running; aborted = mgr->aborted; if(!running && !aborted) { SDL_CondWait(mgr->cond, mgr->mutex); } SDL_UnlockMutex(mgr->mutex); } while(!running && !aborted); while(running && !aborted) { SDL_LockMutex(mgr->mutex); Task *task = alist_pop(&mgr->queue); running = mgr->running; aborted = mgr->aborted; if(running && task == NULL && !aborted) { SDL_CondWait(mgr->cond, mgr->mutex); } SDL_UnlockMutex(mgr->mutex); if(task != NULL) { SDL_LockMutex(task->mutex); bool task_disowned = task->disowned; if(aborted && task->status == TASK_PENDING) { task->status = TASK_CANCELLED; } if(task->status == TASK_PENDING) { task->status = TASK_RUNNING; SDL_UnlockMutex(task->mutex); task->result = task->callback(task->userdata); SDL_LockMutex(task->mutex); assert(task->in_queue); task->in_queue = false; (void)SDL_AtomicDecRef(&mgr->numtasks); if((task_disowned = task->disowned)) { SDL_UnlockMutex(task->mutex); task_free(task); } else { task->status = TASK_FINISHED; SDL_CondBroadcast(task->cond); SDL_UnlockMutex(task->mutex); } } else if(task->status == TASK_CANCELLED) { assert(task->in_queue); task->in_queue = false; (void)SDL_AtomicDecRef(&mgr->numtasks); SDL_UnlockMutex(task->mutex); if(task_disowned) { task_free(task); } } else { UNREACHABLE; } } } return 0; }