diff --git a/libfreerdp/core/client.c b/libfreerdp/core/client.c index e80c3f595..83e4ff2d7 100644 --- a/libfreerdp/core/client.c +++ b/libfreerdp/core/client.c @@ -34,7 +34,7 @@ int g_open_handle_sequence = 1; /* For locking the global resources */ static CRITICAL_SECTION g_channels_lock; -rdpChannels* freerdp_channels_find_by_open_handle(int OpenHandle, int* pindex) +rdpChannels* freerdp_channels_find_by_open_handle(UINT32 OpenHandle, int* pindex) { int i, j; BOOL found = FALSE; diff --git a/winpr/include/winpr/collections.h b/winpr/include/winpr/collections.h index 0f6516e34..6e7568dbe 100644 --- a/winpr/include/winpr/collections.h +++ b/winpr/include/winpr/collections.h @@ -322,6 +322,9 @@ WINPR_API void CountdownEvent_Free(wCountdownEvent* countdown); struct _wHashTable { + BOOL synchronized; + CRITICAL_SECTION lock; + long numOfBuckets; long numOfElements; float idealRatio; @@ -346,7 +349,7 @@ WINPR_API BOOL HashTable_ContainsValue(wHashTable* table, void* value); WINPR_API void* HashTable_GetItemValue(wHashTable* table, void* key); WINPR_API BOOL HashTable_SetItemValue(wHashTable* table, void* key, void* value); -WINPR_API wHashTable* HashTable_New(); +WINPR_API wHashTable* HashTable_New(BOOL synchronized); WINPR_API void HashTable_Free(wHashTable* table); /* BufferPool */ diff --git a/winpr/libwinpr/utils/collections/HashTable.c b/winpr/libwinpr/utils/collections/HashTable.c index 0d4eaf985..15ae5175e 100644 --- a/winpr/libwinpr/utils/collections/HashTable.c +++ b/winpr/libwinpr/utils/collections/HashTable.c @@ -178,6 +178,7 @@ int HashTable_Count(wHashTable* table) int HashTable_Add(wHashTable* table, void* key, void* value) { + int status = 0; long hashValue; wKeyValuePair* pair; wKeyValuePair* newPair; @@ -185,6 +186,9 @@ int HashTable_Add(wHashTable* table, void* key, void* value) if (!key || !value) return -1; + if (table->synchronized) + EnterCriticalSection(&table->lock); + hashValue = table->hashFunction(key) % table->numOfBuckets; pair = table->bucketArray[hashValue]; @@ -213,7 +217,7 @@ int HashTable_Add(wHashTable* table, void* key, void* value) if (!newPair) { - return -1; + status = -1; } else { @@ -233,7 +237,10 @@ int HashTable_Add(wHashTable* table, void* key, void* value) } } - return 0; + if (table->synchronized) + LeaveCriticalSection(&table->lock); + + return status; } /** @@ -242,43 +249,54 @@ int HashTable_Add(wHashTable* table, void* key, void* value) BOOL HashTable_Remove(wHashTable* table, void* key) { + BOOL status = TRUE; long hashValue = table->hashFunction(key) % table->numOfBuckets; wKeyValuePair* pair = table->bucketArray[hashValue]; wKeyValuePair* previousPair = NULL; - while (pair != NULL && table->keycmp(key, pair->key) != 0) + if (table->synchronized) + EnterCriticalSection(&table->lock); + + while (pair && table->keycmp(key, pair->key) != 0) { previousPair = pair; pair = pair->next; } if (!pair) - return FALSE; - - if (table->keyDeallocator) - table->keyDeallocator((void*) pair->key); - - if (table->valueDeallocator) - table->valueDeallocator(pair->value); - - if (previousPair != NULL) - previousPair->next = pair->next; - else - table->bucketArray[hashValue] = pair->next; - - free(pair); - - table->numOfElements--; - - if (table->lowerRehashThreshold > 0.0) { - float elementToBucketRatio = (float) table->numOfElements / (float) table->numOfBuckets; + status = FALSE; + } + else + { + if (table->keyDeallocator) + table->keyDeallocator((void*) pair->key); - if (elementToBucketRatio < table->lowerRehashThreshold) - HashTable_Rehash(table, 0); + if (table->valueDeallocator) + table->valueDeallocator(pair->value); + + if (previousPair) + previousPair->next = pair->next; + else + table->bucketArray[hashValue] = pair->next; + + free(pair); + + table->numOfElements--; + + if (table->lowerRehashThreshold > 0.0) + { + float elementToBucketRatio = (float) table->numOfElements / (float) table->numOfBuckets; + + if (elementToBucketRatio < table->lowerRehashThreshold) + HashTable_Rehash(table, 0); + } } - return TRUE; + if (table->synchronized) + LeaveCriticalSection(&table->lock); + + return status; } /** @@ -287,14 +305,21 @@ BOOL HashTable_Remove(wHashTable* table, void* key) void* HashTable_GetItemValue(wHashTable* table, void* key) { + void* value = NULL; wKeyValuePair* pair; + if (table->synchronized) + EnterCriticalSection(&table->lock); + pair = HashTable_Get(table, key); - if (!pair) - return NULL; + if (pair) + value = pair->value; - return pair->value; + if (table->synchronized) + LeaveCriticalSection(&table->lock); + + return value; } /** @@ -303,16 +328,23 @@ void* HashTable_GetItemValue(wHashTable* table, void* key) BOOL HashTable_SetItemValue(wHashTable* table, void* key, void* value) { + BOOL status = TRUE; wKeyValuePair* pair; + if (table->synchronized) + EnterCriticalSection(&table->lock); + pair = HashTable_Get(table, key); if (!pair) - return FALSE; + status = FALSE; + else + pair->value = value; - pair->value = value; + if (table->synchronized) + LeaveCriticalSection(&table->lock); - return TRUE; + return status; } /** @@ -325,11 +357,14 @@ void HashTable_Clear(wHashTable* table) wKeyValuePair* pair; wKeyValuePair* nextPair; + if (table->synchronized) + EnterCriticalSection(&table->lock); + for (index = 0; index < table->numOfBuckets; index++) { pair = table->bucketArray[index]; - while (pair != NULL) + while (pair) { nextPair = pair->next; @@ -349,6 +384,9 @@ void HashTable_Clear(wHashTable* table) table->numOfElements = 0; HashTable_Rehash(table, 5); + + if (table->synchronized) + LeaveCriticalSection(&table->lock); } /** @@ -357,7 +395,17 @@ void HashTable_Clear(wHashTable* table) BOOL HashTable_Contains(wHashTable* table, void* key) { - return (HashTable_Get(table, key) != NULL) ? TRUE : FALSE; + BOOL status; + + if (table->synchronized) + EnterCriticalSection(&table->lock); + + status = (HashTable_Get(table, key) != NULL) ? TRUE : FALSE; + + if (table->synchronized) + LeaveCriticalSection(&table->lock); + + return status; } /** @@ -366,7 +414,17 @@ BOOL HashTable_Contains(wHashTable* table, void* key) BOOL HashTable_ContainsKey(wHashTable* table, void* key) { - return (HashTable_Get(table, key) != NULL) ? TRUE : FALSE; + BOOL status; + + if (table->synchronized) + EnterCriticalSection(&table->lock); + + status = (HashTable_Get(table, key) != NULL) ? TRUE : FALSE; + + if (table->synchronized) + LeaveCriticalSection(&table->lock); + + return status; } /** @@ -376,29 +434,42 @@ BOOL HashTable_ContainsKey(wHashTable* table, void* key) BOOL HashTable_ContainsValue(wHashTable* table, void* value) { int index; + BOOL status = FALSE; wKeyValuePair* pair; + if (table->synchronized) + EnterCriticalSection(&table->lock); + for (index = 0; index < table->numOfBuckets; index++) { pair = table->bucketArray[index]; - while (pair != NULL) + while (pair) { if (table->valuecmp(value, pair->value) == 0) - return TRUE; + { + status = TRUE; + break; + } pair = pair->next; } + + if (status) + break; } - return FALSE; + if (table->synchronized) + LeaveCriticalSection(&table->lock); + + return status; } /** * Construction, Destruction */ -wHashTable* HashTable_New() +wHashTable* HashTable_New(BOOL synchronized) { int index; wHashTable* table; @@ -407,6 +478,9 @@ wHashTable* HashTable_New() if (table) { + table->synchronized = synchronized; + InitializeCriticalSectionAndSpinCount(&table->lock, 4000); + table->numOfBuckets = 64; table->numOfElements = 0; diff --git a/winpr/libwinpr/utils/test/TestHashTable.c b/winpr/libwinpr/utils/test/TestHashTable.c index c804b7e71..e71a0ebba 100644 --- a/winpr/libwinpr/utils/test/TestHashTable.c +++ b/winpr/libwinpr/utils/test/TestHashTable.c @@ -17,7 +17,7 @@ int TestHashTable(int argc, char* argv[]) char* value; wHashTable* table; - table = HashTable_New(); + table = HashTable_New(TRUE); HashTable_Add(table, key1, val1); HashTable_Add(table, key2, val2);