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
|
||||
*/
|
||||
|
||||
ReferenceTable_Add(transport->ReceiveReferences, received);
|
||||
|
||||
recv_status = transport->ReceiveCallback(transport, received, transport->ReceiveExtra);
|
||||
|
||||
ReferenceTable_Release(transport->ReceiveReferences, received);
|
||||
|
||||
if (recv_status < 0)
|
||||
status = -1;
|
||||
|
||||
if (recv_status == 0)
|
||||
transport_receive_pool_return(transport, received);
|
||||
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
@ -789,6 +790,9 @@ rdpTransport* transport_new(rdpSettings* settings)
|
||||
transport->ReceiveQueue = Queue_New(TRUE, -1, -1);
|
||||
Queue_Object(transport->ReceivePool)->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;
|
||||
@ -819,6 +823,8 @@ void transport_free(rdpTransport* transport)
|
||||
Queue_Free(transport->ReceivePool);
|
||||
Queue_Free(transport->ReceiveQueue);
|
||||
|
||||
ReferenceTable_Free(transport->ReceiveReferences);
|
||||
|
||||
free(transport);
|
||||
}
|
||||
}
|
||||
|
@ -69,6 +69,8 @@ struct rdp_transport
|
||||
|
||||
wQueue* ReceivePool;
|
||||
wQueue* ReceiveQueue;
|
||||
|
||||
wReferenceTable* ReceiveReferences;
|
||||
};
|
||||
|
||||
STREAM* transport_recv_stream_init(rdpTransport* transport, int size);
|
||||
|
@ -701,6 +701,8 @@ void update_free(rdpUpdate* update)
|
||||
|
||||
CloseHandle(update->thread);
|
||||
|
||||
Queue_Free(update->queue);
|
||||
|
||||
free(update);
|
||||
}
|
||||
}
|
||||
|
@ -174,4 +174,32 @@ struct _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 */
|
||||
|
@ -51,6 +51,10 @@
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
typedef void *(*pthread_start_routine)(void*);
|
||||
@ -95,7 +99,7 @@ HANDLE GetCurrentProcess(VOID)
|
||||
|
||||
DWORD GetCurrentProcessId(VOID)
|
||||
{
|
||||
return 0;
|
||||
return ((DWORD) getpid());
|
||||
}
|
||||
|
||||
DWORD GetProcessId(HANDLE Process)
|
||||
|
@ -21,6 +21,7 @@ set(MODULE_PREFIX "WINPR_UTILS")
|
||||
set(${MODULE_PREFIX}_COLLECTIONS_SRCS
|
||||
collections/Queue.c
|
||||
collections/Stack.c
|
||||
collections/Reference.c
|
||||
collections/ArrayList.c
|
||||
collections/Dictionary.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