VFSZipFileTLS* vfs_zipfile_get_tls(VFSNode *node, bool create) { VFSZipFileData *zdata = node->data1; VFSZipFileTLS *tls = SDL_TLSGet(zdata->tls_id); if(tls || !create) { return tls; } tls = calloc(1, sizeof(VFSZipFileTLS)); SDL_TLSSet(zdata->tls_id, tls, (void(*)(void*))vfs_zipfile_free_tls); zip_source_t *src = zip_source_function_create(vfs_zipfile_srcfunc, node, &tls->error); zip_t *zip = tls->zip = zip_open_from_source(src, ZIP_RDONLY, &tls->error); // FIXME: Taisei currently doesn't handle zip files without explicit directory entries correctly (file listing will not work) if(!zip) { char *r = vfs_node_repr(zdata->source, true); vfs_set_error("Failed to open zip archive '%s': %s", r, zip_error_strerror(&tls->error)); free(r); vfs_zipfile_free_tls(tls); SDL_TLSSet(zdata->tls_id, 0, NULL); zip_source_free(src); return NULL; } return tls; }
/* 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; }
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 */ }
int SDLCALL ThreadFunc(void *data) { SDL_TLSSet(tls, "baby thread", NULL); SDL_Log("Started thread %s: My thread id is %lu, thread data = %s\n", (char *) data, SDL_ThreadID(), (const char *)SDL_TLSGet(tls)); while (alive) { SDL_Log("Thread '%s' is alive!\n", (char *) data); SDL_Delay(1 * 1000); } SDL_Log("Thread '%s' exiting!\n", (char *) data); return (0); }
int SDLCALL ThreadFunc(void *data) { SDL_ThreadPriority prio = SDL_THREAD_PRIORITY_NORMAL; SDL_TLSSet(tls, "baby thread", NULL); SDL_Log("Started thread %s: My thread id is %lu, thread data = %s\n", (char *) data, SDL_ThreadID(), (const char *)SDL_TLSGet(tls)); while (alive) { SDL_Log("Thread '%s' is alive!\n", (char *) data); if (testprio) { SDL_Log("SDL_SetThreadPriority(%s):%d\n", getprioritystr(prio), SDL_SetThreadPriority(prio)); if (++prio > SDL_THREAD_PRIORITY_TIME_CRITICAL) prio = SDL_THREAD_PRIORITY_LOW; } SDL_Delay(1 * 1000); } SDL_Log("Thread '%s' exiting!\n", (char *) data); return (0); }
static void vfs_zipfile_free(VFSNode *node) { if(node) { VFSZipFileData *zdata = node->data1; if(zdata) { SDL_TLSID tls_id = ((VFSZipFileData*)node->data1)->tls_id; VFSZipFileTLS *tls = SDL_TLSGet(tls_id); if(tls) { vfs_zipfile_free_tls(tls); SDL_TLSSet(tls_id, NULL, NULL); } if(zdata->source) { vfs_decref(zdata->source); } ht_destroy(&zdata->pathmap); free(zdata); } } }