// ex3.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
// ex5.cpp : 定义控制台应用程序的入口点。
//
//#include "stdafx.h"
#include <windows.h>
#include <conio.h>
#include <fstream>
#include <stdio.h>
#include<iostream>
using namespace std;
#define INTE_PER_SEC 1000
#define MAX_THREAD_NUM 64
#define MAX_FILE_NUM 32
#define MAX_STR_LEN 32
int readcount = 0;
int writecount = 0;
CRITICAL_SECTION RP_Write;
struct ThreadInfo
{
int serial;
char entity;
double delay;
double persist;
};
class MySemaphore
{
public: HANDLE s1, s2;
public: int ResourceNum;
MySemaphore() {}
MySemaphore(int ResourceNum, char* name)
{/*
参数:
//1.安全属性
2.复位方式:false为自动复原
3.事件对象初始状态true为有信号
4.如果为NULL,将创建一个无名的事件对象。
*/
s1 = CreateEvent(NULL, FALSE, TRUE, NULL); //它用来创建或打开一个命名的或无名的事件对象。
s2 = CreateEvent(NULL, FALSE, FALSE, NULL);
this->ResourceNum = ResourceNum;
}
void P()
{/*
WaitForSingleObject函数用来检测hHandle事件的信号状态,在某一线程中调用该函数时,线程暂时挂起,
如果在挂起的dwMilliseconds毫秒内,线程所等待的对象变为有信号状态,则该函数立即返回;
如果超时时间已经到达dwMilliseconds毫秒,但hHandle所指向的对象还没有变成有信号状态,函数照样返回。
参数:
1.句柄对象
2.定时时间间隔(毫秒)
*/
//WaitForSingleObject(s1, -1);
WaitForSingleObject(this->s1, -1);
ResourceNum--;
if (this->ResourceNum<0)
{/*
ReleaseSemaphore函数用于对指定的信号量增加指定的值;
参数:
1.所要操作的信号量对象的句柄
2.这个信号量对象在当前基础上所要增加的值
3.指向返回信号量上次值的变量的指针,如果不需要信号量上次的值,
那么这个参数可以设置为NULL
*/
SetEvent(s1);
//WaitForSingleObject(s2, -1);
//ReleaseSemaphore(this->s1, 1, NULL);
WaitForSingleObject(this->s2, -1);
}
SetEvent(s1);
//ReleaseSemaphore(this->s1, 1, NULL);
}
void V()
{
//WaitForSingleObject(s1, -1);
WaitForSingleObject(this->s1, -1);
ResourceNum++;
if (ResourceNum <= 0)
{
SetEvent(s2);
//ReleaseSemaphore(this->s2, 1, NULL);
}
else
{
SetEvent(s1);
//ReleaseSemaphore(this->s1, 1, NULL);
}
}
};
char ReaderName[50] = "Reader", WriterName[50] = "Writer";
MySemaphore ReaderSemaphore, WriterSemaphore;
void ReaderPriority(char* file);
void RP_ReaderThread(void* p);
void RP_WriterThread(void* p);
////////////////////////////////////////////////////////
// main fuction
////////////////////////////////////////////////////////
int main()
{
char ReaderName[50] = "Reader", WriterName[50] = "Writer";
ReaderSemaphore = MySemaphore(1, ReaderName);
WriterSemaphore = MySemaphore(1, WriterName);
char ch;
while (TRUE)
{
// Cleare screen
system("cls");
// display prompt info
printf("*********************************************\n");
printf(" 1.Start test\n");
printf(" 2.Exit to Windows\n");
printf("*********************************************\n");
printf("Input your choice(1or2): ");
// if the number inputed is error, retry!
do {
ch = (char)_getch();
} while (ch != '1' && ch != '2');
system("cls");
if (ch == '1')
ReaderPriority("sm5.dat");
else if (ch == '2')
return 0;
printf("\nPress any key to finish this Program. \nThank you test this Program!\n");
_getch();
} //end while
} //end main
///////////////////////////////////////////////////////////////
// Reader Priority fuction
// file: filename
//////////////////////////////////////////////////////////////
void ReaderPriority(char* file)
{
DWORD n_thread = 0;
DWORD thread_ID;
DWORD wait_for_all;
// Mutex Object
//HANDLE h_Mutex;
//h_Mutex = CreateMutex( NULL,FALSE,"mutex_for_readcount" );
// Tread Object Array
HANDLE h_Thread[MAX_THREAD_NUM];
ThreadInfo thread_info[MAX_THREAD_NUM];
readcount = 0; //init readercount
//InitializeCriticalSection(&RP_Write); //init critical sectoin
ifstream inFile;
inFile.open(file); //open file
printf("Reader Priority:\n\n");
while (inFile)
{
// read every reader/writer info
inFile >> thread_info[n_thread].serial;
inFile >> thread_info[n_thread].entity;
inFile >> thread_info[n_thread].delay;
inFile >> thread_info[n_thread++].persist;
inFile.get();
} //end while
for (int i = 0; i < (int)(n_thread); i++)
{
if (thread_info[i].entity == 'R' || thread_info[i].entity == 'r')
{
// Create Reader thread
h_Thread[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(RP_ReaderThread), &thread_info[i], 0, &thread_ID);
}
else {
// Create Writer thread
h_Thread[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(RP_WriterThread), &thread_info[i], 0, &thread_ID);
}
} //end for
// waiting all thread will been finished
wait_for_all = WaitForMultipleObjects(n_thread, h_Thread, TRUE, -1);
printf("All reader and writer thread have finished Operating.\n");
}// end readerPriority
////////////////////////////////////
// reader priority -- reader thread
// p: reader thread info
///////////////////////////////////
void RP_ReaderThread(void* p)
{
// mutex
//HANDLE h_Mutex;
//h_Mutex = OpenMutex(MUTEX_ALL_ACCESS,FALSE,"mutex_for_readcount");
//DWORD wait_for_mutex;
DWORD m_delay;
DWORD m_persist;
int m_serial;
//get info from para
m_serial = ((ThreadInfo*)(p))->serial;
m_delay = (DWORD)(((ThreadInfo*)(p))->delay*INTE_PER_SEC);
m_persist = (DWORD)(((ThreadInfo*)(p))->persist*INTE_PER_SEC);
Sleep(m_delay);
printf("Reader thread %d sents the reading require .\n", m_serial);
// wait Rmutex
ReaderSemaphore.P();
//wait_for_mutex = WaitForSingleObject( h_Mutex,-1);
// inc reader count
readcount++;
if (readcount == 1)
{
// The frist reader
WriterSemaphore.P();
}
ReaderSemaphore.V();
// read file
printf("Reader thread %d begins to read file.\n", m_serial);
Sleep(m_persist);
//exit thread
printf("Reader thread %d finished reading file.\n", m_serial);
//waiting Mutex
ReaderSemaphore.P();
// dec Reader count
readcount--;
if (readcount == 0)
{
// singal Writer
WriterSemaphore.V();
}
ReaderSemaphore.V();
}
////////////////////////////////////
// Reader priority -- writer thread
// p: writer thread info
///////////////////////////////////
void RP_WriterThread(void* p)
{
DWORD m_delay;
DWORD m_persist;
int m_serial;
//get info froam para
m_serial = ((ThreadInfo*)(p))->serial;
m_delay = (DWORD)(((ThreadInfo*)(p))->delay*INTE_PER_SEC);
m_persist = (DWORD)(((ThreadInfo*)(p))->persist*INTE_PER_SEC);
Sleep(m_delay);
printf("Writer thread %d sents the writing require .\n", m_serial);
// wait resource
WriterSemaphore.P();
// write to the file
printf("Writer thread %d begins to write to the file.\n", m_serial);
Sleep(m_persist);
//exit thread
printf("Writer thread %d finished Writing to the file.\n", m_serial);
//release resource
WriterSemaphore.V();
}