LethE Mesaj tarihi: Aralık 3, 2007 Paylaş Mesaj tarihi: Aralık 3, 2007 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ş Daha fazla paylaşım seçeneği…
Mirage Mesaj tarihi: Aralık 3, 2007 Paylaş Mesaj tarihi: Aralık 3, 2007 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ş Daha fazla paylaşım seçeneği…
LethE Mesaj tarihi: Aralık 3, 2007 Konuyu açan Paylaş Mesaj tarihi: Aralık 3, 2007 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ş Daha fazla paylaşım seçeneği…
Mirage Mesaj tarihi: Aralık 3, 2007 Paylaş Mesaj tarihi: Aralık 3, 2007 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ş Daha fazla paylaşım seçeneği…
LethE Mesaj tarihi: Aralık 3, 2007 Konuyu açan Paylaş Mesaj tarihi: Aralık 3, 2007 class ThreadableObject : public IRunnable böyle yapınca kısaca irunnable dan subclass yaratmış olmuyormuyum. hani şey gibi. insan classı ordan ->erkek yarattık. erkek insan yazılabilcek yerlere yazılabiliyor. dediğin gibi deneyeceğim olacak inşallah. Link to comment Sosyal ağlarda paylaş Daha fazla paylaşım seçeneği…
Mirage Mesaj tarihi: Aralık 3, 2007 Paylaş Mesaj tarihi: Aralık 3, 2007 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ş Daha fazla paylaşım seçeneği…
LethE Mesaj tarihi: Aralık 3, 2007 Konuyu açan Paylaş Mesaj tarihi: Aralık 3, 2007 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ş Daha fazla paylaşım seçeneği…
riglous Mesaj tarihi: Aralık 3, 2007 Paylaş Mesaj tarihi: Aralık 3, 2007 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ş Daha fazla paylaşım seçeneği…
LethE Mesaj tarihi: Aralık 3, 2007 Konuyu açan Paylaş Mesaj tarihi: Aralık 3, 2007 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ş Daha fazla paylaşım seçeneği…
riglous Mesaj tarihi: Aralık 3, 2007 Paylaş Mesaj tarihi: Aralık 3, 2007 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ş Daha fazla paylaşım seçeneği…
Mirage Mesaj tarihi: Aralık 3, 2007 Paylaş Mesaj tarihi: Aralık 3, 2007 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ş Daha fazla paylaşım seçeneği…
LethE Mesaj tarihi: Aralık 3, 2007 Konuyu açan Paylaş Mesaj tarihi: Aralık 3, 2007 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ş Daha fazla paylaşım seçeneği…
Öne çıkan mesajlar