Jump to content
Forumu Destekleyenlere Katılın ×
Paticik Forumları
2000 lerden beri faal olan, çok şukela bir paylaşım platformuyuz. Hoşgeldiniz.

Dining Philosophers c++


LethE

Öne çıkan mesajlar

Bilindik Dining Philosophers sorununu monitor kullanarak c++ da yapmamız lazım (daha zor olcakmış bunu yapmamız daha iyiymiş .. pff)

Şimdi ben CCodeproject'den OO bir thread classı buldum.

az biraz ayak üstü oldu üstüne uzunca bir süredir kod yazmamaktan paslanma durumu var kodun kusura bakmayın lütfen.
monitorü şöyle yapayım dedim.

Monitor

class letheM {
public:
bool fork[5]; //our forks
bool kilit; // our lock
letheM(){ //contructor ultima
kilit=false;
for (int i=0; i<5; i++)
fork[i] = false; //all forks are free to start with
}
int pickup(int i){ //Let them pick up forks
if (kilit == true) //check lock
return 0; //notify that CR is occupied
else {
kilit=true; //lock CR
if (fork[i]==false && fork[(i-1)%5]==false) { //take both forks if both are free
fork[i]=true;
fork[(i-1)%5]=true;//pick up fork
kilit=false; //unlock CR
return 1; //notify success
}
else {
kilit=false; //unlock CR
return 0;
} //fork in use. notify failure
}//nested else if
}//pickup
int putdown(int i){
if (kilit == true) //check lock
return 0; //locked? fail!
else { //unlocked! put forks down
kilit=true; //lock it up
fork[i]=false; //let them go
fork[(i-1)%5]=false;
kilit=false; //unlock CR
}//else
}//putdown
};//class


üşenenler için Codeprojectteki thread class

Thread.h

#ifndef __THREAD_H__
#define __THREAD_H__
/////////////////////////////////////////////////////////////////////////////////
#include "Windows.h"

struct IRunnable {
virtual unsigned long run() = 0;
virtual void stop() = 0;
};

class ThreadException {
public:
ThreadException(DWORD lastError) {
HLOCAL msgBuffer;
::FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
0, lastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPSTR)&msgBuffer, 0, NULL);
Message = (LPSTR)msgBuffer;
::LocalFree(msgBuffer);
}

ThreadException(const std::string &msg) { Message = msg; }
std::string Message;
};

class Thread {
public:
Thread(IRunnable *ptr=0) {
_runnable = ptr;
_started = false;
_threadHandle = 0;
}

~Thread() {
if(_threadHandle != 0)
::CloseHandle(_threadHandle);
}

void start(IRunnable *ptr=0) {
if(_started)
throw ThreadException("Thread already started.");

if(!_started && _threadHandle != 0)
::CloseHandle(_threadHandle);

if(ptr != 0)
_runnable = ptr;

if(_runnable == 0)
throw ThreadException("An object implementing the IRunnable interface required.");


DWORD threadID=0;
_threadHandle = ::CreateThread(0, 0, ThreadProc, this, 0, &threadID);
if(_threadHandle == 0)
throw ThreadException(::GetLastError());

::Sleep(0);
}

void stop() {
checkAlive();
_runnable->stop();
}

void suspend() {
checkAlive();
checkThreadHandle();
if(::SuspendThread(_threadHandle) == -1)
throw ThreadException(::GetLastError());
}

void resume() {
checkAlive();
checkThreadHandle();
if(::ResumeThread(_threadHandle) == -1)
throw ThreadException(::GetLastError());
}

void join(unsigned long timeOut=INFINITE) {
checkThreadHandle();
if(isAlive()) {
DWORD waitResult = ::WaitForSingleObject(_threadHandle, timeOut);
if(waitResult == WAIT_FAILED)
throw ThreadException(::GetLastError());
}
}

bool isAlive() { return _started; }

protected:

bool _started;
HANDLE _threadHandle;
IRunnable *_runnable;

unsigned long run() {
_started = true;
unsigned long threadExitCode = _runnable->run();
_started = false;
return threadExitCode;
}

void checkThreadHandle() {
if(_threadHandle == 0)
throw ThreadException("Thread not yet created, call the start() method.");
}
void checkAlive() {
if(!isAlive())
throw ThreadException("No Thread alive.");
}

static unsigned long __stdcall ThreadProc(void* ptr) {
return ((Thread *)ptr)->run();
}
};

