//-------------------------------------------------------------------------------------------------- static void PopContext ( Parser_t* parserPtr ) //-------------------------------------------------------------------------------------------------- { // Don't do anything if a client handler has already stopped parsing. if (NotStopped(parserPtr)) { // Pop the top one and release it. le_sls_Link_t* linkPtr = le_sls_Pop(&parserPtr->contextStack); le_mem_Release(CONTAINER_OF(linkPtr, Context_t, link)); // Check the new context le_json_ContextType_t context = GetContext(parserPtr)->type; switch (context) { case LE_JSON_CONTEXT_DOC: // We've finished parsing the whole document. // Automatically stop parsing and report the document end to the client. StopParsing(parserPtr); Report(parserPtr, LE_JSON_DOC_END); break; case LE_JSON_CONTEXT_OBJECT: // We've finished parsing an object member. // Expect a comma separator or the end of the object next. parserPtr->next = EXPECT_COMMA_OR_OBJECT_END; break; case LE_JSON_CONTEXT_MEMBER: // We've finished parsing the value of an object member. // This is also the end of the member, so pop that context too. PopContext(parserPtr); break; case LE_JSON_CONTEXT_ARRAY: // We've finished parsing an array element value. // Expect a comma separator or the end of the array next. parserPtr->next = EXPECT_COMMA_OR_ARRAY_END; break; // These are all leaf contexts. That is, we should never find one of these // contexts after popping another one off the stack. case LE_JSON_CONTEXT_STRING: case LE_JSON_CONTEXT_NUMBER: case LE_JSON_CONTEXT_TRUE: case LE_JSON_CONTEXT_FALSE: case LE_JSON_CONTEXT_NULL: LE_FATAL("Unexpected context after pop: %s", le_json_GetContextName(context)); } } }
//-------------------------------------------------------------------------------------------------- void* le_mem_TryAlloc ( le_mem_PoolRef_t pool ///< [IN] The pool from which the object is to be allocated. ) { LE_ASSERT(pool != NULL); MemBlock_t* blockPtr = NULL; void* userPtr = NULL; Lock(); #ifndef LE_MEM_VALGRIND // Pop a link off the pool. le_sls_Link_t* blockLinkPtr = le_sls_Pop(&(pool->freeList)); if (blockLinkPtr != NULL) { // Get the block from the block link. blockPtr = CONTAINER_OF(blockLinkPtr, MemBlock_t, link); } #else blockPtr = malloc(pool->blockSize); if (blockPtr != NULL) { InitBlock(pool, blockPtr); } #endif if (blockPtr != NULL) { // Update the pool and the block. pool->numAllocations++; pool->numBlocksInUse++; if (pool->numBlocksInUse > pool->maxNumBlocksUsed) { pool->maxNumBlocksUsed = pool->numBlocksInUse; } blockPtr->refCount = 1; // Return the user object in the block. #ifdef USE_GUARD_BAND CheckGuardBands(blockPtr); userPtr = blockPtr->data + GUARD_BAND_SIZE; #else userPtr = blockPtr->data; #endif } Unlock(); return userPtr; }
//-------------------------------------------------------------------------------------------------- static void CleanupThread ( void* objPtr ///< Pointer to the Thread object. ) { ThreadObj_t* threadObjPtr = objPtr; // Call all destructors in the list. le_sls_Link_t* destructorLinkPtr = le_sls_Pop(&(threadObjPtr->destructorList)); while (destructorLinkPtr != NULL) { // Get the destructor object DestructorObj_t* destructorObjPtr = CONTAINER_OF(destructorLinkPtr, DestructorObj_t, link); // Call the destructor. if (destructorObjPtr->destructor != NULL) { destructorObjPtr->destructor(destructorObjPtr->context); } // Free the destructor object. le_mem_Release(destructorObjPtr); destructorLinkPtr = le_sls_Pop(&(threadObjPtr->destructorList)); } // Destruct the event loop. event_DestructThread(); // If this thread is NOT joinable, then immediately invalidate its safe reference and free // the thread object. Otherwise, wait until someone joins with it. if (! threadObjPtr->isJoinable) { Lock(); le_ref_DeleteRef(ThreadRefMap, threadObjPtr->safeRef); Unlock(); DeleteThread(threadObjPtr); } }
//-------------------------------------------------------------------------------------------------- static void MoveBlocks ( le_mem_PoolRef_t destPool, ///< [IN] The pool to move the blocks to. le_mem_PoolRef_t srcPool, ///< [IN] The pool to get the blocks from. size_t numBlocks ///< [IN] The maximum number of blocks to move. ) { #ifndef LE_MEM_VALGRIND // Get the first block to move. le_sls_Link_t* blockLinkPtr = le_sls_Pop(&(srcPool->freeList)); size_t i = 0; while (i < numBlocks) { if (blockLinkPtr == NULL) { LE_FATAL("Asked to move %zu blocks from pool '%s' to pool '%s', " "but only %zu were available.", numBlocks, srcPool->name, destPool->name, i); } // Add the block to the destination pool. le_sls_Stack(&(destPool->freeList), blockLinkPtr); // Update the blocks parent pool. MemBlock_t* blockPtr = CONTAINER_OF(blockLinkPtr, MemBlock_t, link); blockPtr->poolPtr = destPool; // Get the next block. blockLinkPtr = le_sls_Pop(&(srcPool->freeList)); i++; } #endif }
//-------------------------------------------------------------------------------------------------- static void ParserDestructor ( void* blockPtr ) //-------------------------------------------------------------------------------------------------- { Parser_t* parserPtr = blockPtr; StopParsing(parserPtr); le_sls_Link_t* linkPtr; while ((linkPtr = le_sls_Pop(&parserPtr->contextStack)) != NULL) { le_mem_Release(CONTAINER_OF(linkPtr, Context_t, link)); } le_thread_RemoveDestructor(parserPtr->threadDestructor); }
static le_result_t TestSinglyLinkLists(size_t maxListSize) { // Node definition. typedef struct { le_sls_Link_t link; uint32_t id; } idRecord_t; int i; le_sls_List_t list0, list1; printf("\n"); printf("*** Unit Test for le_singlyLinkedList module. ***\n"); // // Multiple list creation // // Initialize the lists list0 = LE_SLS_LIST_INIT; list1 = LE_SLS_LIST_INIT; printf("One singly linked list was successfully created.\n"); // // Attempt to query empty list // if ( (le_sls_Peek(&list0) != NULL) || (le_sls_Pop(&list0) != NULL) ) { printf("Query of empty list failed: %d", __LINE__); return LE_FAULT; } printf("Query of empty list correct.\n"); // // Node insertions // { idRecord_t* newNodePtr; le_sls_Link_t* prevLinkPtr; // Queue nodes to list0. for (i = 0; i < maxListSize; i++) { // Create the new node newNodePtr = (idRecord_t*)malloc(sizeof(idRecord_t)); newNodePtr->id = i; // Initialize the link. newNodePtr->link = LE_SLS_LINK_INIT; if (i < maxListSize/2) { // Insert the new node to the tail. le_sls_Queue(&list0, &(newNodePtr->link)); } else { // Insert to the tail using insert after. le_sls_AddAfter(&list0, prevLinkPtr, &(newNodePtr->link)); } prevLinkPtr = &(newNodePtr->link); } printf("%zu nodes were queued to the tail of list0.\n", maxListSize); // Stack nodes to list1. for (i = 0; i < maxListSize; i++) { // Create the new node newNodePtr = (idRecord_t*)malloc(sizeof(idRecord_t)); newNodePtr->id = i; // Initialize the link. newNodePtr->link = LE_SLS_LINK_INIT; // Insert the new node to the head. le_sls_Stack(&list1, &(newNodePtr->link)); } printf("%zu nodes were stacked to the head of list1.\n", maxListSize); } // // Check that all the nodes have been added properly // { idRecord_t* nodePtr; le_sls_Link_t* link0Ptr = le_sls_Peek(&list0); le_sls_Link_t* link1Ptr = le_sls_Peek(&list1); if ( (link0Ptr == NULL) || (link1Ptr == NULL) ) { printf("Link error: %d", __LINE__); return LE_FAULT; } i = 0; do { // Get the node from list 0 nodePtr = CONTAINER_OF(link0Ptr, idRecord_t, link); // Check the node. if ( nodePtr->id != i) { printf("Link error: %d", __LINE__); return LE_FAULT; } // Get the node from list 1 nodePtr = CONTAINER_OF(link1Ptr, idRecord_t, link); // Check the node. if ( nodePtr->id != maxListSize - i - 1) { printf("Link error: %d", __LINE__); return LE_FAULT; } // Move to the next node. link0Ptr = le_sls_PeekNext(&list0, link0Ptr); link1Ptr = le_sls_PeekNext(&list1, link1Ptr); i++; } while (link0Ptr != NULL); // Make sure everything is correct. if ( (i != maxListSize) || (link1Ptr != NULL) ) { printf("Link error: %d", __LINE__); return LE_FAULT; } } printf("Checked that all nodes added to the head and tails are all correct.\n"); // // Pop nodes. // { //pop half the list. for (i = 0; i < (maxListSize / 2); i++) { le_sls_Pop(&list0); } } printf("Popped half the nodes from the head of list0.\n"); // Check that the list is still in tact. { idRecord_t* nodePtr; // For list 0. le_sls_Link_t* linkPtr = le_sls_Peek(&list0); i = maxListSize/2; do { nodePtr = CONTAINER_OF(linkPtr, idRecord_t, link); if (nodePtr->id != i++) { printf("Link error: %d", __LINE__); return LE_FAULT; } linkPtr = le_sls_PeekNext(&list0, linkPtr); } while (linkPtr != NULL); // Check that the number of links left is correct. if (i != maxListSize) { printf("Wrong number of links: %d", __LINE__); return LE_FAULT; } } printf("Checked that all nodes were properly popped from the lists.\n"); // // Check for list corruption. // { le_sls_Link_t* linkPtr; if (le_sls_IsListCorrupted(&list0)) { printf("List0 is corrupt but shouldn't be: %d", __LINE__); return LE_FAULT; } // Access one of the links directly. This should corrupt the list. linkPtr = le_sls_Peek(&list0); linkPtr = le_sls_PeekNext(&list0, linkPtr); linkPtr->nextPtr = NULL; if (!le_sls_IsListCorrupted(&list0)) { printf("List0 is not corrupted but should be: %d", __LINE__); return LE_FAULT; } } printf("Checked lists for corruption.\n"); printf("*** Unit Test for le_singlyLinkedList module passed. ***\n"); printf("\n"); return LE_OK; }