libfreerdp-core: added reference counter for receive buffers
This commit is contained in:
parent
136bbc8bf7
commit
5b4aaf276f
@ -693,14 +693,15 @@ int transport_check_fds(rdpTransport** ptransport)
|
|||||||
* 1: asynchronous return
|
* 1: asynchronous return
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
ReferenceTable_Add(transport->ReceiveReferences, received);
|
||||||
|
|
||||||
recv_status = transport->ReceiveCallback(transport, received, transport->ReceiveExtra);
|
recv_status = transport->ReceiveCallback(transport, received, transport->ReceiveExtra);
|
||||||
|
|
||||||
|
ReferenceTable_Release(transport->ReceiveReferences, received);
|
||||||
|
|
||||||
if (recv_status < 0)
|
if (recv_status < 0)
|
||||||
status = -1;
|
status = -1;
|
||||||
|
|
||||||
if (recv_status == 0)
|
|
||||||
transport_receive_pool_return(transport, received);
|
|
||||||
|
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
@ -789,6 +790,9 @@ rdpTransport* transport_new(rdpSettings* settings)
|
|||||||
transport->ReceiveQueue = Queue_New(TRUE, -1, -1);
|
transport->ReceiveQueue = Queue_New(TRUE, -1, -1);
|
||||||
Queue_Object(transport->ReceivePool)->fnObjectFree = (OBJECT_FREE_FN) stream_free;
|
Queue_Object(transport->ReceivePool)->fnObjectFree = (OBJECT_FREE_FN) stream_free;
|
||||||
Queue_Object(transport->ReceiveQueue)->fnObjectFree = (OBJECT_FREE_FN) stream_free;
|
Queue_Object(transport->ReceiveQueue)->fnObjectFree = (OBJECT_FREE_FN) stream_free;
|
||||||
|
|
||||||
|
transport->ReceiveReferences = ReferenceTable_New(TRUE,
|
||||||
|
(void*) transport, (REFERENCE_FREE) transport_receive_pool_return);
|
||||||
}
|
}
|
||||||
|
|
||||||
return transport;
|
return transport;
|
||||||
@ -819,6 +823,8 @@ void transport_free(rdpTransport* transport)
|
|||||||
Queue_Free(transport->ReceivePool);
|
Queue_Free(transport->ReceivePool);
|
||||||
Queue_Free(transport->ReceiveQueue);
|
Queue_Free(transport->ReceiveQueue);
|
||||||
|
|
||||||
|
ReferenceTable_Free(transport->ReceiveReferences);
|
||||||
|
|
||||||
free(transport);
|
free(transport);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,6 +69,8 @@ struct rdp_transport
|
|||||||
|
|
||||||
wQueue* ReceivePool;
|
wQueue* ReceivePool;
|
||||||
wQueue* ReceiveQueue;
|
wQueue* ReceiveQueue;
|
||||||
|
|
||||||
|
wReferenceTable* ReceiveReferences;
|
||||||
};
|
};
|
||||||
|
|
||||||
STREAM* transport_recv_stream_init(rdpTransport* transport, int size);
|
STREAM* transport_recv_stream_init(rdpTransport* transport, int size);
|
||||||
|
@ -701,6 +701,8 @@ void update_free(rdpUpdate* update)
|
|||||||
|
|
||||||
CloseHandle(update->thread);
|
CloseHandle(update->thread);
|
||||||
|
|
||||||
|
Queue_Free(update->queue);
|
||||||
|
|
||||||
free(update);
|
free(update);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -174,4 +174,32 @@ struct _wKeyValuePair
|
|||||||
};
|
};
|
||||||
typedef struct _wKeyValuePair wKeyValuePair;
|
typedef struct _wKeyValuePair wKeyValuePair;
|
||||||
|
|
||||||
|
/* Reference Table */
|
||||||
|
|
||||||
|
struct _wReference
|
||||||
|
{
|
||||||
|
UINT32 Count;
|
||||||
|
void* Pointer;
|
||||||
|
};
|
||||||
|
typedef struct _wReference wReference;
|
||||||
|
|
||||||
|
typedef int (*REFERENCE_FREE)(void* context, void* ptr);
|
||||||
|
|
||||||
|
struct _wReferenceTable
|
||||||
|
{
|
||||||
|
UINT32 size;
|
||||||
|
HANDLE mutex;
|
||||||
|
void* context;
|
||||||
|
BOOL synchronized;
|
||||||
|
wReference* array;
|
||||||
|
REFERENCE_FREE ReferenceFree;
|
||||||
|
};
|
||||||
|
typedef struct _wReferenceTable wReferenceTable;
|
||||||
|
|
||||||
|
WINPR_API UINT32 ReferenceTable_Add(wReferenceTable* referenceTable, void* ptr);
|
||||||
|
WINPR_API UINT32 ReferenceTable_Release(wReferenceTable* referenceTable, void* ptr);
|
||||||
|
|
||||||
|
WINPR_API wReferenceTable* ReferenceTable_New(BOOL synchronized, void* context, REFERENCE_FREE ReferenceFree);
|
||||||
|
WINPR_API void ReferenceTable_Free(wReferenceTable* referenceTable);
|
||||||
|
|
||||||
#endif /* WINPR_COLLECTIONS_H */
|
#endif /* WINPR_COLLECTIONS_H */
|
||||||
|
@ -51,6 +51,10 @@
|
|||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
typedef void *(*pthread_start_routine)(void*);
|
typedef void *(*pthread_start_routine)(void*);
|
||||||
@ -95,7 +99,7 @@ HANDLE GetCurrentProcess(VOID)
|
|||||||
|
|
||||||
DWORD GetCurrentProcessId(VOID)
|
DWORD GetCurrentProcessId(VOID)
|
||||||
{
|
{
|
||||||
return 0;
|
return ((DWORD) getpid());
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD GetProcessId(HANDLE Process)
|
DWORD GetProcessId(HANDLE Process)
|
||||||
|
@ -21,6 +21,7 @@ set(MODULE_PREFIX "WINPR_UTILS")
|
|||||||
set(${MODULE_PREFIX}_COLLECTIONS_SRCS
|
set(${MODULE_PREFIX}_COLLECTIONS_SRCS
|
||||||
collections/Queue.c
|
collections/Queue.c
|
||||||
collections/Stack.c
|
collections/Stack.c
|
||||||
|
collections/Reference.c
|
||||||
collections/ArrayList.c
|
collections/ArrayList.c
|
||||||
collections/Dictionary.c
|
collections/Dictionary.c
|
||||||
collections/ListDictionary.c
|
collections/ListDictionary.c
|
||||||
|
171
winpr/libwinpr/utils/collections/Reference.c
Normal file
171
winpr/libwinpr/utils/collections/Reference.c
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
/**
|
||||||
|
* WinPR: Windows Portable Runtime
|
||||||
|
* Reference Count Table
|
||||||
|
*
|
||||||
|
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <winpr/crt.h>
|
||||||
|
|
||||||
|
#include <winpr/collections.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* C reference counting
|
||||||
|
* http://msdn.microsoft.com/en-us/library/windows/desktop/ms693431/
|
||||||
|
*/
|
||||||
|
|
||||||
|
wReference* ReferenceTable_FindEntry(wReferenceTable* referenceTable, void* ptr)
|
||||||
|
{
|
||||||
|
int index = 0;
|
||||||
|
BOOL found = FALSE;
|
||||||
|
wReference* reference = NULL;
|
||||||
|
|
||||||
|
for (index = 0; index < referenceTable->size; index++)
|
||||||
|
{
|
||||||
|
reference = &referenceTable->array[index];
|
||||||
|
|
||||||
|
if (reference->Pointer == ptr)
|
||||||
|
found = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (found) ? reference : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
wReference* ReferenceTable_GetFreeEntry(wReferenceTable* referenceTable)
|
||||||
|
{
|
||||||
|
int index = 0;
|
||||||
|
BOOL found = FALSE;
|
||||||
|
wReference* reference = NULL;
|
||||||
|
|
||||||
|
for (index = 0; index < referenceTable->size; index++)
|
||||||
|
{
|
||||||
|
reference = &referenceTable->array[index];
|
||||||
|
|
||||||
|
if (reference->Pointer == NULL)
|
||||||
|
{
|
||||||
|
reference->Count = 0;
|
||||||
|
found = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
referenceTable->size *= 2;
|
||||||
|
referenceTable->array = (wReference*) realloc(referenceTable->array, sizeof(wReference) * referenceTable->size);
|
||||||
|
|
||||||
|
ZeroMemory(&referenceTable->array[(referenceTable->size / 2)],
|
||||||
|
sizeof(wReference) * (referenceTable->size / 2));
|
||||||
|
|
||||||
|
return ReferenceTable_GetFreeEntry(referenceTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
return reference;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT32 ReferenceTable_Add(wReferenceTable* referenceTable, void* ptr)
|
||||||
|
{
|
||||||
|
UINT32 count = 0;
|
||||||
|
wReference* reference = NULL;
|
||||||
|
|
||||||
|
if (referenceTable->synchronized)
|
||||||
|
WaitForSingleObject(referenceTable->mutex, INFINITE);
|
||||||
|
|
||||||
|
reference = ReferenceTable_FindEntry(referenceTable, ptr);
|
||||||
|
|
||||||
|
if (!reference)
|
||||||
|
{
|
||||||
|
reference = ReferenceTable_GetFreeEntry(referenceTable);
|
||||||
|
reference->Pointer = ptr;
|
||||||
|
reference->Count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
count = ++(reference->Count);
|
||||||
|
|
||||||
|
if (referenceTable->synchronized)
|
||||||
|
ReleaseMutex(referenceTable->mutex);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT32 ReferenceTable_Release(wReferenceTable* referenceTable, void* ptr)
|
||||||
|
{
|
||||||
|
UINT32 count = 0;
|
||||||
|
wReference* reference = NULL;
|
||||||
|
|
||||||
|
if (referenceTable->synchronized)
|
||||||
|
WaitForSingleObject(referenceTable->mutex, INFINITE);
|
||||||
|
|
||||||
|
reference = ReferenceTable_FindEntry(referenceTable, ptr);
|
||||||
|
|
||||||
|
if (reference)
|
||||||
|
{
|
||||||
|
count = --(reference->Count);
|
||||||
|
|
||||||
|
if (count < 1)
|
||||||
|
{
|
||||||
|
if (referenceTable->ReferenceFree)
|
||||||
|
{
|
||||||
|
referenceTable->ReferenceFree(referenceTable->context, ptr);
|
||||||
|
reference->Pointer = NULL;
|
||||||
|
reference->Count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (referenceTable->synchronized)
|
||||||
|
ReleaseMutex(referenceTable->mutex);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
wReferenceTable* ReferenceTable_New(BOOL synchronized, void* context, REFERENCE_FREE ReferenceFree)
|
||||||
|
{
|
||||||
|
wReferenceTable* referenceTable;
|
||||||
|
|
||||||
|
referenceTable = (wReferenceTable*) malloc(sizeof(wReferenceTable));
|
||||||
|
|
||||||
|
if (referenceTable)
|
||||||
|
{
|
||||||
|
referenceTable->context = context;
|
||||||
|
referenceTable->ReferenceFree = ReferenceFree;
|
||||||
|
|
||||||
|
referenceTable->size = 32;
|
||||||
|
referenceTable->array = (wReference*) malloc(sizeof(wReference) * referenceTable->size);
|
||||||
|
ZeroMemory(referenceTable->array, sizeof(wReference) * referenceTable->size);
|
||||||
|
|
||||||
|
referenceTable->synchronized = synchronized;
|
||||||
|
referenceTable->mutex = CreateMutex(NULL, FALSE, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return referenceTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReferenceTable_Free(wReferenceTable* referenceTable)
|
||||||
|
{
|
||||||
|
if (referenceTable)
|
||||||
|
{
|
||||||
|
CloseHandle(referenceTable->mutex);
|
||||||
|
free(referenceTable->array);
|
||||||
|
free(referenceTable);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user