📄 pdc.c
字号:
if (SearchRequest->File != NULL) {
CloseHandle( SearchRequest->File );
}
//
// Search the file contents, keeping track of line breaks
// so we can tell the line number of each match.
//
s = FileData;
LineNumber = 0;
MatchesFound = 0;
while (s < EndOfFile) {
BegLine = s;
while (s < EndOfFile && *s != '\n') {
s++;
}
if (*s == '\n') {
LineNumber += 1;
EndLine = s - 1;
if (EndLine > BegLine && EndLine[ -1 ] == '\r') {
EndLine -= 1;
}
s1 = BegLine;
while (s1 < (EndLine - SearchStringLength)) {
if (!(SearchFunction)( s1, SearchString, SearchStringLength )) {
//
// We have a match for this line. Append the
// output to the virtual buffer and update the
// current output pointer.
//
State->CurrentOutput += sprintf( State->CurrentOutput,
"%s(%u) : %.*s\n",
SearchRequest->FullPathName,
LineNumber,
EndLine - BegLine,
BegLine
);
MatchesFound += 1;
break;
}
s1++;
}
s++;
}
}
if (MatchesFound) {
MatchedLineCount += MatchesFound;
MatchedFileCount += 1;
}
SearchedFileCount += 1;
//
// All done with the file contents. Discard it either by
// unmapping the view of the file in the case of mapped file
// I/O or free the virtual memory for other types of I/O
//
if (MappedFileIO) {
if (!UnmapViewOfFile( FileData )) {
State->CurrentOutput += sprintf( State->CurrentOutput,
"%s(%u) : UnmapViewOfFile( %08x ) failed, error == %u\n",
SearchRequest->FullPathName,
LineNumber,
FileData,
GetLastError()
);
}
}
else {
VirtualFree( FileData, 0, MEM_RELEASE );
}
}
PWORK_QUEUE
CreateWorkQueue(
IN DWORD NumberOfWorkerThreads,
IN PWORKER_ROUTINE WorkerRoutine
)
/*++
Routine Description:
This function creates a work queue, with the specified number of
threads to service work items placed in the queue. Work items
are removed from the queue in the same order that they are placed
in the queue.
Arguments:
NumberOfWorkerThreads - Specifies how many threads this function
should create to process work items placed in the queue.
Must be greater than 0 and less than 128.
WorkerRoutine - Specifies the address of a routine to call
for each work item as it is removed from the queue. The
thread context the routine is called in is undefined.
Return Value:
A pointer to the work queue. Returns NULL if unable to create
the work queue and its worker threads. Extended error information
is available from GetLastError()
--*/
{
PWORK_QUEUE WorkQueue;
HANDLE Thread;
DWORD ThreadId;
DWORD i;
//
// Allocate space for the work queue, which includes an
// array of thread handles.
//
WorkQueue = LocalAlloc( LMEM_ZEROINIT,
sizeof( *WorkQueue ) +
(NumberOfWorkerThreads * sizeof( HANDLE ))
);
if (WorkQueue == NULL) {
return NULL;
}
//
// The work queue is controlled by a counting semaphore that
// is incremented each time a work item is placed in the queue
// and decremented each time a worker thread wakes up to remove
// an item from the queue.
//
if (WorkQueue->Semaphore = CreateSemaphore( NULL, 0, 100000, NULL )) {
//
// Mutual exclusion between the worker threads accessing
// the work queue is done with a critical section.
//
InitializeCriticalSection( &WorkQueue->CriticalSection );
//
// The queue itself is just a doubly linked list, where
// items are placed in the queue at the tail of the list
// and removed from the queue from the head of the list.
//
InitializeListHead( &WorkQueue->Queue );
//
// Removed the address of the supplied worker function
// in the work queue structure.
//
WorkQueue->WorkerRoutine = WorkerRoutine;
//
// Now create the requested number of worker threads.
// The handle to each thread is remembered in an
// array of thread handles in the work queue structure.
//
for (i=0; i<NumberOfWorkerThreads; i++) {
Thread = CreateThread( NULL,
0,
(LPTHREAD_START_ROUTINE) WorkerThread,
WorkQueue,
0,
&ThreadId
);
if (Thread == NULL) {
break;
}
else {
WorkQueue->NumberOfWorkerThreads++;
WorkQueue->WorkerThreads[ i ] = Thread;
SetThreadPriority( Thread, THREAD_PRIORITY_ABOVE_NORMAL );
}
}
//
// If we successfully created all of the worker threads
// then return the address of the work queue structure
// to indicate success.
//
if (i == NumberOfWorkerThreads) {
return WorkQueue;
}
}
//
// Failed for some reason. Destroy whatever we managed
// to create and return failure to the caller.
//
DestroyWorkQueue( WorkQueue );
return NULL;
}
VOID
DestroyWorkQueue(
IN OUT PWORK_QUEUE WorkQueue
)
/*++
Routine Description:
This function destroys a work queue created with the CreateWorkQueue
functions. It attempts to shut down the worker threads cleanly
by queueing a terminate work item to each worker thread. It then
waits for all the worker threads to terminate. If the wait is
not satisfied within 30 seconds, then it goes ahead and terminates
all of the worker threads.
Arguments:
WorkQueue - Supplies a pointer to the work queue to destroy.
Return Value:
None.
--*/
{
DWORD i;
DWORD rc;
//
// If the semaphore handle field is not NULL, then there
// may be threads to terminate.
//
if (WorkQueue->Semaphore != NULL) {
//
// Set the termiating flag in the work queue and
// signal the counting semaphore by the number
// worker threads so they will all wake up and
// notice the terminating flag and exit.
//
EnterCriticalSection( &WorkQueue->CriticalSection );
_try {
WorkQueue->Terminating = TRUE;
ReleaseSemaphore( WorkQueue->Semaphore,
WorkQueue->NumberOfWorkerThreads,
NULL
);
}
_finally {
LeaveCriticalSection( &WorkQueue->CriticalSection );
}
//
// Wait for all worker threads to wake up and see the
// terminate flag and then terminate themselves. Timeout
// the wait after 30 seconds.
//
while (TRUE) {
rc = WaitForMultipleObjectsEx( WorkQueue->NumberOfWorkerThreads,
WorkQueue->WorkerThreads,
TRUE,
30000,
TRUE
);
if (rc == WAIT_IO_COMPLETION) {
//
// If we came out of the wait because an I/O
// completion routine was called, reissue the
// wait.
//
continue;
}
else {
break;
}
}
//
// Now close our thread handles so they will actually
// evaporate. If the wait above was unsuccessful,
// then first attempt to force the termination of
// each worker thread prior to closing the handle.
//
for (i=0; i<WorkQueue->NumberOfWorkerThreads; i++) {
if (rc != NO_ERROR) {
TerminateThread( WorkQueue->WorkerThreads[ i ], rc );
}
CloseHandle( WorkQueue->WorkerThreads[ i ] );
}
//
// All threads stopped, all thread handles closed. Now
// delete the critical section and close the semaphore
// handle.
//
DeleteCriticalSection( &WorkQueue->CriticalSection );
CloseHandle( WorkQueue->Semaphore );
}
//
// Everything done, now free the memory used by the work queue.
//
LocalFree( WorkQueue );
return;
}
BOOL
QueueWorkItem(
IN OUT PWORK_QUEUE WorkQueue,
IN PWORK_QUEUE_ITEM WorkItem
)
/*++
Routine Description:
This function queues a work item to the passed work queue that is
processed by one of the worker threads associated with the queue.
Arguments:
WorkQueue - Supplies a pointer to the work queue that is to
receive the work item.
WorkItem - Supplies a pointer to the work item to add the the queue.
The work item structure contains a doubly linked list entry, the
address of a routine to call and a parameter to pass to that
routine. It is the routine's responsibility to reclaim the
storage occupied by the WorkItem structure.
Return Value:
TRUE if operation was successful. Otherwise returns FALSE and
extended error information is available from GetLastError()
--*/
{
BOOL Result;
//
// Acquire the work queue critical section and insert the work item
// in the queue and release the semaphore if the work item is not
// already in the list.
//
EnterCriticalSection( &WorkQueue->CriticalSection );
Result = TRUE;
_try {
WorkItem->WorkQueue = WorkQueue;
InsertTailList( &WorkQueue->Queue, &WorkItem->List );
Result = ReleaseSemaphore( WorkQueue->Semaphore, 1, NULL );
}
_finally {
LeaveCriticalSection( &WorkQueue->CriticalSection );
}
return Result;
}
DWORD
WorkerThread(
LPVOID lpThreadParameter
)
{
PWORK_QUEUE WorkQueue = (PWORK_QUEUE)lpThreadParameter;
DWORD rc;
WORK_QUEUE_ITEM InitWorkItem;
PWORK_QUEUE_ITEM WorkItem;
//
// Call the worker routine with an initialize work item
// to give it a change to initialize some per thread
// state that will passed to it for each subsequent
// work item.
//
InitWorkItem.Reason = WORK_INITIALIZE_ITEM;
(WorkQueue->WorkerRoutine)( &InitWorkItem );
while( TRUE ) {
_try {
//
// Wait until something is put in the queue (semaphore is
// released), remove the item from the queue, mark it not
// inserted, and execute the specified routine.
//
rc = WaitForSingleObjectEx( WorkQueue->Semaphore, 0xFFFFFFFF, TRUE );
if (rc == WAIT_IO_COMPLETION) {
continue;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -