/** * Destroys thread local variables, sets exit event and dereferences * the thread handle. */ STATIC void THREAD_Cleanup(ThrData* thr) { /* invoke destructors for thread local variables */ int i, n = 1; for (i=0; i<MAX_DESTRUCTOR_ITERATIONS && n > 0; i++) { int k; n = 0; for (k=0; k<VECTOR_Size(&thr->cleanupList); k++) { ThrKey key = VECTOR_Get(&thr->cleanupList, k); void * value = TlsGetValue(key->index); if (value) { TlsSetValue(key->index, NULL); #ifdef _USE_EXCEPTION_HANDLING __try { #endif /* _USE_EXCEPTION_HANDLING */ key->clean(value); ASSERT(!TlsGetValue(key->index)); #ifdef _USE_EXCEPTION_HANDLING } __except(EXCEPTION_EXECUTE_HANDLER) { TlsSetValue(key->index,NULL); ASSMSG1("EXCEPTION %08lX in cleanup proc!", GetExceptionCode()); } #endif /* _USE_EXCEPTION_HANDLING */ n++; } } } ASSERT(i<MAX_DESTRUCTOR_ITERATIONS); /* Dereference ThrKey structures */ while ((n = VECTOR_Size(&thr->cleanupList)) > 0) { ThrKey key = VECTOR_Remove(&thr->cleanupList, n-1); if (InterlockedDecrement(&key->ref) == 0) { ASSERT(key->index == TLS_OUT_OF_INDEXES); MEM_Free(key); } } InterlockedDecrement(&WIN32_ThreadCount); VECTOR_Destroy(&thr->cleanupList); EVENT_Set(&thr->exitEvent); THREAD_Deref(thr); }
/* * XML_Handle parses well-formed XML stream returning the root tag context * on success, NULL on failure. The endTag callback provided by the root tag * handler can be used to deallocate the root tag can context without any * side effects. However, in order to extract any useful information from the * root tag context, each object providing root tag handler would normally * provide a function that would exract such information from the root tag * (and deallocate everything else). * * The last parameter is a context parameter passed to the root tag callback * as the first argument. The code calling XML_Handle or the XMLHandleRoot * callback directly must know that XMLHandleRoot expects as a context * parameter. Typically, this is not a problem, but the use of this parameter * is discouraged. The XML stream should be self-sufficient, i.e. it should * contain all the information necessary to completely parse it. The context * parameter exists primarily to support for legacy XML file formats that * require extra parsing information in addition to the information contained * in the XML stream itself. */ XMLTag * XML_Handle(File * f, Str tag, XMLHandleRoot root, void * ctx) { XMLTag * rootTag = NULL; XMLContext context; memset(&context, 0, sizeof(context)); context.rootTagName = tag; context.rootHandler = root; context.rootContext = ctx; if (VECTOR_Init(&context.stack, 0, NULL, XML_VectorFreeTagContext)) { XMLCallbacks cb; memset(&cb, 0, sizeof(cb)); cb.startElem = XML_HandleStartElem; cb.endElem = XML_HandleEndElem; cb.charData = XML_HandleCharData; if (!XML_ParseStream(f, &cb, &context)) { context.error = True; } if (!context.error) { rootTag = context.rootTag; } else if (context.rootTag) { if (context.rootTag->endTag) { context.rootTag->endTag(context.rootTag, NULL); } else { MEM_Free(context.rootTag); } } /* * VECTOR_Destroy would destroy the elements starting with the * first element. We must start with the last element, which is * a natural cleanup order for a stack. If parsing was successful, * the vector is already empty. However, if parsing failed, the * vector may be non-empty and the order in which we deallocate the * tags must be opposite to the order in which they were created. */ while (!VECTOR_IsEmpty(&context.stack)) { VECTOR_Remove(&context.stack, VECTOR_Size(&context.stack)-1); } VECTOR_Destroy(&context.stack); } return rootTag; }
/** * "End element" callback for XML_Handle. If this tag has been "skipped" by * XML_StartElemCB, simply decrements skipDepth. Otherwise, calls the client * callback to deallocate the tag context. */ STATIC void XML_HandleEndElem(void * ctx, Str tag) { XMLContext * context = (XMLContext*)ctx; UNREF(tag); if (context->error && context->skipDepth > 0) { context->skipDepth--; } else { int depth = VECTOR_Size(&context->stack); ASSERT(depth > 0); if (depth == 1 && !context->error) { XMLTagCtx * root; root = (XMLTagCtx*)VECTOR_Get(&context->stack,0); ASSERT(root && root->context == context); ASSERT(!context->rootTag); /* prevent XML_VectorFreeTagContext from deallocating the tag */ context->rootTag = root->tag; root->tag = NULL; } if (depth > 0) { VECTOR_Remove(&context->stack, depth-1); } } }