S
sanya923
Здравствуйте!
Помогите пожалуйста решить проблему.
Читать лучше сразу самый низ кода - большой комент, там в принципе вся проблема и заключена.
Помогите пожалуйста решить проблему.
Читать лучше сразу самый низ кода - большой комент, там в принципе вся проблема и заключена.
C++:
// spo1.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include "windows.h"
#include "stdlib.h"
#include "stdio.h"
#include <string>
using namespace std;
class TQuery
{
/*только public оставил на свое усмотрение*/
public:
static TQuery *head,*tail;
static int count_query,count_obs;
int p,v,i;
TQuery *next,*pre;
TQuery(int p_, int v_, int i_) : p(p_), v(v_), i(i_), next(NULL), pre(NULL)
{}
//добавление элемента в очередь
void Past(TQuery *q)
{
count_query+=1;
TQuery *poisk;
poisk=head;
if (tail == NULL)
{
tail=q;
head=q;
}
else
{
if (q->p>poisk->p)
{
poisk->pre=q;
q->next=poisk;
head=q;
}
else
{
if (poisk->next==NULL)
{
q->pre=poisk;
poisk->next=q;
tail=q;
}
else
{
while ((q->p<=poisk->p)&&(poisk->next!=NULL))
poisk=poisk->next;
if (q->p==poisk->p)
{
poisk->next=q;
q->pre=poisk;
tail=q;
}
else
{
q->pre=poisk->pre;
poisk->pre->next=q;
poisk->pre=q;
q->next=poisk;
}
}
}
}
}
//удаление элемента из очереди
void UdElm()
{
TQuery *ud;
count_obs+=1;
count_query-=1;
if (head->next!=NULL)
{
head=head->next;
head->pre->next=NULL;
}
else
{
StartClear();
}
delete ud;
}
//обнуление параметров
void StartClear()
{head=NULL;tail=NULL;count_query=0;}
void ObsClear()
{count_obs=0;}
};
HANDLE sp; //для семафора
HANDLE s_kanal[3]; //для семафоров
HANDLE uvv[3]; //для устройст(потоков) обслуживающих заявки
HANDLE a,b; //а-поток поступающих заявок,b-поток опрашивающий устройства
bool p_kanal[3]; //признак занятости устройства
TQuery *q_elm_kanal[3]; //для обслуживающихся заявок
//поток с поступающими заявками
int fThread1()
{
int i=0;
double p_,v_,t1;
TQuery *z;
while (true)
{
WaitForSingleObject(sp,INFINITE);
i+=1;
p_=rand(); v_=rand(); p_=p_/32768; v_=v_/32678;
z = new TQuery(unsigned(20*p_+0.5),unsigned(8*v_+0.5),i);
z->Past(z);
cout<<"заявка № "<<i<<" встала в очередь (приоритет "<<z->p<<", объем "<<z->v<<", № "<<z->i<<")"<<endl;
ReleaseSemaphore(sp,1,NULL);
t1=rand();
t1=t1/32678;
t1=1000+2000*t1;
Sleep(unsigned(t1));
}
return 0;
}
//поток обслуживающего устройства(три устройства будет)
int fThread2(int i_)
{
double t2;
while (true)
{
WaitForSingleObject(s_kanal[i_],INFINITE);//-------здесь поток виснет--------
t2=rand(); t2=t2/32678; t2=1000*i_+1000*q_elm_kanal[i_]->v;
Sleep(unsigned(t2));
cout<<" устройство № "<<i_<<" обслужило заявку № "<<q_elm_kanal[i_]->i<<" за "<<unsigned(t2)<<endl;
p_kanal[i_]=true;
}
return 0;
}
//поток опрашивающий устройства
int fThread3()
{
int i;
while (true)
{
if (TQuery::count_query!=0)
{
for (i=0;i<3;i++)
{
WaitForSingleObject(sp,INFINITE);
if (p_kanal[i])
{
p_kanal[i]=false;
q_elm_kanal[i]=TQuery::head;
TQuery::UdElm;
cout<<" заявка № "<<q_elm_kanal[i]->i<<" поступила на устройство № "<<i<<endl;
ReleaseSemaphore(s_kanal[i],1,NULL);
ReleaseSemaphore(sp,1,NULL);
break;
}
ReleaseSemaphore(sp,1,NULL);
}
}
}
return 0;
}
int TQuery::count_obs;
int TQuery::count_query;
TQuery * TQuery::head;
TQuery * TQuery::tail;
int main()
{
TQuery::StartClear; TQuery::ObsClear;
//поток с поступающими заявками сразу начинает работать поэтому 1
sp=CreateSemaphore(NULL,1,1,NULL);
int i;
for (i=0;i<3;i++)
{
/*когда потоки устройств запускаются они должны ждать,
поэтому 0 поставил*/
s_kanal[i]=CreateSemaphore(NULL,0,1,NULL);
p_kanal[i]=true;
}
a=CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)fThread1,NULL,NULL,NULL);
for (i=0;i<3;i++)
{
/*здесь виснет при первом заходе(см. fThread2)
и на второй круг не идет, ну и следовательно и "b" тоже не запускается,
а в нем как раз ReleaseSemaphore, который должен просигнализировать.
поток "a" при этом продолжает работать.
в делфи писал, всё было норм. хотел разобраться с этим же и в с++.
думается я с потоками где-то налажал, неже ли с семафорами,
т.к. в делфи для синхронизации также пользовался API, т.е. CreateSemaphore,
WaitForSingleObject,ReleaseSemaphore, а вот поток создавал подругому, не с
помощью CreateThread*/
uvv[i]=CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)fThread2(i),NULL,NULL,NULL);
}
b=CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)fThread3,NULL,NULL,NULL);
return 0;
}