/* * Slowly load the contents of "List.c" into the * linked list. */ DWORD WINAPI LoadThreadFunc(LPVOID n) { int nBatchCount; Node *pNode; FILE* fp = fopen("List.c", "r"); if (!fp) { fprintf(stderr, "ReadWrit.c not found\n"); exit(EXIT_FAILURE); } pNode = GlobalAlloc(GPTR, sizeof(Node)); nBatchCount = (rand() % 10) + 2; AcquireWriteLock(&gpList->lock); while (fgets(pNode->szBuffer, sizeof(Node), fp)) { AddHead(gpList, pNode); // Try not to hog the lock if (--nBatchCount == 0) { ReleaseWriteLock(&gpList->lock); Sleep(rand() % 5); nBatchCount = (rand() % 10) + 2; AcquireWriteLock(&gpList->lock); } pNode = GlobalAlloc(GPTR, sizeof(Node)); } ReleaseWriteLock(&gpList->lock); return 0; }
BOOL WINAPI WahEnumerateHandleContexts(IN PWAH_HANDLE_TABLE Table, IN PWAH_HANDLE_ENUMERATE_PROC Callback, IN PVOID Context) { DWORD i, j; PWAH_SEARCH_TABLE SearchTable; PWAH_HASH_TABLE HashTable; PWAH_HANDLE Handle; BOOL GoOn = TRUE; /* Loop the table */ for (i = 0; i <= Table->Mask; i++) { /* Get the Search table */ SearchTable = &Table->SearchTables[i]; /* Lock it */ AcquireWriteLock(SearchTable); /* Mark us as expanding and wait for everyone */ SearchTable->Expanding = TRUE; TryWaitForReaders(SearchTable); /* Get the hash table */ HashTable = SearchTable->HashTable; /* Make sure it exists */ if (HashTable) { /* Loop every handle in it */ for (j = 0; j < HashTable->Size; j++) { /* Get this handle */ Handle = HashTable->Handles[j]; if (!Handle) continue; /* Call the callback proc */ GoOn = Callback(Context, Handle); if (!GoOn) break; } } /* Disable the expansion bit and release the lock */ SearchTable->Expanding = FALSE; ReleaseWriteLock(SearchTable); /* Check again if we should leave */ if (!GoOn) break; } /* return */ return GoOn; }
BOOL DeleteList(List *pList) { AcquireWriteLock(&pList->lock); while (DeleteHead(pList)) ; ReleaseWriteLock(&pList->lock); DestroyRWLock(&gpList->lock); GlobalFree(pList); return TRUE; }
/* * Every so often, delete some entries in the list. */ DWORD WINAPI DeleteThreadFunc(LPVOID n) { int i; for (i=0; i<100; i++) { Sleep(1); AcquireWriteLock(&gpList->lock); DeleteHead(gpList); DeleteHead(gpList); DeleteHead(gpList); ReleaseWriteLock(&gpList->lock); } return 0; }
DWORD WINAPI WahRemoveHandleContext(IN PWAH_HANDLE_TABLE Table, IN PWAH_HANDLE Handle) { PWAH_HANDLE *HashHandle; PWAH_SEARCH_TABLE SearchTable; PWAH_HASH_TABLE HashTable; DWORD ErrorCode = ERROR_SUCCESS; /* Get the current Search Table */ SearchTable = WSH_SEARCH_TABLE_FROM_HANDLE(Handle->Handle, Table); /* Lock it */ AcquireWriteLock(SearchTable); /* Get the hash table and handle */ HashTable = SearchTable->HashTable; HashHandle = &WSH_HASH_FROM_HANDLE(Handle->Handle, HashTable); /* Make sure we have a handle, and write the new pointer */ if (HashHandle && (InterlockedCompareExchangePointer((PVOID*)HashHandle, NULL, Handle) == Handle)) { /* Wait for everyone to be done with it */ TryWaitForReaders(SearchTable); } else { /* Invalid handle */ ErrorCode = ERROR_INVALID_PARAMETER; } /* Release the lock */ ReleaseWriteLock(SearchTable); /* Return */ return ErrorCode; }
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; }