📄 list.c
字号:
/*
* List.c
*
* Sample code for "Multithreading Applications in Win32"
* This is from Chapter 7, Listing 7-1
*
* Demonstrates an implementation of the
* Readers/Writers algorithm. This version
* gives preference to readers.
*/
#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include "ReadWrit.h"
///////////////////////////////////////////////////////
//
// Structure definition
//
typedef struct _Node
{
struct _Node *pNext;
char szBuffer[80];
} Node;
typedef struct _List
{
RWLock lock;
Node *pHead;
} List;
//
// Linked list prototypes
//
BOOL InitRWLock(RWLock *pLock);
BOOL DeleteList(List *pList);
BOOL AddHead(List *pList, Node *node);
BOOL DeleteHead(List *pList);
BOOL Insert(List *pList, Node *afterNode, Node *newNode);
Node *Next(List *pList, Node *node);
//
// Test functions prototypes
//
DWORD WINAPI LoadThreadFunc(LPVOID n);
DWORD WINAPI SearchThreadFunc(LPVOID n);
DWORD WINAPI DeleteThreadFunc(LPVOID n);
//
// Global variables
//
// This is the list we use for testing
List *gpList;
///////////////////////////////////////////////////////
List *CreateList()
{
List *pList = GlobalAlloc(GPTR, sizeof(List));
if (InitRWLock(&pList->lock) == FALSE)
{
GlobalFree(pList);
pList = NULL;
}
return pList;
}
BOOL DeleteList(List *pList)
{
AcquireWriteLock(&pList->lock);
while (DeleteHead(pList))
;
ReleaseWriteLock(&pList->lock);
DestroyRWLock(&gpList->lock);
GlobalFree(pList);
return TRUE;
}
BOOL AddHead(List *pList, Node *pNode)
{
if (!WriteOK(&pList->lock))
return FatalError("AddHead - not allowed to write!");
pNode->pNext = pList->pHead;
pList->pHead = pNode;
}
BOOL DeleteHead(List *pList)
{
Node *pNode;
if (!WriteOK(&pList->lock))
return FatalError("AddHead - not allowed to write!");
if (pList->pHead == NULL)
return FALSE;
pNode = pList->pHead->pNext;
GlobalFree(pList->pHead);
pList->pHead = pNode;
return TRUE;
}
BOOL Insert(List *pList, Node *afterNode, Node *newNode)
{
if (!WriteOK(&pList->lock))
return FatalError("Insert - not allowed to write!");
if (afterNode == NULL)
{
AddHead(pList, newNode);
}
else
{
newNode->pNext = afterNode->pNext;
afterNode->pNext = newNode;
}
}
Node *Next(List *pList, Node *pNode)
{
if (!ReadOK(&pList->lock))
{
FatalError("Next - Not allowed to read!");
return NULL;
}
if (pNode == NULL)
return pList->pHead;
else
return pNode->pNext;
}
///////////////////////////////////////////////////////
DWORD WINAPI ThreadFunc(LPVOID);
int main()
{
HANDLE hThrds[4];
int slot = 0;
int rc;
int nThreadCount = 0;
DWORD dwThreadId;
gpList = CreateList();
if (!gpList)
FatalError("main - List creation failed!");
hThrds[nThreadCount++] = CreateThread(NULL,
0, LoadThreadFunc, 0, 0, &dwThreadId );
hThrds[nThreadCount++] = CreateThread(NULL,
0, SearchThreadFunc, (LPVOID)"pNode", 0, &dwThreadId );
hThrds[nThreadCount++] = CreateThread(NULL,
0, SearchThreadFunc, (LPVOID)"pList", 0, &dwThreadId );
hThrds[nThreadCount++] = CreateThread(NULL,
0, DeleteThreadFunc, 0, 0, &dwThreadId );
/* Now wait for all threads to terminate */
rc = WaitForMultipleObjects(
nThreadCount,
hThrds,
TRUE,
INFINITE );
for (slot=0; slot<nThreadCount; slot++)
CloseHandle(hThrds[slot]);
printf("\nProgram finished.\n");
DeleteList(gpList);
return EXIT_SUCCESS;
}
/*
* 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;
}
/*
* 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;
}
/*
* 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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -