/* * Every so often, walked the linked list * and figure out how many lines one string * appears (given as the startup param) */ DWORD WINAPI SearchThreadFunc(LPVOID n) { int i; char *szSearch = (char *)n; for (i=0; i<20; i++) { int nFoundCount = 0; Node *next = NULL; AcquireReadLock(&gpList->lock); next = Next(gpList, next); while (next) { if (strstr(next->szBuffer, szSearch)) nFoundCount++; next = Next(gpList, next); } ReleaseReadLock(&gpList->lock); printf("Found %d lines with '%s'\n", nFoundCount, szSearch); Sleep((rand() % 30)); } return 0; }
PWAH_HANDLE WINAPI WahReferenceContextByHandle(IN PWAH_HANDLE_TABLE Table, IN HANDLE Handle) { PWAH_HANDLE HashHandle; PWAH_SEARCH_TABLE SearchTable; PWAH_HASH_TABLE HashTable; PVLONG Count; /* Get the current Search Table */ SearchTable = WSH_SEARCH_TABLE_FROM_HANDLE(Handle, Table); /* Lock it */ AcquireReadLock(SearchTable, &Count); /* Get the hash table and handle */ HashTable = SearchTable->HashTable; /* Check if it's valid, and if it's the one we want */ if ((HashTable) && (HashHandle = WSH_HASH_FROM_HANDLE(Handle, HashTable)) && (HashHandle->Handle == Handle)) { /* Reference the handle */ InterlockedIncrement(&HashHandle->RefCount); } else { /* Invalid handle */ HashHandle = NULL; } /* Release the lock */ ReleaseReadLock(SearchTable, Count); /* Return */ return HashHandle; }
PWAH_HANDLE WINAPI WahInsertHandleContext(IN PWAH_HANDLE_TABLE Table, IN PWAH_HANDLE Handle) { PWAH_HANDLE *HashHandle, OldHandle; PVLONG Count; PWAH_HASH_TABLE HashTable, NewHashTable; DWORD HandleCount, i; PWAH_SEARCH_TABLE SearchTable; /* Get the current Search Table */ SearchTable = WSH_SEARCH_TABLE_FROM_HANDLE(Handle->Handle, Table); /* Start loop */ do { /* Get reader lock */ AcquireReadLock(SearchTable, &Count); /* Get the hash table */ HashTable = SearchTable->HashTable; /* Make sure we are not expanding, and that the table is there */ if (!(SearchTable->Expanding) && (HashTable)) { /* Get the hash handle */ HashHandle = &WSH_HASH_FROM_HANDLE(Handle->Handle, HashTable); /* Do the insert */ if (InterlockedCompareExchangePointer((PVOID*)HashHandle, Handle, NULL) == NULL) { /* Success, release the reader lock */ ReleaseReadLock(SearchTable, Count); /* Save old handle */ OldHandle = Handle; break; } } /* Release the read lock since we're done with it now */ ReleaseReadLock(SearchTable, Count); /* We need the writer lock to expand/create the table */ AcquireWriteLock(SearchTable); /* Mark the table in use */ SearchTable->Expanding = TRUE; /* Wait for all the readers to finish */ TryWaitForReaders(SearchTable); /* Start loop */ do { /* Get the hash table again */ HashTable = SearchTable->HashTable; /* Check if exists now */ if (HashTable) { /* It does! Do what we wanted to do earlier. Get the hash... */ HashHandle = &WSH_HASH_FROM_HANDLE(Handle->Handle, HashTable); /* Check if it doesn't exist */ if (!(*HashHandle)) { /* Write it (no need for interlock, we have the RW lock) */ OldHandle = Handle; *HashHandle = Handle; break; } else if ((*HashHandle)->Handle == Handle->Handle) { /* Handle matches, write it (see comment above) */ OldHandle = *HashHandle; *HashHandle = Handle; break; } /* No go, we need to expand the table. Remember the size now */ HandleCount = HashTable->Size; } else { /* Table is empty, we have to create it */ HandleCount = 0; } ExpandTable: /* Find a free prime */ for (i = 0; HandleCount >= SockPrimes[i]; i++); /* Check if we found one */ if (SockPrimes[i] != 0xFFFFFFFF) { /* Use the prime */ HandleCount = SockPrimes[i]; } else { /* No primes left. Table is quite large, so simply double it */ HandleCount *= 2; } /* Allocate the table */ NewHashTable = HeapAlloc(GlobalHeap, 0, FIELD_OFFSET(WSH_HASH_TABLE, Handles[HandleCount])); /* Hopefully we have one now */ if (NewHashTable) { /* Set its size */ NewHashTable->Size = HandleCount; /* Initialize it */ RtlZeroMemory(NewHashTable->Handles, HandleCount * sizeof(PVOID)); /* Insert us first */ WSH_HASH_FROM_HANDLE(Handle->Handle, NewHashTable) = Handle; /* Now check if our old table had entries in it */ if (HashTable) { /* We need to move them */ for (i = 0; i < HashTable->Size; i++) { /* Make sure the hash handle exists */ if (HashTable->Handles[i]) { /* Get it */ HashHandle = &WSH_HASH_FROM_HANDLE(HashTable-> Handles[i]->Handle, NewHashTable); /* Check if it has a value */ if (!(*HashHandle)) { /* It's empty, so just write the handle */ *HashHandle = HashTable->Handles[i]; } else { /* Not empty :/... that implies a collision */ HeapFree(GlobalHeap, 0, NewHashTable); goto ExpandTable; } } } /* Write the new hash table */ SearchTable->HashTable = NewHashTable; /* Wait for everyone to be done with it, then free it */ TryWaitForReaders(SearchTable); HeapFree(GlobalHeap, 0, HashTable); } else { /* It was empty, nothing to worry about */ SearchTable->HashTable = NewHashTable; } /* Save the old handle */ OldHandle = Handle; } else { /* There was no old handle */ OldHandle = Handle; } } while (0); /* Mark us as free, and release the write lock */ SearchTable->Expanding = FALSE; ReleaseWriteLock(SearchTable); break; } while (1); /* Return the old handle */ return OldHandle; }