bool vfs_zipfile_init(VFSNode *node, VFSNode *source) { VFSNode backup; memcpy(&backup, node, sizeof(VFSNode)); VFSZipFileData *zdata = calloc(1, sizeof(VFSZipFileData)); zdata->source = source; zdata->tls_id = SDL_TLSCreate(); node->data1 = zdata; node->funcs = &vfs_funcs_zipfile; if(!zdata->tls_id) { vfs_set_error("SDL_TLSCreate() failed: %s", SDL_GetError()); goto error; } if(!vfs_zipfile_get_tls(node, true)) { goto error; } vfs_zipfile_init_pathmap(node); return true; error: zdata->source = NULL; // don't decref it node->funcs->free(node); memcpy(node, &backup, sizeof(VFSNode)); return false; }
int main(int argc, char *argv[]) { int arg = 1; SDL_Thread *thread; /* Enable standard application logging */ SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); /* Load the SDL library */ if (SDL_Init(0) < 0) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError()); return (1); } while (argv[arg] && *argv[arg] == '-') { if (SDL_strcmp(argv[arg], "--prio") == 0) { testprio = 1; } ++arg; } tls = SDL_TLSCreate(); SDL_assert(tls); SDL_TLSSet(tls, "main thread", NULL); SDL_Log("Main thread data initially: %s\n", (const char *)SDL_TLSGet(tls)); alive = 1; thread = SDL_CreateThread(ThreadFunc, "One", "#1"); if (thread == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create thread: %s\n", SDL_GetError()); quit(1); } SDL_Delay(5 * 1000); SDL_Log("Waiting for thread #1\n"); alive = 0; SDL_WaitThread(thread, NULL); SDL_Log("Main thread data finally: %s\n", (const char *)SDL_TLSGet(tls)); alive = 1; signal(SIGTERM, killed); thread = SDL_CreateThread(ThreadFunc, "Two", "#2"); if (thread == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create thread: %s\n", SDL_GetError()); quit(1); } raise(SIGTERM); SDL_Quit(); /* Never reached */ return (0); /* Never reached */ }
/* Routine to get the thread-specific error variable */ SDL_error * SDL_GetErrBuf(void) { static SDL_SpinLock tls_lock; static SDL_bool tls_being_created; static SDL_TLSID tls_errbuf; static SDL_error SDL_global_errbuf; const SDL_error *ALLOCATION_IN_PROGRESS = (SDL_error *)-1; SDL_error *errbuf; /* tls_being_created is there simply to prevent recursion if SDL_TLSCreate() fails. It also means it's possible for another thread to also use SDL_global_errbuf, but that's very unlikely and hopefully won't cause issues. */ if (!tls_errbuf && !tls_being_created) { SDL_AtomicLock(&tls_lock); if (!tls_errbuf) { SDL_TLSID slot; tls_being_created = SDL_TRUE; slot = SDL_TLSCreate(); tls_being_created = SDL_FALSE; SDL_MemoryBarrierRelease(); tls_errbuf = slot; } SDL_AtomicUnlock(&tls_lock); } if (!tls_errbuf) { return &SDL_global_errbuf; } SDL_MemoryBarrierAcquire(); errbuf = (SDL_error *)SDL_TLSGet(tls_errbuf); if (errbuf == ALLOCATION_IN_PROGRESS) { return &SDL_global_errbuf; } if (!errbuf) { /* Mark that we're in the middle of allocating our buffer */ SDL_TLSSet(tls_errbuf, ALLOCATION_IN_PROGRESS, NULL); errbuf = (SDL_error *)SDL_malloc(sizeof(*errbuf)); if (!errbuf) { SDL_TLSSet(tls_errbuf, NULL, NULL); return &SDL_global_errbuf; } SDL_zerop(errbuf); SDL_TLSSet(tls_errbuf, errbuf, SDL_free); } return errbuf; }