Removing unnecessary additional directory level.
git-svn-id: https://pupnp.svn.sourceforge.net/svnroot/pupnp/trunk@29 119443c7-1b9e-41f8-b6fc-b9c35fce742c
This commit is contained in:
177
threadutil/src/FreeList.c
Normal file
177
threadutil/src/FreeList.c
Normal file
@@ -0,0 +1,177 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2000-2003 Intel Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
// * Neither name of Intel Corporation nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "FreeList.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Function: FreeListInit
|
||||
*
|
||||
* Description:
|
||||
* Initializes Free List. Must be called first.
|
||||
* And only once for FreeList.
|
||||
* Parameters:
|
||||
* free_list - must be valid, non null, pointer to a linked list.
|
||||
* size_t - size of elements to store in free list
|
||||
* maxFreeListSize - max size that the free list can grow to
|
||||
* before returning memory to O.S.
|
||||
* Returns:
|
||||
* 0 on success. Nonzero on failure.
|
||||
* Always returns 0.
|
||||
*****************************************************************************/
|
||||
int
|
||||
FreeListInit( FreeList * free_list,
|
||||
size_t elementSize,
|
||||
int maxFreeListLength )
|
||||
{
|
||||
assert( free_list != NULL );
|
||||
|
||||
if( free_list == NULL )
|
||||
return EINVAL;
|
||||
|
||||
free_list->element_size = elementSize;
|
||||
free_list->maxFreeListLength = maxFreeListLength;
|
||||
free_list->head = NULL;
|
||||
free_list->freeListLength = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: FreeListAlloc
|
||||
*
|
||||
* Description:
|
||||
* Allocates chunk of set size.
|
||||
* If a free item is available in the list, returnes the stored item.
|
||||
* Otherwise calls the O.S. to allocate memory.
|
||||
* Parameters:
|
||||
* free_list - must be valid, non null, pointer to a linked list.
|
||||
* Returns:
|
||||
* Non NULL on success. NULL on failure.
|
||||
*****************************************************************************/
|
||||
void *
|
||||
FreeListAlloc( FreeList * free_list )
|
||||
{
|
||||
FreeListNode *ret = NULL;
|
||||
|
||||
assert( free_list != NULL );
|
||||
|
||||
if( free_list == NULL )
|
||||
return NULL;
|
||||
|
||||
if( free_list->head ) {
|
||||
ret = free_list->head;
|
||||
free_list->head = free_list->head->next;
|
||||
free_list->freeListLength--;
|
||||
} else {
|
||||
ret = malloc( free_list->element_size );
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: FreeListFree
|
||||
*
|
||||
* Description:
|
||||
* Returns an item to the Free List.
|
||||
* If the free list is smaller than the max size than
|
||||
* adds the item to the free list.
|
||||
* Otherwise returns the item to the O.S.
|
||||
* Parameters:
|
||||
* free_list - must be valid, non null, pointer to a free list.
|
||||
* element - must be a pointer allocated by FreeListAlloc
|
||||
* Returns:
|
||||
* 0 on success. Nonzero on failure.
|
||||
* Always returns 0.
|
||||
*****************************************************************************/
|
||||
int
|
||||
FreeListFree( FreeList * free_list,
|
||||
void *element )
|
||||
{
|
||||
|
||||
FreeListNode *temp = NULL;
|
||||
|
||||
assert( free_list != NULL );
|
||||
|
||||
if( free_list == NULL )
|
||||
return EINVAL;
|
||||
|
||||
if( ( element != NULL ) &&
|
||||
( ( free_list->freeListLength + 1 ) <
|
||||
free_list->maxFreeListLength ) ) {
|
||||
free_list->freeListLength++;
|
||||
temp = ( FreeListNode * ) element;
|
||||
temp->next = free_list->head;
|
||||
free_list->head = temp;
|
||||
|
||||
} else {
|
||||
|
||||
free( element );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: FreeListDestroy
|
||||
*
|
||||
* Description:
|
||||
* Releases the resources stored with the free list.
|
||||
* Parameters:
|
||||
* free_list - must be valid, non null, pointer to a linked list.
|
||||
* Returns:
|
||||
* 0 on success. Nonzero on failure.
|
||||
* Always returns 0.
|
||||
*****************************************************************************/
|
||||
int
|
||||
FreeListDestroy( FreeList * free_list )
|
||||
{
|
||||
FreeListNode *temp = NULL;
|
||||
int i = 0;
|
||||
|
||||
assert( free_list != NULL );
|
||||
|
||||
if( free_list == NULL )
|
||||
return EINVAL;
|
||||
|
||||
while( free_list->head ) {
|
||||
i++;
|
||||
temp = free_list->head->next;
|
||||
free( free_list->head );
|
||||
free_list->head = temp;
|
||||
}
|
||||
|
||||
free_list->freeListLength = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
533
threadutil/src/LinkedList.c
Normal file
533
threadutil/src/LinkedList.c
Normal file
@@ -0,0 +1,533 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2000-2003 Intel Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
// * Neither name of Intel Corporation nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "LinkedList.h"
|
||||
#ifdef __FreeBSD__
|
||||
#include <stdlib.h>
|
||||
#else
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#include <assert.h>
|
||||
|
||||
static int
|
||||
freeListNode( ListNode * node,
|
||||
LinkedList * list )
|
||||
{
|
||||
assert( list != NULL );
|
||||
|
||||
return FreeListFree( &list->freeNodeList, node );
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: CreateListNode
|
||||
*
|
||||
* Description:
|
||||
* Creates a list node. Dynamically.
|
||||
*
|
||||
* Parameters:
|
||||
* void * item - the item to store
|
||||
* Returns:
|
||||
* The new node, NULL on failure.
|
||||
*****************************************************************************/
|
||||
static ListNode *
|
||||
CreateListNode( void *item,
|
||||
LinkedList * list )
|
||||
{
|
||||
|
||||
ListNode *temp = NULL;
|
||||
|
||||
assert( list != NULL );
|
||||
|
||||
temp = ( ListNode * ) FreeListAlloc( &list->freeNodeList );
|
||||
if( temp ) {
|
||||
temp->prev = NULL;
|
||||
temp->next = NULL;
|
||||
temp->item = item;
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: ListInit
|
||||
*
|
||||
* Description:
|
||||
* Initializes LinkedList. Must be called first.
|
||||
* And only once for List.
|
||||
* Parameters:
|
||||
* list - must be valid, non null, pointer to a linked list.
|
||||
* cmp_func - function used to compare items. (May be NULL)
|
||||
* free_func - function used to free items. (May be NULL)
|
||||
* Returns:
|
||||
* 0 on success, EOUTOFMEM on failure.
|
||||
*****************************************************************************/
|
||||
int
|
||||
ListInit( LinkedList * list,
|
||||
cmp_routine cmp_func,
|
||||
free_function free_func )
|
||||
{
|
||||
|
||||
int retCode = 0;
|
||||
|
||||
assert( list != NULL );
|
||||
|
||||
if( list == NULL )
|
||||
return EINVAL;
|
||||
|
||||
list->size = 0;
|
||||
list->cmp_func = cmp_func;
|
||||
list->free_func = free_func;
|
||||
|
||||
retCode =
|
||||
FreeListInit( &list->freeNodeList, sizeof( ListNode ),
|
||||
FREELISTSIZE );
|
||||
|
||||
assert( retCode == 0 );
|
||||
|
||||
list->head.item = NULL;
|
||||
list->head.next = &list->tail;
|
||||
list->head.prev = NULL;
|
||||
|
||||
list->tail.item = NULL;
|
||||
list->tail.prev = &list->head;
|
||||
list->tail.next = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: ListAddHead
|
||||
*
|
||||
* Description:
|
||||
* Adds a node to the head of the list.
|
||||
* Node gets immediately after list.head.
|
||||
* Parameters:
|
||||
* LinkedList *list - must be valid, non null, pointer to a linked list.
|
||||
* void * item - item to be added
|
||||
* Returns:
|
||||
* The pointer to the ListNode on success, NULL on failure.
|
||||
* Precondition:
|
||||
* The list has been initialized.
|
||||
*****************************************************************************/
|
||||
ListNode *
|
||||
ListAddHead( LinkedList * list,
|
||||
void *item )
|
||||
{
|
||||
assert( list != NULL );
|
||||
|
||||
if( list == NULL )
|
||||
return NULL;
|
||||
|
||||
return ListAddAfter( list, item, &list->head );
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: ListAddTail
|
||||
*
|
||||
* Description:
|
||||
* Adds a node to the tail of the list.
|
||||
* Node gets added immediately before list.tail.
|
||||
* Parameters:
|
||||
* LinkedList *list - must be valid, non null, pointer to a linked list.
|
||||
* void * item - item to be added
|
||||
* Returns:
|
||||
* The pointer to the ListNode on success, NULL on failure.
|
||||
* Precondition:
|
||||
* The list has been initialized.
|
||||
*****************************************************************************/
|
||||
ListNode *
|
||||
ListAddTail( LinkedList * list,
|
||||
void *item )
|
||||
{
|
||||
assert( list != NULL );
|
||||
|
||||
if( list == NULL )
|
||||
return NULL;
|
||||
|
||||
return ListAddBefore( list, item, &list->tail );
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: ListAddAfter
|
||||
*
|
||||
* Description:
|
||||
* Adds a node after the specified node.
|
||||
* Node gets added immediately after bnode.
|
||||
* Parameters:
|
||||
* LinkedList *list - must be valid, non null, pointer to a linked list.
|
||||
* void * item - item to be added
|
||||
* ListNode * bnode - node to add after
|
||||
* Returns:
|
||||
* The pointer to the ListNode on success, NULL on failure.
|
||||
* Precondition:
|
||||
* The list has been initialized.
|
||||
*****************************************************************************/
|
||||
ListNode *
|
||||
ListAddAfter( LinkedList * list,
|
||||
void *item,
|
||||
ListNode * bnode )
|
||||
{
|
||||
ListNode *newNode = NULL;
|
||||
|
||||
assert( list != NULL );
|
||||
|
||||
if( ( list == NULL ) || ( bnode == NULL ) )
|
||||
return NULL;
|
||||
|
||||
newNode = CreateListNode( item, list );
|
||||
if( newNode ) {
|
||||
ListNode *temp = bnode->next;
|
||||
|
||||
bnode->next = newNode;
|
||||
newNode->prev = bnode;
|
||||
newNode->next = temp;
|
||||
temp->prev = newNode;
|
||||
list->size++;
|
||||
return newNode;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: ListAddBefore
|
||||
*
|
||||
* Description:
|
||||
* Adds a node before the specified node.
|
||||
* Node gets added immediately before anode.
|
||||
* Parameters:
|
||||
* LinkedList *list - must be valid, non null, pointer to a linked list.
|
||||
* ListNode * anode - node to add the in front of.
|
||||
* void * item - item to be added
|
||||
* Returns:
|
||||
* The pointer to the ListNode on success, NULL on failure.
|
||||
* Precondition:
|
||||
* The list has been initialized.
|
||||
*****************************************************************************/
|
||||
ListNode *
|
||||
ListAddBefore( LinkedList * list,
|
||||
void *item,
|
||||
ListNode * anode )
|
||||
{
|
||||
ListNode *newNode = NULL;
|
||||
|
||||
assert( list != NULL );
|
||||
|
||||
if( ( list == NULL ) || ( anode == NULL ) )
|
||||
return NULL;
|
||||
|
||||
newNode = CreateListNode( item, list );
|
||||
|
||||
if( newNode ) {
|
||||
ListNode *temp = anode->prev;
|
||||
|
||||
anode->prev = newNode;
|
||||
newNode->next = anode;
|
||||
newNode->prev = temp;
|
||||
temp->next = newNode;
|
||||
list->size++;
|
||||
return newNode;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: ListDelNode
|
||||
*
|
||||
* Description:
|
||||
* Removes a node from the list
|
||||
* The memory for the node is freed but the
|
||||
* the memory for the items are not.
|
||||
* Parameters:
|
||||
* LinkedList *list - must be valid, non null, pointer to a linked list.
|
||||
* ListNode *dnode - done to delete.
|
||||
* Returns:
|
||||
* The pointer to the item stored in node on success, NULL on failure.
|
||||
* Precondition:
|
||||
* The list has been initialized.
|
||||
*****************************************************************************/
|
||||
void *
|
||||
ListDelNode( LinkedList * list,
|
||||
ListNode * dnode,
|
||||
int freeItem )
|
||||
{
|
||||
void *temp;
|
||||
|
||||
assert( list != NULL );
|
||||
assert( dnode != &list->head );
|
||||
assert( dnode != &list->tail );
|
||||
|
||||
if( ( list == NULL ) ||
|
||||
( dnode == &list->head ) ||
|
||||
( dnode == &list->tail ) || ( dnode == NULL ) ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
temp = dnode->item;
|
||||
dnode->prev->next = dnode->next;
|
||||
dnode->next->prev = dnode->prev;
|
||||
|
||||
freeListNode( dnode, list );
|
||||
list->size--;
|
||||
|
||||
if( freeItem && list->free_func ) {
|
||||
list->free_func( temp );
|
||||
temp = NULL;
|
||||
}
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: ListDestroy
|
||||
*
|
||||
* Description:
|
||||
* Removes all memory associated with list nodes.
|
||||
* Does not free LinkedList *list.
|
||||
* Items stored in the list are not freed, only nodes are.
|
||||
* Parameters:
|
||||
* LinkedList *list - must be valid, non null, pointer to a linked list.
|
||||
* Returns:
|
||||
* 0 on success. Nonzero on failure.
|
||||
* Always returns 0.
|
||||
* Precondition:
|
||||
* The list has been initialized.
|
||||
*****************************************************************************/
|
||||
int
|
||||
ListDestroy( LinkedList * list,
|
||||
int freeItem )
|
||||
{
|
||||
ListNode *dnode = NULL;
|
||||
ListNode *temp = NULL;
|
||||
|
||||
if( list == NULL )
|
||||
return EINVAL;
|
||||
|
||||
for( dnode = list->head.next; dnode != &list->tail; ) {
|
||||
temp = dnode->next;
|
||||
ListDelNode( list, dnode, freeItem );
|
||||
dnode = temp;
|
||||
}
|
||||
|
||||
list->size = 0;
|
||||
FreeListDestroy( &list->freeNodeList );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: ListHead
|
||||
*
|
||||
* Description:
|
||||
* Returns the head of the list.
|
||||
*
|
||||
* Parameters:
|
||||
* LinkedList *list - must be valid, non null, pointer to a linked list.
|
||||
*
|
||||
* Returns:
|
||||
* The head of the list. NULL if list is empty.
|
||||
* Precondition:
|
||||
* The list has been initialized.
|
||||
*****************************************************************************/
|
||||
ListNode *
|
||||
ListHead( LinkedList * list )
|
||||
{
|
||||
assert( list != NULL );
|
||||
|
||||
if( list == NULL )
|
||||
return NULL;
|
||||
|
||||
if( list->size == 0 )
|
||||
return NULL;
|
||||
else
|
||||
return list->head.next;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: ListTail
|
||||
*
|
||||
* Description:
|
||||
* Returns the tail of the list.
|
||||
*
|
||||
* Parameters:
|
||||
* LinkedList *list - must be valid, non null, pointer to a linked list.
|
||||
*
|
||||
* Returns:
|
||||
* The tail of the list. NULL if list is empty.
|
||||
* Precondition:
|
||||
* The list has been initialized.
|
||||
*****************************************************************************/
|
||||
ListNode *
|
||||
ListTail( LinkedList * list )
|
||||
{
|
||||
assert( list != NULL );
|
||||
|
||||
if( list == NULL )
|
||||
return NULL;
|
||||
|
||||
if( list->size == 0 )
|
||||
return NULL;
|
||||
else
|
||||
return list->tail.prev;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: ListNext
|
||||
*
|
||||
* Description:
|
||||
* Returns the next item in the list.
|
||||
*
|
||||
* Parameters:
|
||||
* LinkedList *list - must be valid, non null, pointer to a linked list.
|
||||
*
|
||||
* Returns:
|
||||
* The next item in the list. NULL if there are no more items in list.
|
||||
* Precondition:
|
||||
* The list has been initialized.
|
||||
*****************************************************************************/
|
||||
ListNode *
|
||||
ListNext( LinkedList * list,
|
||||
ListNode * node )
|
||||
{
|
||||
assert( list != NULL );
|
||||
assert( node != NULL );
|
||||
|
||||
if( ( list == NULL ) || ( node == NULL ) )
|
||||
return NULL;
|
||||
|
||||
if( node->next == &list->tail )
|
||||
return NULL;
|
||||
else
|
||||
return node->next;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: ListPrev
|
||||
*
|
||||
* Description:
|
||||
* Returns the previous item in the list.
|
||||
*
|
||||
* Parameters:
|
||||
* LinkedList *list - must be valid, non null, pointer to a linked list.
|
||||
*
|
||||
* Returns:
|
||||
* The previous item in the list. NULL if there are no more items in list.
|
||||
* Precondition:
|
||||
* The list has been initialized.
|
||||
*****************************************************************************/
|
||||
ListNode *
|
||||
ListPrev( LinkedList * list,
|
||||
ListNode * node )
|
||||
{
|
||||
assert( list != NULL );
|
||||
assert( node != NULL );
|
||||
|
||||
if( ( list == NULL ) || ( node == NULL ) )
|
||||
return NULL;
|
||||
|
||||
if( node->prev == &list->head )
|
||||
return NULL;
|
||||
else
|
||||
return node->prev;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: ListFind
|
||||
*
|
||||
* Description:
|
||||
* Finds the specified item in the list.
|
||||
* Uses the compare function specified in ListInit. If compare function
|
||||
* is NULL then compares items as pointers.
|
||||
* Parameters:
|
||||
* LinkedList *list - must be valid, non null, pointer to a linked list.
|
||||
* ListNode *start - the node to start from, NULL if to start from
|
||||
* beginning.
|
||||
* void * item - the item to search for.
|
||||
* Returns:
|
||||
* The node containing the item. NULL if no node contains the item.
|
||||
* Precondition:
|
||||
* The list has been initialized.
|
||||
*****************************************************************************/
|
||||
ListNode *
|
||||
ListFind( LinkedList * list,
|
||||
ListNode * start,
|
||||
void *item )
|
||||
{
|
||||
|
||||
ListNode *finger = NULL;
|
||||
|
||||
if( list == NULL )
|
||||
return NULL;
|
||||
|
||||
if( start == NULL )
|
||||
start = &list->head;
|
||||
|
||||
assert( start );
|
||||
|
||||
finger = start->next;
|
||||
|
||||
assert( finger );
|
||||
|
||||
while( finger != &list->tail ) {
|
||||
if( list->cmp_func ) {
|
||||
if( list->cmp_func( item, finger->item ) )
|
||||
return finger;
|
||||
} else {
|
||||
if( item == finger->item )
|
||||
return finger;
|
||||
}
|
||||
finger = finger->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: ListSize
|
||||
*
|
||||
* Description:
|
||||
* Returns the size of the list.
|
||||
* Parameters:
|
||||
* LinkedList *list - must be valid, non null, pointer to a linked list.
|
||||
|
||||
* Returns:
|
||||
* The number of items in the list.
|
||||
* Precondition:
|
||||
* The list has been initialized.
|
||||
*****************************************************************************/
|
||||
int
|
||||
ListSize( LinkedList * list )
|
||||
{
|
||||
assert( list != NULL );
|
||||
|
||||
if( list == NULL )
|
||||
return EINVAL;
|
||||
|
||||
return list->size;
|
||||
}
|
||||
1545
threadutil/src/ThreadPool.c
Normal file
1545
threadutil/src/ThreadPool.c
Normal file
File diff suppressed because it is too large
Load Diff
519
threadutil/src/TimerThread.c
Normal file
519
threadutil/src/TimerThread.c
Normal file
@@ -0,0 +1,519 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2000-2003 Intel Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
// * Neither name of Intel Corporation nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "TimerThread.h"
|
||||
#include <assert.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Function: FreeTimerEvent
|
||||
*
|
||||
* Description:
|
||||
* Deallocates a dynamically allocated TimerEvent.
|
||||
* Parameters:
|
||||
* TimerEvent *event - must be allocated with CreateTimerEvent
|
||||
*****************************************************************************/
|
||||
static void
|
||||
FreeTimerEvent( TimerThread * timer,
|
||||
TimerEvent * event )
|
||||
{
|
||||
|
||||
assert( timer != NULL );
|
||||
|
||||
FreeListFree( &timer->freeEvents, event );
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: TimerThreadWorker
|
||||
*
|
||||
* Description:
|
||||
* Implements timer thread.
|
||||
* Waits for next event to occur and schedules
|
||||
* associated job into threadpool.
|
||||
* Internal Only.
|
||||
* Parameters:
|
||||
* void * arg -> is cast to TimerThread *
|
||||
*****************************************************************************/
|
||||
static void *
|
||||
TimerThreadWorker( void *arg )
|
||||
{
|
||||
TimerThread *timer = ( TimerThread * ) arg;
|
||||
ListNode *head = NULL;
|
||||
|
||||
TimerEvent *nextEvent = NULL;
|
||||
|
||||
time_t currentTime = 0;
|
||||
time_t nextEventTime = 0;
|
||||
struct timespec timeToWait;
|
||||
|
||||
int tempId;
|
||||
|
||||
assert( timer != NULL );
|
||||
|
||||
ithread_mutex_lock( &timer->mutex );
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
|
||||
//mutex should always be locked at top of loop
|
||||
|
||||
//Check for shutdown
|
||||
|
||||
if( timer->shutdown )
|
||||
{
|
||||
|
||||
timer->shutdown = 0;
|
||||
ithread_cond_signal( &timer->condition );
|
||||
ithread_mutex_unlock( &timer->mutex );
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
nextEvent = NULL;
|
||||
|
||||
//Get the next event if possible
|
||||
if( timer->eventQ.size > 0 )
|
||||
{
|
||||
head = ListHead( &timer->eventQ );
|
||||
|
||||
nextEvent = ( TimerEvent * ) head->item;
|
||||
nextEventTime = nextEvent->eventTime;
|
||||
}
|
||||
|
||||
currentTime = time( NULL );
|
||||
|
||||
//If time has elapsed, schedule job
|
||||
|
||||
if( ( nextEvent != NULL ) && ( currentTime >= nextEventTime ) )
|
||||
{
|
||||
|
||||
if( nextEvent->persistent ) {
|
||||
|
||||
ThreadPoolAddPersistent( timer->tp, &nextEvent->job,
|
||||
&tempId );
|
||||
} else {
|
||||
|
||||
ThreadPoolAdd( timer->tp, &nextEvent->job, &tempId );
|
||||
}
|
||||
|
||||
ListDelNode( &timer->eventQ, head, 0 );
|
||||
FreeTimerEvent( timer, nextEvent );
|
||||
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
if( nextEvent != NULL ) {
|
||||
timeToWait.tv_nsec = 0;
|
||||
timeToWait.tv_sec = nextEvent->eventTime;
|
||||
|
||||
ithread_cond_timedwait( &timer->condition, &timer->mutex,
|
||||
&timeToWait );
|
||||
|
||||
} else {
|
||||
ithread_cond_wait( &timer->condition, &timer->mutex );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: CalculateEventTime
|
||||
*
|
||||
* Description:
|
||||
* Calculates the appropriate timeout in absolute seconds since
|
||||
* Jan 1, 1970
|
||||
* Internal Only.
|
||||
* Parameters:
|
||||
* time_t *timeout - timeout
|
||||
*
|
||||
*****************************************************************************/
|
||||
static int
|
||||
CalculateEventTime( time_t * timeout,
|
||||
TimeoutType type )
|
||||
{
|
||||
time_t now;
|
||||
|
||||
assert( timeout != NULL );
|
||||
|
||||
if( type == ABS_SEC )
|
||||
return 0;
|
||||
else if( type == REL_SEC ) {
|
||||
time( &now );
|
||||
( *timeout ) += now;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: CreateTimerEvent
|
||||
*
|
||||
* Description:
|
||||
* Creates a Timer Event. (Dynamically allocated)
|
||||
* Internal to timer thread.
|
||||
* Parameters:
|
||||
* func - thread function to run.
|
||||
* arg - argument to function.
|
||||
* priority - priority of job.
|
||||
* eventTime - the absoule time of the event
|
||||
* in seconds from Jan, 1970
|
||||
* id - id of job
|
||||
*
|
||||
* Returns:
|
||||
* TimerEvent * on success, NULL on failure.
|
||||
****************************************************************************/
|
||||
static TimerEvent *
|
||||
CreateTimerEvent( TimerThread * timer,
|
||||
ThreadPoolJob * job,
|
||||
Duration persistent,
|
||||
time_t eventTime,
|
||||
int id )
|
||||
{
|
||||
TimerEvent *temp = NULL;
|
||||
|
||||
assert( timer != NULL );
|
||||
assert( job != NULL );
|
||||
|
||||
temp = ( TimerEvent * ) FreeListAlloc( &timer->freeEvents );
|
||||
if( temp == NULL )
|
||||
return temp;
|
||||
temp->job = ( *job );
|
||||
temp->persistent = persistent;
|
||||
temp->eventTime = eventTime;
|
||||
temp->id = id;
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Function: TimerThreadInit
|
||||
*
|
||||
* Description:
|
||||
* Initializes and starts timer thread.
|
||||
*
|
||||
* Parameters:
|
||||
* timer - valid timer thread pointer.
|
||||
* tp - valid thread pool to use. Must be
|
||||
* started. Must be valid for lifetime
|
||||
* of timer. Timer must be shutdown
|
||||
* BEFORE thread pool.
|
||||
* Return:
|
||||
* 0 on success, nonzero on failure
|
||||
* Returns error from ThreadPoolAddPersistent if failure.
|
||||
************************************************************************/
|
||||
int
|
||||
TimerThreadInit( TimerThread * timer,
|
||||
ThreadPool * tp )
|
||||
{
|
||||
|
||||
int rc = 0;
|
||||
|
||||
ThreadPoolJob timerThreadWorker;
|
||||
|
||||
assert( timer != NULL );
|
||||
assert( tp != NULL );
|
||||
|
||||
if( ( timer == NULL ) || ( tp == NULL ) ) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
rc += ithread_mutex_init( &timer->mutex, NULL );
|
||||
|
||||
assert( rc == 0 );
|
||||
|
||||
rc += ithread_mutex_lock( &timer->mutex );
|
||||
assert( rc == 0 );
|
||||
|
||||
rc += ithread_cond_init( &timer->condition, NULL );
|
||||
assert( rc == 0 );
|
||||
|
||||
rc += FreeListInit( &timer->freeEvents, sizeof( TimerEvent ), 100 );
|
||||
assert( rc == 0 );
|
||||
|
||||
timer->shutdown = 0;
|
||||
timer->tp = tp;
|
||||
timer->lastEventId = 0;
|
||||
rc += ListInit( &timer->eventQ, NULL, NULL );
|
||||
|
||||
assert( rc == 0 );
|
||||
|
||||
if( rc != 0 ) {
|
||||
rc = EAGAIN;
|
||||
} else {
|
||||
|
||||
TPJobInit( &timerThreadWorker, TimerThreadWorker, timer );
|
||||
TPJobSetPriority( &timerThreadWorker, HIGH_PRIORITY );
|
||||
|
||||
rc = ThreadPoolAddPersistent( tp, &timerThreadWorker, NULL );
|
||||
}
|
||||
|
||||
ithread_mutex_unlock( &timer->mutex );
|
||||
|
||||
if( rc != 0 ) {
|
||||
ithread_cond_destroy( &timer->condition );
|
||||
ithread_mutex_destroy( &timer->mutex );
|
||||
FreeListDestroy( &timer->freeEvents );
|
||||
ListDestroy( &timer->eventQ, 0 );
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Function: TimerThreadSchedule
|
||||
*
|
||||
* Description:
|
||||
* Schedules an event to run at a specified time.
|
||||
*
|
||||
* Parameters:
|
||||
* timer - valid timer thread pointer.
|
||||
* time_t - time of event.
|
||||
* either in absolute seconds,
|
||||
* or relative seconds in the future.
|
||||
* timeoutType - either ABS_SEC, or REL_SEC.
|
||||
* if REL_SEC, then the event
|
||||
* will be scheduled at the
|
||||
* current time + REL_SEC.
|
||||
*
|
||||
* func - function to schedule
|
||||
* arg - argument to function
|
||||
* priority - priority of job.
|
||||
* id - id of timer event. (out)
|
||||
* Return:
|
||||
* 0 on success, nonzero on failure
|
||||
* EOUTOFMEM if not enough memory to schedule job
|
||||
************************************************************************/
|
||||
int
|
||||
TimerThreadSchedule( TimerThread * timer,
|
||||
time_t timeout,
|
||||
TimeoutType type,
|
||||
ThreadPoolJob * job,
|
||||
Duration duration,
|
||||
int *id )
|
||||
{
|
||||
|
||||
int rc = EOUTOFMEM;
|
||||
int found = 0;
|
||||
int tempId = 0;
|
||||
|
||||
ListNode *tempNode = NULL;
|
||||
TimerEvent *temp = NULL;
|
||||
TimerEvent *newEvent = NULL;
|
||||
|
||||
assert( timer != NULL );
|
||||
assert( job != NULL );
|
||||
|
||||
if( ( timer == NULL ) || ( job == NULL ) ) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
CalculateEventTime( &timeout, type );
|
||||
ithread_mutex_lock( &timer->mutex );
|
||||
|
||||
if( id == NULL )
|
||||
id = &tempId;
|
||||
|
||||
( *id ) = INVALID_EVENT_ID;
|
||||
|
||||
newEvent = CreateTimerEvent( timer, job, duration, timeout,
|
||||
timer->lastEventId );
|
||||
|
||||
if( newEvent == NULL ) {
|
||||
ithread_mutex_unlock( &timer->mutex );
|
||||
return rc;
|
||||
}
|
||||
|
||||
tempNode = ListHead( &timer->eventQ );
|
||||
//add job to Q
|
||||
//Q is ordered by eventTime
|
||||
//with the head of the Q being the next event
|
||||
|
||||
while( tempNode != NULL ) {
|
||||
temp = ( TimerEvent * ) tempNode->item;
|
||||
if( temp->eventTime >= timeout )
|
||||
{
|
||||
|
||||
if( ListAddBefore( &timer->eventQ, newEvent, tempNode ) !=
|
||||
NULL )
|
||||
rc = 0;
|
||||
found = 1;
|
||||
break;
|
||||
|
||||
}
|
||||
tempNode = ListNext( &timer->eventQ, tempNode );
|
||||
}
|
||||
|
||||
//add to the end of Q
|
||||
if( !found ) {
|
||||
|
||||
if( ListAddTail( &timer->eventQ, newEvent ) != NULL )
|
||||
rc = 0;
|
||||
|
||||
}
|
||||
//signal change in Q
|
||||
if( rc == 0 ) {
|
||||
|
||||
ithread_cond_signal( &timer->condition );
|
||||
} else {
|
||||
FreeTimerEvent( timer, newEvent );
|
||||
}
|
||||
( *id ) = timer->lastEventId++;
|
||||
ithread_mutex_unlock( &timer->mutex );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Function: TimerThreadRemove
|
||||
*
|
||||
* Description:
|
||||
* Removes an event from the timer Q.
|
||||
* Events can only be removed
|
||||
* before they have been placed in the
|
||||
* thread pool.
|
||||
*
|
||||
* Parameters:
|
||||
* timer - valid timer thread pointer.
|
||||
* id - id of event to remove.
|
||||
* out - space for returned job (Can be NULL)
|
||||
* Return:
|
||||
* 0 on success.
|
||||
* INVALID_EVENT_ID on error.
|
||||
*
|
||||
************************************************************************/
|
||||
int
|
||||
TimerThreadRemove( TimerThread * timer,
|
||||
int id,
|
||||
ThreadPoolJob * out )
|
||||
{
|
||||
int rc = INVALID_EVENT_ID;
|
||||
ListNode *tempNode = NULL;
|
||||
TimerEvent *temp = NULL;
|
||||
|
||||
assert( timer != NULL );
|
||||
|
||||
if( timer == NULL ) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
ithread_mutex_lock( &timer->mutex );
|
||||
|
||||
tempNode = ListHead( &timer->eventQ );
|
||||
|
||||
while( tempNode != NULL ) {
|
||||
temp = ( TimerEvent * ) tempNode->item;
|
||||
if( temp->id == id )
|
||||
{
|
||||
|
||||
ListDelNode( &timer->eventQ, tempNode, 0 );
|
||||
if( out != NULL )
|
||||
( *out ) = temp->job;
|
||||
FreeTimerEvent( timer, temp );
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
tempNode = ListNext( &timer->eventQ, tempNode );
|
||||
}
|
||||
|
||||
ithread_mutex_unlock( &timer->mutex );
|
||||
return rc;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Function: TimerThreadShutdown
|
||||
*
|
||||
* Description:
|
||||
* Shutdown the timer thread
|
||||
* Events scheduled in the future will NOT be run.
|
||||
* Timer thread should be shutdown BEFORE it's associated
|
||||
* thread pool.
|
||||
* Returns:
|
||||
* returns 0 if succesfull,
|
||||
* nonzero otherwise.
|
||||
* Always returns 0.
|
||||
***********************************************************************/
|
||||
int
|
||||
TimerThreadShutdown( TimerThread * timer )
|
||||
{
|
||||
ListNode *tempNode2 = NULL;
|
||||
ListNode *tempNode = NULL;
|
||||
|
||||
assert( timer != NULL );
|
||||
|
||||
if( timer == NULL ) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
ithread_mutex_lock( &timer->mutex );
|
||||
|
||||
timer->shutdown = 1;
|
||||
tempNode = ListHead( &timer->eventQ );
|
||||
|
||||
//Delete nodes in Q
|
||||
//call registered free function
|
||||
//on argument
|
||||
while( tempNode != NULL ) {
|
||||
TimerEvent *temp = ( TimerEvent * ) tempNode->item;
|
||||
|
||||
tempNode2 = ListNext( &timer->eventQ, tempNode );
|
||||
ListDelNode( &timer->eventQ, tempNode, 0 );
|
||||
if( temp->job.free_func ) {
|
||||
temp->job.free_func( temp->job.arg );
|
||||
}
|
||||
FreeTimerEvent( timer, temp );
|
||||
tempNode = tempNode2;
|
||||
}
|
||||
|
||||
ListDestroy( &timer->eventQ, 0 );
|
||||
FreeListDestroy( &timer->freeEvents );
|
||||
|
||||
ithread_cond_broadcast( &timer->condition );
|
||||
|
||||
while( timer->shutdown ) //wait for timer thread to shutdown
|
||||
{
|
||||
ithread_cond_wait( &timer->condition, &timer->mutex );
|
||||
}
|
||||
|
||||
ithread_mutex_unlock( &timer->mutex );
|
||||
|
||||
//destroy condition
|
||||
while( ithread_cond_destroy( &timer->condition ) != 0 ) {
|
||||
}
|
||||
|
||||
//destroy mutex
|
||||
while( ithread_mutex_destroy( &timer->mutex ) != 0 ) {
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
152
threadutil/src/iasnprintf.c
Normal file
152
threadutil/src/iasnprintf.c
Normal file
@@ -0,0 +1,152 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2000-2003 Intel Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
// * Neither name of Intel Corporation nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
#ifdef __FreeBSD__
|
||||
#include <stdlib.h>
|
||||
#else
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include "iasnprintf.h"
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#define vsnprintf _vsnprintf
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Allocates enough memory for the
|
||||
* Formatted string, up to max
|
||||
* specified.
|
||||
* With max set to -1, it allocates as
|
||||
* much size as needed.
|
||||
* Memory must be freed using free.
|
||||
*/
|
||||
|
||||
int
|
||||
iasnprintf( char **ret,
|
||||
int incr,
|
||||
int max,
|
||||
const char *fmt,
|
||||
... )
|
||||
{
|
||||
int size = incr;
|
||||
int retc = 0;
|
||||
va_list ap;
|
||||
char *temp = NULL;
|
||||
|
||||
assert( ret );
|
||||
assert( fmt );
|
||||
( *ret ) = ( char * )malloc( incr );
|
||||
|
||||
if( ( *ret ) == NULL ) return -1;
|
||||
|
||||
while( 1 ) {
|
||||
va_start( ap, fmt );
|
||||
retc = vsnprintf( ( *ret ), size, fmt, ap );
|
||||
va_end( ap );
|
||||
|
||||
if( retc < 0 ) {
|
||||
//size not big enough
|
||||
//and vsnprintf does NOT return the
|
||||
//necessary number of bytes
|
||||
if( ( max != -1 ) && ( size == max ) ) //max reached
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
incr *= 2; //increase increment
|
||||
//increase size and try again
|
||||
if( ( max != -1 ) && ( ( size + incr ) > max ) ) {
|
||||
incr = ( max - size );
|
||||
}
|
||||
|
||||
temp = ( char * )realloc( ( *ret ), size + incr );
|
||||
if( temp == NULL ) {
|
||||
break;
|
||||
}
|
||||
size += incr;
|
||||
( *ret ) = temp;
|
||||
|
||||
} else {
|
||||
if( ( retc + 1 ) > size ) {
|
||||
//size not big enough
|
||||
//and vsnprintf
|
||||
//returns the necessary
|
||||
//number of bytes
|
||||
if( ( max != -1 ) && ( retc + 1 > max ) ) {
|
||||
retc = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
temp = ( char * )realloc( ( *ret ), retc + 1 );
|
||||
if( temp == NULL ) {
|
||||
retc = -1;
|
||||
break;
|
||||
}
|
||||
size = retc + 1;
|
||||
( *ret ) = temp; //size increased try again
|
||||
} else if( ( retc + 1 ) < size ) {
|
||||
//size is bigger than needed
|
||||
//try and reallocate smaller
|
||||
|
||||
temp = ( char * )realloc( ( *ret ), retc + 1 );
|
||||
if( temp != NULL ) {
|
||||
( *ret ) = temp;
|
||||
}
|
||||
break;
|
||||
} else //size is just right, exit
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if( retc < 0 ) {
|
||||
free( ( *ret ) );
|
||||
( *ret ) = NULL;
|
||||
}
|
||||
|
||||
return retc;
|
||||
}
|
||||
|
||||
void
|
||||
iasnprintfFree( char *fChar )
|
||||
{
|
||||
free( fChar );
|
||||
fChar = NULL;
|
||||
}
|
||||
Reference in New Issue
Block a user