///////////////////////////////////////////////////////////////////////////////
#endif // __THREAD_H__



burda mainimsi

Mainimsi

// Thread.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "Thread.h"
#include "Monitor.h"


// define a threadable object
class ThreadableObject : public IRunnable {
public:
ThreadableObject() {
_continue = true;

//int id,hunger,result;
}
virtual unsigned long run(int id,int hunger,int result,letheM *mon) {
while(_continue) {
while(hunger>0){
result=mon->pickup(id);
if (result == 1) {
hunger--;
std::cout<<"Philosopher "< result=mon->putdown(id);
Sleep(500);
}
else {
std::cout<<"Philosopher "< Sleep(500);
}
}
std::cout<<"Philosopher "<
}
return 0;
}
virtual void stop() {
_continue = false;
}
protected:
bool _continue;
};



int _tmain(int argc, _TCHAR* argv[]) {
// example of usage

ThreadableObject *obj=0;
Thread *thread=0;
letheM mon;

try {
for(int x=0;x<5;x++){
// create the threadable object first
ThreadableObject *obj = new ThreadableObject(x,3,0,&mon);

// create and start the thread the thread
Thread *thread = new Thread(obj);
thread->start();

// see if the thread exits in 10 seconds
thread->join(10000);
}


printf("Ok.n");
getch();

}
catch (ThreadException &e)
{
printf(e.Message.c_str());
}


return 0;
}



görüldüğü gibi irunnable ın abstract run() tanımınıyla uyuşmuyor diyor fakat ben ikisininde parametrelerini aynı yapsamda (ki saçma geldi "class ThreadableObject : public IRunnable" diyerek yeni tanımlara sahip yeni bir class oluşturmuyormuyuz) olmadı :(
ayrıca bu join tam olarak ne yapmaya calısıyor onu da çözemedim bildiğim join processin thread bitene kadar ayakta kalmasını sağlamalı ama çözemedim burdakini.

alternatif olarakda QT librarysini kuramadım kurabilen varsa onu da haalledebilsem çok daha öz bir şekilde halledicem herhalde (yazdım compile edemedim :( )
Link to comment
Sosyal ağlarda paylaş

LethE said:

görüldüğü gibi irunnable ın abstract run() tanımınıyla uyuşmuyor diyor


Nerde görüldüğü gibi? Unutmuşsun sanırım hatayı koymayı.

Bir de şu kodları code tagları kullanarak


biçimlendirilmiş yazı


şeklinde koyabilir misin? Böyle okunabilirliği çok kötü. Gözlere zarar. :)
Link to comment
Sosyal ağlarda paylaş

Bilindik Dining Philosophers sorununu monitor kullanarak c++ da yapmamız lazım (daha zor olcakmış bunu yapmamız daha iyiymiş .. pff)

Şimdi ben CCodeproject'den OO bir thread classı buldum.

az biraz ayak üstü oldu üstüne uzunca bir süredir kod yazmamaktan paslanma durumu var kodun kusura bakmayın lütfen.
monitorü şöyle yapayım dedim.

Monitor


class letheM {
public:
bool fork[5]; //our forks
bool kilit; // our lock
letheM(){ //contructor ultima
kilit=false;
for (int i=0; i<5; i++)
fork[i] = false; //all forks are free to start with
}
int pickup(int i){ //Let them pick up forks
if (kilit == true) //check lock
return 0; //notify that CR is occupied
else {
kilit=true; //lock CR
if (fork[i]==false && fork[(i-1)%5]==false) { //take both forks if both are free
fork[i]=true;
fork[(i-1)%5]=true;//pick up fork
kilit=false; //unlock CR
return 1; //notify success
}
else {
kilit=false; //unlock CR
return 0;
} //fork in use. notify failure
}//nested else if
}//pickup
int putdown(int i){
if (kilit == true) //check lock
return 0; //locked? fail!
else { //unlocked! put forks down
kilit=true; //lock it up
fork[i]=false; //let them go
fork[(i-1)%5]=false;
kilit=false; //unlock CR
}//else
}//putdown
};//class




üşenenler için Codeprojectteki thread class

Thread.h


#ifndef __THREAD_H__
#define __THREAD_H__
/////////////////////////////////////////////////////////////////////////////////
#include "Windows.h"

struct IRunnable {
virtual unsigned long run() = 0;
virtual void stop() = 0;
};

class ThreadException {
public:
ThreadException(DWORD lastError) {
HLOCAL msgBuffer;
::FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
0, lastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPSTR)&msgBuffer, 0, NULL);
Message = (LPSTR)msgBuffer;
::LocalFree(msgBuffer);
}

ThreadException(const std::string &msg) { Message = msg; }
std::string Message;
};

class Thread {
public:
Thread(IRunnable *ptr=0) {
_runnable = ptr;
_started = false;
_threadHandle = 0;
}

~Thread() {
if(_threadHandle != 0)
::CloseHandle(_threadHandle);
}

void start(IRunnable *ptr=0) {
if(_started)
throw ThreadException("Thread already started.");

if(!_started && _threadHandle != 0)
::CloseHandle(_threadHandle);

if(ptr != 0)
_runnable = ptr;

if(_runnable == 0)
throw ThreadException("An object implementing the IRunnable interface required.");


DWORD threadID=0;
_threadHandle = ::CreateThread(0, 0, ThreadProc, this, 0, &threadID);
if(_threadHandle == 0)
throw ThreadException(::GetLastError());

::Sleep(0);
}

void stop() {
checkAlive();
_runnable->stop();
}

void suspend() {
checkAlive();
checkThreadHandle();
if(::SuspendThread(_threadHandle) == -1)
throw ThreadException(::GetLastError());
}

void resume() {
checkAlive();
checkThreadHandle();
if(::ResumeThread(_threadHandle) == -1)
throw ThreadException(::GetLastError());
}

void join(unsigned long timeOut=INFINITE) {
checkThreadHandle();
if(isAlive()) {
DWORD waitResult = ::WaitForSingleObject(_threadHandle, timeOut);
if(waitResult == WAIT_FAILED)
throw ThreadException(::GetLastError());
}
}

bool isAlive() { return _started; }

protected:

bool _started;
HANDLE _threadHandle;
IRunnable *_runnable;

unsigned long run() {
_started = true;
unsigned long threadExitCode = _runnable->run();
_started = false;
return threadExitCode;
}

void checkThreadHandle() {
if(_threadHandle == 0)
throw ThreadException("Thread not yet created, call the start() method.");
}
void checkAlive() {
if(!isAlive())
throw ThreadException("No Thread alive.");
}

static unsigned long __stdcall ThreadProc(void* ptr) {
return ((Thread *)ptr)->run();
}
};

///////////////////////////////////////////////////////////////////////////////
#endif // __THREAD_H__





burda mainimsi

Mainimsi


// Thread.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "Thread.h"
#include "Monitor.h"


// define a threadable object
class ThreadableObject : public IRunnable {
public:
ThreadableObject() {
_continue = true;

//int id,hunger,result;
}
virtual unsigned long run(int id,int hunger,int result,letheM *mon) {
while(_continue) {
while(hunger>0){
result=mon->pickup(id);
if (result == 1) {
hunger--;
std::cout<<"Philosopher "<<id<< " is eating!"<<std::endl;
result=mon->putdown(id);
Sleep(500);
}
else {
std::cout<<"Philosopher "<<id<< " is thinking!"<<std::endl;
Sleep(500);
}
}
std::cout<<"Philosopher "<<id<< " has finished eating!"<<std::endl;

}
return 0;
}
virtual void stop() {
_continue = false;
}
protected:
bool _continue;
};



int _tmain(int argc, _TCHAR* argv[]) {
// example of usage

ThreadableObject *obj=0;
Thread *thread=0;
letheM mon;

try {
for(int x=0;x<5;x++){
// create the threadable object first
ThreadableObject *obj = new ThreadableObject(x,3,0,&mon);

// create and start the thread the thread
Thread *thread = new Thread(obj);
thread->start();

// see if the thread exits in 10 seconds
thread->join(10000);
}


printf("Ok.n");
getch();

}
catch (ThreadException &e)
{
printf(e.Message.c_str());
}


return 0;
}





görüldüğü gibi irunnable ın abstract run() tanımınıyla uyuşmuyor diyor fakat ben ikisininde parametrelerini aynı yapsamda (ki saçma geldi "class ThreadableObject : public IRunnable" diyerek yeni tanımlara sahip yeni bir class oluşturmuyormuyuz) olmadı :(
ayrıca bu join tam olarak ne yapmaya calısıyor onu da çözemedim bildiğim join processin thread bitene kadar ayakta kalmasını sağlamalı ama çözemedim burdakini.

alternatif olarakda QT librarysini kuramadım kurabilen varsa onu da haalledebilsem çok daha öz bir şekilde halledicem herhalde (yazdım compile edemedim :( )
öhöm. compiler hatasını unutmuşum.

compiler error


In function `int main(int, _TCHAR**)':
cannot allocate an object of type `ThreadableObject'
because the following virtual functions are abstract:
virtual long unsigned int IRunnable::run()






Threadlerle uğraşmışlığım yok hiç o yüzden garip geliyor.
En azından c de uğraşmışlığım yok kim neyi nereye çağırıyo HÖH? diye kaldım :(
Link to comment
Sosyal ağlarda paylaş

Valla c++ ile çok uğraşmadım. Ama anladığım kadarıyla sorun şu: Compiler senin run metodunu implement ettiğini anlamıyor bir şekilde. O yüzden ThreadableObject class'ını da abstract olarak görüyor. Abstract class'tan da instance üretemiyorsun.

Aşağıdaki sorunu çözmezse buraya bak



Metodları class tanımı dışında tanımlamak sorunu düzeltebilir belki. Class tanımı içinde yazınca inline oluyordu galiba. Orda bir aksilik çıkmış olabilir.

Ayrıca küçük bir ihtimal, ama metod imzasının da tıpatıp aynı olması gerekiyor olabilir. Değişkenlerin sırasını da hatada verdiği gibi yazmayı dene.


class ThreadableObject : public IRunnable {
public:
ThreadableObject();
virtual unsigned long run(int id,int hunger,int result,letheM *mon);
protected:
bool _continue;
};


şeklinde class'ı ve interface'ini tanımladıktan sonra altında metodları tanımlarsın. şöyle:


ThreadableObject::ThreadableObject() {
// Constructor tanımı
}

virtual long unsigned int ThreadableObject::run() {
// metod tanımı
}


Umarım bir yararı dokunur.



Edit: Bu arada hatada


virtual long unsigned int IRunnable::run()



yazıyor. Metodda parametre yok. Sen bir sürü parametre koymuşsun. Bu durumda overloading yapıyorsun, override etmiyorsun. O yüzden de abstract kalıyor class'ın büyük ihtimalle.
Link to comment
Sosyal ağlarda paylaş

IRunnable normal bir class değil, interface.

Yani insan class'ından erkek yaratık türetmiyorsun da; ürettiğin erkek yaratık class'ına interface'ler ekleyerek, yaratık class'ını genişletiyorsun. Bu interface'ler ise sana yazman gereken metodları belirliyor.

Yine yaratık örneğinde, iki interface düşün. IKillable ve ITameable. Yarattığın yaratık class'ına bu iki interface'i koyduğun zaman, bunlar sana

void onTamed()
int getTamingDifficulty()
void onDeath()
void afterDeath()

metodlarını implement etmen gerektiğini bildiriyor mesela. Bu metodları doldurmazsan compiler kabul etmiyor class'ını. RunUO'da buna benzer interface'ler var mesela.

Senin durumunda ise yarattığın nesne IRunnable interface'ini implement ettiği için, sana belirtilen run() metodunu implement etmen gerekiyor.
Link to comment
Sosyal ağlarda paylaş

yuh bana :P
new ThreadableObject(x,3,0,&mon); vermmişim parametreleri mainde
sonra gidip run() a koymuşum :D
neyse çalıştı ama süper karmaşa olmuş output birbirine giriyor.
(bu output stream e 2 thread aynı anda yazmaya çalışıyor)
misal "Philosopher Philosopher 10 is eating! is eating".
ve sadece 2 thread çalışıyor o da sorun ama önce şu streami düzeltmek lazım :P
bir fikrin varmı?
neye std:ostream thread safe değilmiş gene lock kullanıcaz :)

lol bana

// Thread.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "Thread.h"
#include "Monitor.h"


// define a threadable object
class ThreadableObject : public IRunnable {
public:
int id;
int hunger;
int result;
letheM *mon;
ThreadableObject(int ida,int hungera,int resulta,letheM *mona) {
_continue = true;

id=ida;
hunger=hungera;
result=resulta;
mon=mona;
}
virtual unsigned long run() {

while(hunger>0){
result=mon->pickup(id);
if (result == 1) {
hunger--;
std::cout<<"Philosopher "<<id<< " is eating!"<<std::endl;
result=mon->putdown(id);
Sleep(500);
}
else {
std::cout<<"Philosopher "<<id<< " is thinking!"<<std::endl;
Sleep(500);
}
}
std::cout<<"Philosopher "<<id<< " has finished eating!"<<std::endl;


return 0;
}
virtual void stop() {
_continue = false;
}
protected:
bool _continue;
};



int _tmain(int argc, _TCHAR* argv[]) {
// example of usage

ThreadableObject *obj=0;
Thread *thread=0;
letheM mon;

try {
for(int x=0;x<5;x++){
// create the threadable object first
ThreadableObject *obj = new ThreadableObject(x,3,0,&mon);

// create and start the thread the thread
Thread *thread = new Thread(obj);
thread->start();

// see if the thread exits in 10 seconds
thread->join(1);
}


printf("Ok.n");
getch();

}
catch (ThreadException &e)
{
printf(e.Message.c_str());
}


return 0;
}


Link to comment
Sosyal ağlarda paylaş

Yanlis anlamadiysam, sadece simulasyonunu yapiyosan, thread kullanmana gerek yok ki. Tamam gercek implementation'da kullanilir ama cok daha basit bi sekilde loop icinde yapabilirsin bunu?

Calisma kismina gelince... Eger output'un oyleyse calismiyodur? 0 hala yerken nasi oluyo da 1 interrupt'la araya giriyo, yiyo, sonra tekrar 0'a donuyo? Sorun zaten 0'in elinde tutmasi catalla bicagi, bu sirada 1'in yemesi imkansiz.
Link to comment
Sosyal ağlarda paylaş

mesela 2 thread aynı anda çalışıyor. (zaten bu sorun multithreading sorunlarını göstermek için)
ilk thread monitöre girdi . çatal bıcak onun.
yazmaya başlıyor
"philosopher 1 is eating"
"philosopher 2 is thinking" ise yiyemeyen in yazdığı.
bunlar aynı anda yazmaya kalkınca output stream e
"philosopher philsopher 12 is eating is thinking" oluyor.
ama monitor sağlam yani fork olarak bi sorunum yok.
(loop da bunu yaparsam dining philosophers la alakam kalmaz ki 1-chair-restaurant-philosophers olur :P)

update:
her cout dan önce lok=1 sonra lok=0. her lok=1 den önce tlock() koydum. tlock() lok=0 olana kadar kendini çağırıyor :P (evet çok kötü ama oturup wait condition m ıyazayım :( )
ve çok güzel göçerttim programı kafasına göre 1 saniyede dönüyor 10 saniyede :D

output lock


// Thread.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "Thread.h"
#include "Monitor.h"


// define a threadable object
class ThreadableObject : public IRunnable {
public:
int id;
int hunger;
int result;
letheM *mon;
int *lok;
ThreadableObject(int ida,int hungera,int resulta,letheM *mona,int *lak) {
_continue = true;

id=ida;
hunger=hungera;
result=resulta;
mon=mona;
lok=lak;
}
virtual unsigned long tlock(){
if(*lok==1)
tlock();
}
virtual unsigned long run() {

while(hunger>0){
result=mon->pickup(id);
if (result == 1) {
hunger--;
tlock();
*lok=1;
std::cout<<"Philosopher "<<id<< " is eating!"<<std::endl;
*lok=0;

result=mon->putdown(id);
Sleep(500);
}
else {
tlock();
*lok=1;
std::cout<<"Philosopher "<<id<< " is thinking!"<<std::endl;
*lok=0;
Sleep(500);
}
}
tlock();
*lok=1;
std::cout<<"Philosopher "<<id<< " has FINISHED eating!"<<std::endl;
*lok=0;


return 0;
}
virtual void stop() {
_continue = false;
}
protected:
bool _continue;
};



int _tmain(int argc, _TCHAR* argv[]) {
// example of usage

ThreadableObject *obj=0;
Thread *thread=0;
letheM mon;
int tlock=0;

try {
for(int x=0;x<5;x++){
// create the threadable object first
ThreadableObject *obj = new ThreadableObject(x,3,0,&mon,&tlock);

// create and start the thread the thread
Thread *thread = new Thread(obj);
thread->start();

// see if the thread exits in 10 seconds
thread->join(1);
}


while(true){}
getch();

}
catch (ThreadException &e)
{
printf(e.Message.c_str());
}


return 0;
}




Link to comment
Sosyal ağlarda paylaş

canim sonucta her phil.'in saginda solunda bicak catal var.
printState dersin, hepsi attempt yapar, her halukarda sadece 1'i alir (2 kisilik oldugunu dusunursek). En kotu ihtimal, hepsi sagindakini alir. Daha sonra print state dersin, kimin naaptigi gozukur.
Deal etmek icin de eger sagdaki varsa, solundakini alamiyosan, elindekini birak dersin, deadlock'tan cikmis olur.

Hala fazla komplike hale getirdigini dusunmekteyim.

Soyle sooliyim, iyi guzel thread'lerin deadlock'a girmesini simule ediyosun da, sonucta thread olarak kullandigin surece deadlock'a girmez ki bu alet... Zaten kendi icinde cozumu var. Bi ust seviyede baslatip thread'in simulasyonunu yapman gerekmiyo mu? Neyse kafani karistirdim ben iyice... kusura bakma
Link to comment
Sosyal ağlarda paylaş

Yapmış olduğun şekilde lok diye bir değişken kullanarak yapamazsın kilidi.


if (result == 1) {
hunger--;
tlock();
*lok=1;
std::cout<<"Philosopher "<<id<< " is eating!"<<std::endl;
*lok=0;

result=mon->putdown(id);
Sleep(500);
}


dediğin yerde


tlock();
*lok=1;


Bu iki satır arasında interrupt girebilir. Sen iki saat beklersin lok 0 olsun diye. Tam 0 olur. Sen *lok=1 yapana kadar diğer thread girer, kilidin işe yaramamış olur.

Bunu engellemenin yolu nesne ve metod kilitleri kullanmak. Programlama dillerinin de bu iş için yöntemleri olur. Javada synchronized metodlar ile yapabilirsin kilit işlerini örneğin. C#'da da farklı bir syntax ile synchronized'ın aynısını yapabiliyorsun. C++'da nasıl oluyor bilmiyorum. Biraz araştır ama bulursun elbet.
Link to comment
Sosyal ağlarda paylaş

yeni elemanımız
std::ostringstream out;
std::string str;
....
constructorda
out << ida;
...
run da outputlar
str ="Philosopher ";
str += out.str();
str +=" is eating!n";
std::cout<

stringler artık birbirlerinin üstüne çıkmıyor her satır için bir kere << çağırdığım için.
neyse hatırladım loopda threadleri yaratıp başlatırken sleep koymazsak tıkanıyor 2.den sonra.
emeği geçenlere teşekkürler
Link to comment
Sosyal ağlarda paylaş

×
×
  • Yeni Oluştur...