//任何转载源代码的请保留出处作者等相关信息
//作者:chlaws
//运行环境:visual studio 2008
//描述:银行家算法及演示结果
//说明:这里不给出原创的思路,在阅读过程中有不懂得可以询问
memset(_allocation,0,MAX);
memset(_need,0,MAX);
memset(_work,0,MAX);
memset(_tmpalloc,0,MAX);
memset(_tmpneed,0,MAX);
_finish=false;
//_insafe=false;
}
static void Prompt();
void InitProInfo();
ProcessInfo(const ProcessInfo& rhs);
ProcessInfo& operator=(const ProcessInfo& rhs);
~ProcessInfo(){}
friend ostream& operator<<(ostream& out,const ProcessInfo& rhs);
friend istream& operator>>(istream& in, const ProcessInfo& rhs);
friend class Banker;
private:
static string _sourcename[MAX];
static int _srctype;//资源种类数
static int _sourcenum[MAX];//各种资源的数量
static int _avaliable[MAX];
string _processname;
int _allocation[MAX];
int _need[MAX];
static bool _insafe;//判断是否已进入安全检查,通过该标志来确定是否输出work和max
//false 没进入过,不输出work,可输出max
//true 已进入过,输出work,不输出max
int _tmpalloc[MAX];
int _tmpneed[MAX];
int _work[MAX];
bool _finish;
};
//静态变量定义
bool ProcessInfo::_insafe = false;
string ProcessInfo::_sourcename[MAX]={"a","b","c"};
int ProcessInfo::_srctype=3;
int ProcessInfo::_sourcenum[MAX]={10,5,7};
int ProcessInfo::_avaliable[MAX]={-1};//第一个数-1用来标识可用资源avariable没有经过计算
//静态函数定义
void ProcessInfo::Prompt()
{
int tmplen=ProcessInfo::_srctype;
int ix;
cout << "初始时有" << tmplen << "种资源(";
for(ix=0; ix<tmplen-1; ix++)
{
cout << "[资源名:" << ProcessInfo::_sourcename[ix] <<",数量为:"
<< ProcessInfo::_sourcenum[ix] << "],";
}
cout << "[资源名:" <<ProcessInfo::_sourcename[ix] <<"数量为:"
<< ProcessInfo::_sourcenum[ix] << "]" << ")" ;
//若avariable已经计算过了,则输出
if(ProcessInfo::_avaliable[0] != -1)
{
cout << ",可用资源分别为(";
for(ix=0; ix<tmplen-1; ix++)
{
cout << ProcessInfo::_avaliable[ix] <<",";
}
cout << ProcessInfo::_avaliable[ix] << ")";
}
cout << endl;
}
//重载输出操作符
ostream& operator<<(ostream& out,const ProcessInfo& rhs)
{
out << rhs._processname << "/t";
int tmplen=ProcessInfo::_srctype;
int max[MAX];
int wkalloc[MAX];//work+allocation
ostream_iterator<int> itout(out," ");
//通过是否进入安全检查来判断是输出work还是max
if(ProcessInfo::_insafe)
{
for(int ix=0; ix<tmplen; ix++)
{
wkalloc[ix]=rhs._work[ix]+rhs._allocation[ix];
}
copy(rhs._work,rhs._work+tmplen,itout);
}
else
{
for(int ix=0; ix<tmplen; ix++)
{
max[ix]=rhs._allocation[ix]+rhs._need[ix];
}
copy(max,max+tmplen,itout);
}
out << " ";
copy(rhs._allocation,rhs._allocation+tmplen,itout);
out << " ";
copy(rhs._need,rhs._need+tmplen,itout);
out << " ";
if(ProcessInfo::_insafe)
{
copy(wkalloc,wkalloc+tmplen,itout);
out << "/t";
rhs._finish ? out << "true" : out <<"false";
}
return out;
}
//重载输入操作符
istream& operator>>(istream& in, ProcessInfo& rhs)
{
rhs.InitProInfo();
return in;
}
ProcessInfo& ProcessInfo::operator=(const ProcessInfo& rhs)
{
_processname=rhs._processname;
int tmplen=ProcessInfo::_srctype;
for(int ix=0; ix<tmplen; ix++)
{
_allocation[ix]=rhs._allocation[ix];
_need[ix]=rhs._need[ix];
_tmpalloc[ix]=rhs._tmpalloc[ix];
_tmpneed[ix]=rhs._tmpneed[ix];
_work[ix]=rhs._work[ix];
}
_finish=rhs._finish;
_insafe=rhs._insafe;
return *this;
}
ProcessInfo::ProcessInfo(const ProcessInfo& rhs)
{
_processname=rhs._processname;
int tmplen=ProcessInfo::_srctype;
for(int ix=0; ix<tmplen; ix++)
{
_allocation[ix]=rhs._allocation[ix];
_need[ix]=rhs._need[ix];
_tmpalloc[ix]=rhs._tmpalloc[ix];
_tmpneed[ix]=rhs._tmpneed[ix];
_work[ix]=rhs._work[ix];
}
_finish=rhs._finish;
//_insafe=rhs._insafe;
}
void ProcessInfo::InitProInfo()
{
cout << "输入进程名称:";
cin >> _processname;
int tmplen=ProcessInfo::_srctype;
int ix;
cout << "输入对每类资源的已分配[allocation](用空格隔开):" ;
for(ix=0; ix<tmplen; ix++)
{
cin >> _allocation[ix];
}
cout << "输入对每类资源的需求[need](用空格隔开):";
for(ix=0; ix<tmplen; ix++)
{
cin >> _need[ix];
}
cout << endl;
}
class Banker{
public:
Banker()
{
_ismodify=false;
}
Banker(const Banker& rhs)
{
copy(rhs._val.begin(),rhs._val.end(),_val.begin());
}
void InitBanker();
bool SafeCheck();
int Request(int* request);
bool BankerCheck(int rindex,int* request);
friend ostream& operator << (ostream& out,const Banker& rhs);
private:
//用来重置finish和work变量
void reset();
bool calavariable();
bool modify();
bool _ismodify;//用来确定是否对初始化信息做了修改false没修改,true已修改
vector<ProcessInfo> _val;
};
//Private function define
bool Banker::modify()
{
int tmplen;
cout << "输入资源种类数量:" ;
cin >> tmplen;
ProcessInfo::_srctype=tmplen;
cout << "输入各类资源名称(用空格隔开):" ;
for(int ix=0; ix<tmplen; ix++)
{
cin >> ProcessInfo::_sourcename[ix];
}
cout << "输入各类资源的数量(用空格隔开):";
for(int ix=0; ix<tmplen; ix++)
{
cin >> ProcessInfo::_sourcenum[ix];
}
return true;
}
bool Banker::calavariable()//计算每类可用资源数量
{
int srctypenum=ProcessInfo::_srctype;
int processnum=_val.size();
int usetotal;
for(int id=0; id<srctypenum; id++)
{
usetotal=0;
for(int ix=0; ix<processnum; ix++)
{
//ProcessInfo::_avaliable[id]+=_val[ix]._allocation[id];
usetotal+=_val[ix]._allocation[id];
}
//ProcessInfo::_avaliable[id] =
// ProcessInfo::_sourcenum[id] - ProcessInfo::_avaliable[id];
ProcessInfo::_avaliable[id] = ProcessInfo::_sourcenum[id] - usetotal;
if(ProcessInfo::_avaliable[id]<0)
{
//cout << "可用资源数为负";
return false;
}
}
return true;
}
void Banker::reset()
{
int tmplen=ProcessInfo::_srctype;
int processnum=_val.size();
for(int ix=0; ix<processnum; ix++)
{
_val[ix]._finish=false;
for(int id=0; id<tmplen; id++)
{
_val[ix]._work[id]=0;
}
}
}
//End private function define
bool Banker::BankerCheck(int rindex,int* request)
{
//进入预分配
//使用tmpalloc保存未修改的allocation
//使用tmpneed保存未修改的need
//使用临时变量tmpavaliable保存未修改的avaliable
//修改avaliable,allocation,need
int tmplen=ProcessInfo::_srctype;
int tmpavaliable[MAX];
int ix;
for(ix=0; ix<tmplen; ix++)
{
_val[rindex]._tmpalloc[ix] = _val[rindex]._allocation[ix];
_val[rindex]._tmpneed[ix] = _val[rindex]._need[ix];
tmpavaliable[ix] = ProcessInfo::_avaliable[ix];
ProcessInfo::_avaliable[ix] -= request[ix];
_val[rindex]._allocation[ix] += request[ix];
_val[rindex]._need[ix] -= request[ix];
}
//由于初始时调用过安全性检查,所以要重置finish和work
reset();
//不存在安全序列,重置avaliable,allocation,need
if(!SafeCheck())
{
for(ix=0; ix<tmplen; ix++)
{
_val[rindex]._allocation[ix] = _val[rindex]._tmpalloc[ix] ;
_val[rindex]._need[ix] = _val[rindex]._tmpneed[ix] ;
ProcessInfo::_avaliable[ix] = tmpavaliable[ix] ;
}
return false;
}
return true;
}
void Banker::InitBanker()
{
char c;
ProcessInfo::Prompt();
cout << "是否需要修改进程默认的初始相关信息(y/n):";
cin >> c;
if (c == 'y' || c == 'Y')
{
_ismodify=true;
if(!modify()){
cout << "operator error!";
exit(1);
}
}
if(_ismodify)
{
ProcessInfo::Prompt();
}
do{
ProcessInfo tmpObj;
cin >> tmpObj;
_val.push_back(tmpObj);
//system("cls"); //如果觉得需要刷新屏幕就把这句加上
cout << "是否完成输入,并进入安全检查(y/n):";
cout.flush();
cin >> c;
}while(c!='y' && c!='Y');
if(!calavariable())
{
cout << "calculator avariable error,avariable have negative value!" << endl;
exit(1);
}
}
bool Banker::SafeCheck()
{
int processnum=_val.size();
int tmplen=ProcessInfo::_srctype;
int tmpwork[MAX]={0};
copy(ProcessInfo::_avaliable,ProcessInfo::_avaliable+tmplen,tmpwork);
bool isnlessw=true;//标识need是否小于work;
int safenum=0;//保存finish为true的次数
vector<ProcessInfo> safelist;
//考虑最坏查找情况使用processnum次大循环进行查找
for(int i=0; i<processnum; i++)
{ //每次大循环中小循环,循环processnum次
for(int ix=0; ix<processnum; ix++)
{
if(_val[ix]._finish == false)
{
isnlessw=true;
//判断 need <= work;
for(int id=0; id<tmplen; id++)
{
if(_val[ix]._need[id] > tmpwork[id])
{
isnlessw=false;
break;
}
}
if(!isnlessw)//need !<= work,则跳过对finish,work的修改.表示没有找到符合条件的
{
continue;
}
else
{
_val[ix]._finish=true;
safenum += 1;
//修改work
copy(tmpwork,tmpwork+tmplen,_val[ix]._work);
//修改tmpwork
for(int id=0; id <tmplen; id++)
{
//work=work+allocation
tmpwork[id]=tmpwork[id]+_val[ix]._allocation[id];
}
//将符合的要求的进程项插入安全序列中
safelist.push_back(_val[ix]);
}
}
}
}
if(safenum != processnum)
{
cout << "不存在安全序列" << endl;
return false;
}
else
{
ProcessInfo::_insafe=true;//修改insafe标志,表示进入了安全检查.
//用于在输出时输出work,而不输出max等
cout << "存在安全序列!" <<endl;
//ProcessInfo::Prompt();
cout << "进程/tWork/tAllocation/tNeed/tWork+Allocation/tFinish/n";
ostream_iterator<ProcessInfo> itout(cout,"/n");
copy(safelist.begin(),safelist.end(),itout);
}
return true;
}
int Banker::Request(int* request)
{
int tmplen=ProcessInfo::_srctype;
//int request[MAX];
cout << "输入请求资源的进程名称(";
int processnum=_val.size();
int ix;//用于循环中的下标索引变量
int rindex=-1;//用来保存request所对应进程在进程序列中的索引值
for(ix=0; ix < processnum-1; ix++)
{
cout << _val[ix]._processname <<",";
}
cout << _val[processnum-1]._processname<< "):";
string rprocessname;
cin >> rprocessname;
bool isnametrue=false; //标识输入的进程名称是否正确.
//int isnametrue=0; //标识输入的进程名称是否正确.
//判断进程名是否在进程序列中
for(ix=0; ix < processnum; ix++)
{
if(rprocessname.compare(_val[ix]._processname) == 0)
{
isnametrue=true;
//isnametrue=1;
rindex=ix;
break;
}
}
if(!isnametrue)
{
cout<< "输入的进程名不在进程序列中,出错退出!" << endl;
exit(1);
}
cout << "输入对各类资源的请求数量(用空格隔开):";
for(ix=0; ix<tmplen; ix++)
{
cin >> request[ix];
}
bool isrlessn=true;//用来标识request是否小于need;
//request <= need
for(ix=0; ix<tmplen; ix++)
{
if(request[ix] > _val[rindex]._need[ix])
{
isrlessn=false;
break;
}
}
if(!isrlessn)
{
cout << "error:request !<= need" << endl;
return -1;
}
bool isrlessa=true;//用来标识request是否小于avaliable;
//request <= avaliable
for(ix=0; ix<tmplen; ix++)
{
if(request[ix] > ProcessInfo::_avaliable[ix])
{
isrlessa=false;
break;
}
}
if(!isrlessa)
{
cout << "error:request !<= avaliable" << endl;
return -1;
}
return rindex;
}
ostream& operator << (ostream& out,const Banker& rhs)
{
cout << endl;
ProcessInfo::Prompt();
cout << "进程/tMax/tAllocation/tNeed/n";
ostream_iterator<ProcessInfo> itout(out,"/n");
copy(rhs._val.begin(),rhs._val.end(),itout);
return out;
}
int main()
{
Banker b;
b.InitBanker();
cout << b;
if(!b.SafeCheck())
{
cout << "在t0时刻不存在安全序列,结束退出" << endl;
exit(1);
}
else
{
cout << "所以在t0时刻存在安全序列" << endl;
}
int request[MAX];
int rindex;
while(1)
{
rindex=b.Request(request);
if(rindex ==-1 )
{
cout << "请求request 不符合条件" << endl;
continue;
}
if(!b.BankerCheck(rindex,request))
{
cout << "BankerCheck error:no exist safe queue!" << endl;
}
}
return 0;
}
运行结果如下: