Jump to page: 1 2 3
Thread overview
Gelin D tadında bir pizza yapalım...:)
Apr 05, 2012
Salih Dinçer
Apr 06, 2012
Salih Dinçer
Apr 06, 2012
Salih Dinçer
Apr 06, 2012
Salih Dinçer
Apr 09, 2012
zafer
Apr 09, 2012
Salih Dinçer
Apr 09, 2012
zafer
Apr 09, 2012
Salih Dinçer
Apr 09, 2012
zafer
Apr 10, 2012
Salih Dinçer
Apr 10, 2012
Salih Dinçer
Apr 10, 2012
Salih Dinçer
Apr 11, 2012
zafer
Apr 11, 2012
Salih Dinçer
Apr 11, 2012
zafer
Apr 11, 2012
Salih Dinçer
Apr 12, 2012
Salih Dinçer
Apr 14, 2012
Salih Dinçer
Apr 14, 2012
mert
April 06, 2012

Merhaba,

Bugün cuma bereketine, daha önce başladığım bir uygulamayı geliştirmeyi hedefledim. Ancak şirketimiz iflas ediyor! Çünkü gelen siparişleri henüz değerlendiremediği gibi çırağın hazırladığı deneme hamuru fırına verilmeden gaz bitiyor ve fırın soğuyor. Sonuçta çırağa 1 TL maaş kalıyor...:)

'siparişVar_mı()' işlevi kısmen hazır ama sanırım sistemi tam iyi otutturamadım. Yani çeşitli hileler ile JSON dosyasını değiştirdiğimde uyanmasını ve sipariş föyünü doldurmasını sağlıyorum. Ancak bu işlev o kadar hevesli ki HEDEF = 100'ü tutturmak için başlangıçtaki tüm siparişleri işlemek istiyor. Tabi bir de 'malzemeDiz()' ve 'fırınaVer()' işlevlerine ihtiyacı var. Ayrıca 'malzemeAl()' ve 'teslimEt()' işlevleri de çok önemli. Çünkü:

  • Siparişi teslim edemezsek para kazanamayız,
  • Para kazanmazsak yeni malzeme alamayız,
  • Yeni malzeme alamazsak siparişlere cevap veremeyiz ve

'İFLAS:' şirketi kapatırız...

/*
   pizzaDlang2.d (06.04.2012)
*/
import std.datetime, std.stdio;
import std.conv, std.file, std.json;
import std.concurrency, core.thread;

   immutable _x_HIZ    = 16;   // xKat

   immutable SERMAYE   = 1000; // Türk Lirası
   immutable HEDEF     = 100; // adet sipariş

   immutable veriDosyası = "pizzaDlang.json";
   immutable kaynakDüğüm = "Siparişler";

   JSONValue[] dosyadanJSONdizi(string dosya, string dizi)
   {
       string veriyiOku = to!string(read(dosya));

       JSONValue[] JSON = parseJSON(veriyiOku).object[dizi].array;

       return JSON;
   }
   enum Hamuru { ince, orta, kalın }
   enum Malzemesi { peynir, sucuk, mantar }

   shared struct SİPARİŞLER {
       static size_t numarası;
       static int[HEDEF] bilgileri;
   }

   shared struct VARLIKLAR {
       int un, su, yağ, ketçap, peynir, sucuk, mantar;
       int gaz, ısı, kasa = SERMAYE;

       this (int m1, int m2, int m3, int m4, int m5, int m6, int m7,
                                       int gaz, int ısı, int masraf) {
           this.un += m1;
           this.su += m2;
           this.yağ += m3;
           this.ketçap += m4;
           this.peynir += m5;
           this.sucuk += m6;
           this.mantar += m7;
           this.gaz += gaz;
           this.ısı += ısı;
           this.kasa -= masraf;
       }
       void Durumu() {
           writef("\tUn %d, Su %d, Yağ %d, Gaz %d, Fırın %d °C\n", un, su, yağ,
                                                                     gaz, ısı);
       }
       void malzemeAl(int xMalzeme) { kasa -= xMalzeme * 10; }
       void teslimEt(int xSipariş) { kasa += 15; }
   }
.
   void hamuraBaşla(Tid durum, shared(VARLIKLAR) * malzeme, Hamuru kalınlık) {
       for(auto i=0;
           i < 10 + kalınlık;
           i++, malzeme.un -= 3, malzeme.su -= 2, malzeme.yağ -= 1)
       {
           if(malzeme.un < 1 || malzeme.su < 1 || malzeme.yağ < 1)
           {
               durum.send(0);
               break;
           }
           durum.send(4);  // boşta
           Thread.sleep(dur!"seconds"(i*i/_x_HIZ));
           durum.send(1);
       }
       durum.send(3);  // hamur hazır
   }

   void fırınıYak(Tid durum, shared(VARLIKLAR) * malzeme, ubyte derece) {
       uint soğumaZamanı = 6;

       while (true)
       {
           if(malzeme.gaz > 0 && malzeme.ısı != derece)
           {
               malzeme.gaz--;
               malzeme.ısı++;
           } else durum.send(5);
           Thread.sleep(dur!"msecs"(soğumaZamanı/_x_HIZ));
           durum.send(6);  // boşta
           if(++soğumaZamanı % 6 == 0)
           {
               if(malzeme.ısı > 19) malzeme.ısı -= 5; else
               {
                   durum.send(0);
                   break;
               }
           }
       }
   }

   void siparişVar_mı(Tid durum, shared(VARLIKLAR) * malzeme, int performans) {
       JSONValue[] siparişler;
       size_t siparişNumarası, müşteriNumarası, xSipariş = 0;
       SİPARİŞLER[HEDEF] sipariş;   // auto sipariş = new SİPARİŞLER();

       sipariş[xSipariş].numarası = size_t.max;
//* TEST 1
writefln("t-> %d/%d", sipariş[xSipariş].numarası, siparişNumarası); //*/
       do {
           siparişler = dosyadanJSONdizi(veriDosyası, kaynakDüğüm);

           siparişNumarası = siparişler[xSipariş + 1].object["nm"].integer;
           müşteriNumarası = siparişler[xSipariş + 1].object["ad"].integer;
//* TEST 2
writefln("t-> %d-%d", sipariş[xSipariş].numarası, siparişNumarası); //*/
           if(sipariş[xSipariş].numarası != siparişNumarası)
           {
               sipariş[++xSipariş].numarası = siparişNumarası;
               sipariş[xSipariş].bilgileri[0] = cast(int)müşteriNumarası;
//* TEST 3
writefln("t-> %d\\%d", sipariş[xSipariş].numarası, siparişNumarası); //*/
               foreach (i, ml; siparişler[xSipariş].object["ml"].array)
               {
                   sipariş[xSipariş].bilgileri[i + 1] = cast(int) ml.integer;
//* TEST 4
writefln("t-> ml[%d][%d]", xSipariş, ml.integer); //*/
               }
               durum.send(2);  // siparişler var
           } else durum.send(1);  // sipariş yok
           // Sipariş sorumlusunun ve/veya şirketin performansı:
           Thread.sleep(dur!"msecs"(performans));
           durum.send(1);  // sipariş yok
       } while (xSipariş < HEDEF);
       durum.send(0);
   }

void main() {
   writeln("pizza Dlang (kuruluş 2012)");
   writeln("==========================");
                                 // un, su, yağ, ketçap, peynir, sucuk, mantar
   shared auto malzeme = VARLIKLAR (100, 100, 100, 100, 100, 100, 100,
                                                        999, 45, 999);
   size_t xDurum = 1;                               // gaz, ısı, kasa (-masraf)

   writefln("Şirket %d sermayeyle kuruldu...", SERMAYE);

   spawn(&hamuraBaşla, thisTid, &malzeme, Hamuru.kalın);
   spawn(&fırınıYak, thisTid, &malzeme, cast(ubyte)180);

   spawn(&siparişVar_mı, thisTid, &malzeme, 100); // ÜZERİNDE ÇALIŞILACAK !!!

   writeln("\nVARLIKLAR:");
   while(xDurum)
   {
       xDurum = receiveOnly!size_t();
       if(xDurum == 1) malzeme.Durumu();
       else if(xDurum == 3) writefln("\t\t(HAMUR HAZIR)");
       else if(xDurum == 5) writefln("\t\t(FIRIN HAZIR) Gaz %d, Fırın %d °C",
                                                  malzeme.gaz, malzeme.ısı);
   }
   writefln("Malzeme bitti !!! (Kasada %d TL var)", malzeme.kasa);
   writefln("İflas ettik...:)");
}/*
   - sipariş[x].bilgileri[0] => xDurum     (durum.send)
   - sipariş[x].bilgileri[1] => xMüşteri   (müşteriNumarası)
   - sipariş[x].bilgileri[2] => Malzemesi.peynir
   - sipariş[x].bilgileri[3] => Malzemesi.sucuk
   - sipariş[x].bilgileri[4] => Malzemesi.mantar
   - Un 67, Su 78, Yağ 89 (kalın hamurlu pizza)
   - Un 70, Su 80, Yağ 90 (orta hamurlu pizza)
   - Un 73, Su 82, Yağ 91 (ince hamurlu pizza)
   - xDurum > 0 (kontrollü çalışmaya devam et)
   - xDurum 1 => sipariş yok
   - xDurum 2 => siparişler var
   - xDurum 3 => hamur hazır
   - xDurum 4 => boşta
   - xDurum 5 => fırın hazır
   - xDurum 6 => boşta
string pizzaDlang.json = '
{
   "belge" : "Pizza Siparişleri",
   "türü"  : "ham-UTF8",
   "Siparişler" : [{
           "nm" : 1,
           "ad" : 1,
           "ml" : [90, 100]
       }, {
           "nm" : 2,
           "ad" : 1,
           "ml" : [90, 100]
       }, {
           "nm" : 3,
           "ad" : 2,
           "ml" : [50, 60, 70]
   }]
}';
*/

Başarılar...

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

April 06, 2012

Yorumların için teşekkürler; doğru tahminlerin içinde...:)

Korkarım, dillerdeki "type inference" özellikleri zamanla gelişse de senin doğru tahminlerin kadar hiç bir zaman olamayacaklar. Biz programcıları hep bu türler kısıtlamakta. Ne integer gerçekten tam sayılar kümesini temsil ediyor ne de long veya cent gibi değişkenler yeterince büyükler. Gün gelecek bütün bunlar da yetmeyecek. Bence hala programlama dilleri çok aptal. Her biri akıllı olmak için karmaşıklaşıyorlar ama sonra dilin tüm özelliklerini kullanan senin gibi akıllı insanlar azalınca bir çok şeyi emekliye ayırıyorlar veya Scala gibi yeni bir dil ortaya çıkıyor.

Örneğin Scala'da public ve default dışında çok fazla kafa karıştırıcı keyword yok. Süslü parantezler ve satır sonu noktalı virgüller bile yok. Oysa bugün dillere bakıyorumda aklıma geldiği sırayla yazarsak static, shared, protected, private, public vb. bir sürü şeyle dolu...:)

Alıntı (acehreli):

>

...Yani iş parçacıklarının içine ortaklaşa bakıp değiştirdikleri bir dizi yoktur ve gereken bilgi ana iş parçacığından dağıtılır.

hamuraBaşla() ve fırınıYak() gibi iş parçacıklarının sorunları, aynı 'malzeme' nesnesi üzerinde değişiklik yapıyor olmaları. Eninde sonunda okuma ve yazma karışıklıkları oluşacaktır.

Örneğin değeri 42 olan aynı değişkeni birisi ++i yapacak diğeri --i yapacak. Sonuçta değerin 42 olarak kalması gerekirken hangisi son yazmışsa onun değeri kalır. Yani ikisi de 42 olarak okurlar, birisi 43 değerini üretir diğeri de 41. Sonra i'ye yeni değerini yazarken son yazan kazanır ve i ya 43 olur ya da 41.

Bu gibi sorunların önüne geçmek için synchronized anahtar sözcüğü kullanılabiliyor ama yine de çok belalıdır. O yüzden en iyisi 'malzeme'de yaşanan veri paylaşımını önlemektir.
Senin söylediğin daha mantıklı görünüyor. Çünkü ileride aynı anda pizzalar pişecek ve belki siparişleri yetiştirebilmek için bir hamurcu ustası daha alacağız...:)

Gerçi her şey eksiye gidiyor ve malzeme deposu ortak ve yeni ürün alımı yapılmadığında herşey eksiliyor. Isının yükseldiği de tek bir fırın var. Belki de sorun olmaz bilemiyorum. Aslında bu kadar çok ayrıntıya kafa yormak da istemiyorum. Benim tek istediğim şu:

Teknik açıdan iki program (master ve slave) olacak ve master siparişi veren ayrı bir derlenmiş D programcığı olacak. Bu iki program JSON ile haberleşecek. Aslında socket programming yapabilsek daha leziz olur ya. Neyse slave ise siparişi alacak ve pizza üretecek. Üretirken de kendi için bağımsız programları (thread) oluşturucak. Onlar kendi başlarına özgürce (malzeme bitmedikçe) harıl harıl çalışacaklar. Sanırım hedefe çok uzak değiliz, ne dersiniz?

Sevgiler, saygılar...

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

April 06, 2012

Alıntı (acehreli):

>

Derleme hatası aldım. Benim Makefile'da en son -m32 seçeneği kaldığı içinmiş.
Doğrudur, bir süredir 64 bit sistem üzerinde çalıştığım için -m32'yi ihmal ediyorum. Aslında artık size_t kullanmayacağım. Kendisine çok cins olmaya başladım...:)

Alıntı (acehreli):

>

Ben SERMAYE ve veriDosyası gibi derleme zamanında bilinen sabitleri artık enum olarak tanımlıyorum. Bu konudaki fikirlerim çok yakın zaman önce oturdu.
Vallahi immutable olayını kafama sokan kim acaba...:)

Onu oradan çıkartıp senelerin enum'u sokmak zor olacak ama deneyeceğim. Gerçi sıklıkla enum kümeleri kullanıyorum. Kelimeleri güzel seçince gerçeken hoş duruyorlar. Bir de if() kullanmadan enum'ları ters kullanabilsek; acaba mümkün mü? Yani ben 1 değerini verdiğimde kümedeki ikinci değeri, yani 1'e eşitlenmiş enum'u verse. Bir de D'de önemli bir eksilik var ki o da INC (veya DEC) enum yaptığımızda (örn. cast(Hamuru) hamur++) eğer son elemandaysa baştaki elemanın değerini döndüreceğine, son elemanın değerini bir arttırıyor. Belki de ben yanlış bir şey yapıyorumdur.

Not: enum adaylarına bir çeki düzen vereceğim...

Alıntı (acehreli):

>

Salih'in kısa kod yazmayı sevdiğini biliyorum ama bu tam bir tuzak olmuş: :)

>                 if(malzeme.ısı > 19) malzeme.ısı -= 5; else
>                 {
>                     durum.send(0);
>                     break;
>                 }
> ```

Hem de nasıl...:)

N'apayım, kodu ben yazdığım için gözümden iki satırı silmek hoşuma gidiyor ve else'ye yoğunlaşıyorum. Çünkü biliyorum ki orası ısıyı düşürüyor ve önemli olan oda sıcaklığına eriştiğimizde ne yapmam gerektiği. Yani kendimce bir scope yapıyorum. Hadi buna "private scope" diyelim...:)

Alıntı (acehreli):
> SİPARİŞLER yapısının ismi sanki SİPARİŞ olmalı ve 'sipariş' değişkeninin ismi sanki 'siparişler' olmalı. Belki de onu tam olarak anlamadığım için öyle düşünüyorumdur. HEDEF adetlik sipariş var ama her birisinin içinde de HEDEF adet bilgi var. Neden HEDEF çarpı HEDEF bilgi gerektiğini anlamadım.
SİPARİŞLER yapısının ikinci elemanını dinamik dizi yapmak istedim. Ama henüz bu kavrama alışık olmadığım için static'e çevirdim. Ancak anlayamadığım bir sebepten (gerçi bunu dersinde belirtmişsin; sonradan okudum) dinamik diziye JSON'dan gelen verileri yerleştiremiyordum. Hiç bir run-time error vermediği gibi orası yokmuş gibi çalışmaya devam ediyordu. Mecburen böyle bir şey yapıp sonra bakmak üzere geçici bir çözüm ürettim.

-- 
[ Bu gönderi, <http://ddili.org/forum>'dan dönüştürülmüştür. ]
April 06, 2012

Çok güzel! Canlı bir program olmuş; kendi başına bir şeyler yapıyor! :)

  1. Derleme hatası aldım. Benim Makefile'da en son -m32 seçeneği kaldığı içinmiş. 32 bit derlerken size_t 32 bitlik olduğu için ama long her zaman için 64 bitlik olduğu için şurada türler uyuşmadı:
           siparişNumarası = siparişler[xSipariş + 1].object["nm"].integer;
           müşteriNumarası = siparişler[xSipariş + 1].object["ad"].integer;

Sağ tarafların başlarına 'cast(size_t)' yazınca derlendi.

Tabii buradaki sorun json'un .integer'ının long olmasından kaynaklanıyor. Daha küçük bir türe dönüştürürken cast kullanmanın gerekmesi doğal. size_t'nin sorunu tam büyüklüğünün derlendiği zamanki ortama bağlı olması ve long'dan daha küçük olabilmesi.

Bunları yazarken bir programcı olarak suçluluk da duyuyorum :) ama size_t olmazsa da olmuyor. C'de ve C++'ta da bulunan sorunlar bunlar...

  1. -m32 ile yukarıdaki gibi derledikten sonra program bir hata ile sonlandı:

'std.concurrency.MessageMismatch@std/concurrency.d(235): Unexpected message type'

Onun da nedeni size_t. receiveOnly yalnızca size_t istiyor ama bütün send()'ler int gönderiyorlar. int alınca çalıştı:

       xDurum = receiveOnly!int();

Daha genel olarak int alan bir temsilci ve receive() ile de çalışır:

       // xDurum = receiveOnly!size_t();
       receive((int durum) { xDurum = durum; });

Ve denedim; 64 bitte de doğru çalışıyor.

  1. Bundan sonrakiler kodla ilgili çoğu önemsiz gözlemler. Hatta kodun eksik olduğunu da söylemiştin zaten... Buna rağmen... :)
  • Ben SERMAYE ve veriDosyası gibi derleme zamanında bilinen sabitleri artık enum olarak tanımlıyorum. Bu konudaki fikirlerim çok yakın zaman önce oturdu.

  • Kod genelde gerçekten çok hoş. :) Hamuru ve Malzemesi özellikle noktayla kullanılırken çok okunaklı oluyorlar. Tabii şu açıklamalar da enum olmak için can atıyorlar: ;)

/*    - xDurum > 0 (kontrollü çalışmaya devam et)
   - xDurum 1 => sipariş yok
   - xDurum 2 => siparişler var
   - xDurum 3 => hamur hazır
   - xDurum 4 => boşta
   - xDurum 5 => fırın hazır
   - xDurum 6 => boşta
*/
  • SİPARİŞLER yapısının ismi sanki SİPARİŞ olmalı ve 'sipariş' değişkeninin ismi sanki 'siparişler' olmalı. Belki de onu tam olarak anlamadığım için öyle düşünüyorumdur. HEDEF adetlik sipariş var ama her birisinin içinde de HEDEF adet bilgi var. Neden HEDEF çarpı HEDEF bilgi gerektiğini anlamadım.

  • VARLIKLAR'ın üyelerinden bazıları birbirleriyle yakından ilgili görünmüyorlar. Bölmek daha yararlı olabilir.

  • Bu tamamen kişisel tercih ama ben post-increment ve post-decrement yazımlarına hiç alışamayacağım: :)

               malzeme.ısı++;

Benim tercihim:

               ++malzeme.ısı;
  • Salih'in kısa kod yazmayı sevdiğini biliyorum ama bu tam bir tuzak olmuş: :)
               if(malzeme.ısı > 19) malzeme.ısı -= 5; else
               {
                   durum.send(0);
                   break;
               }

else farkedilene kadar bloğun if koşuluna bağlı olduğu sanılıyor. else'i görmemek zor belki ama yine de else'in nerede olduğuna bağlı olarak beynimizde sürekli anlam kaydırmaları gerekiyor. Çünkü hemen üstünde de şu var:

           if(malzeme.gaz > 0 && malzeme.ısı != derece)
           {
               malzeme.gaz--;
               malzeme.ısı++;
           } else durum.send(5);

Oraki kod bloğu ise if'in koşuluna bağlı!

Kodun tutarlılığı çok önemli. Çalıştığım yerde biz aşağıdaki yazım standardını kullanıyoruz:

           if(malzeme.gaz > 0 && malzeme.ısı != derece) {
               --malzeme.gaz;
               ++malzeme.ısı;

           } else {
               durum.send(5);
           }
// ...
               if(malzeme.ısı > 19) {
                   malzeme.ısı -= 5;

               } else {
                   durum.send(0);
                   break;
               }
  • Daha geliştireceğini söylüyorsun zaten ama mesajlaşma konusunda aklıma gelenler şöyle:

shared ile veri paylaşımı yerine ana iş parçacıklarından sipariş göndermek daha temiz ve güvenli olur. Örneğin bir iş parçacığı yalnızca sipariş alır ve ana iş parçacığına bir Sipariş nesnesi gönderir. Ana iş parçacığı da malzemeler arasından o siparişe uygun miktarda malzeme çıkartır ve bu malzemeleri ve siparişi bir aşçı iş parçacığına verir. Aşçı iş parçacığı da tekrar ana iş parçacığına bir Pizza nesnesi gönderir. Sonra ana iş parçacığı garson iş parçacığına bu pizzayı verir. vs. Yani iş parçacıklarının içine ortaklaşa bakıp değiştirdikleri bir dizi yoktur ve gereken bilgi ana iş parçacığından dağıtılır.

hamuraBaşla() ve fırınıYak() gibi iş parçacıklarının sorunları, aynı 'malzeme' nesnesi üzerinde değişiklik yapıyor olmaları. Eninde sonunda okuma ve yazma karışıklıkları oluşacaktır.

Örneğin değeri 42 olan aynı değişkeni birisi ++i yapacak diğeri --i yapacak. Sonuçta değerin 42 olarak kalması gerekirken hangisi son yazmışsa onun değeri kalır. Yani ikisi de 42 olarak okurlar, birisi 43 değerini üretir diğeri de 41. Sonra i'ye yeni değerini yazarken son yazan kazanır ve i ya 43 olur ya da 41.

Bu gibi sorunların önüne geçmek için synchronized anahtar sözcüğü kullanılabiliyor ama yine de çok belalıdır. O yüzden en iyisi 'malzeme'de yaşanan veri paylaşımını önlemektir.

  • Sanıyorum nm "numara" ve ml de "malzeme listesi" anlamına geliyor. (?) ;)

Ama dediğim gibi, program benim çok hoşuma gitti.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

April 06, 2012

Merhaba,

Henüz pizza yapmayı öğrenmeden (Master<->JSON<->Slave iletişimine geçmeden) ekmek yapmayı (thread'ların davranışlarını) tam anlamıyla öğrenmem gerektiğini düşünüyorum! Belki daha 10 fırın ekmek yemek gerekiyor ki bu fırında henüz tek fırın var olduğu düşünülürse sanırım çok hızlı gitme hevesliliğini dizginlemeliyim...:)

Bu sabah aşağıdaki (test yazılımı ekmekYap.d) ile koşmadan (şirketi açmadan) evvel emeklemeyi öğrenebileceğimi düşündüm. Her ekmek yapıldığında yeni bir thread oluşturmakla yetinmeyip patronu kovdum ve müdür olarak bir süreliğine fırıncıyı atadım. O da 5 ekmeğe kadar dayanabildi ve kendi işine bakmaya devam**'*'** etti.
'***** (Fırın soğumadan şirket kapanıyor; yani thread_fırınYak düzgün çalışmıyor ki bunu harcadığı gazın azlığından anlıyorum...)'

import std.concurrency, core.thread, std.stdio;

   immutable int _x_HIZ = 32;              // xKat
   immutable int milyar = 1_000_000_000;   // 1 milyar birim

   enum Hamuru {
                   ince = 1,
                   orta,
                   kalın
   } /* Bir ekmek için =>
       - Un 120, Su 60, Yağ 90, Tuz 30 (kalın hamurlusunda)
       - Un 80, Su 40, Yağ 60, Tuz 20 (orta hamurlusunda)
       - Un 40, Su 20, Yağ 30, Tuz 10 (ince hamurlusunda)
   */
   shared struct Kiler {
       int un, su, yağ, tuz, ekmek;

       this (int _un, int _su, int _yağ, int _tuz)
       {
           this.un += _un;
           this.su += _su;
           this.yağ += _yağ;
           this.tuz += _tuz;
       }

       void Durumu() {
           writefln("[Un %d, Su %d, Yağ %d, Tuz %d]: Ekmek = %d",
                                         un, su, yağ, tuz, ekmek);
       }
   }

   shared struct Fırın {
       int gaz;
       ubyte ısı;

       this (ulong _gaz, ubyte _ısı)
       {
           this.gaz += _gaz;
           this.ısı += _ısı;
       }
   }

   void ekmekYap(Tid durum, shared(Kiler) * kiler, Hamuru kalınlık)
   {
       for(auto i = 0;
           i < 10 * kalınlık;
           i++, kiler.un -= 4, kiler.su -= 2,
                kiler.yağ -= 3, kiler.tuz -= 1)
       {
           if(kiler.un < 1 || kiler.su < 1 ||
              kiler.yağ < 1 || kiler.tuz < 1)
           {
               durum.send(0);
               break;
           }
           durum.send(2);  // bekleme
           Thread.sleep(dur!"seconds"(i*i/_x_HIZ));
           durum.send(1);  // yazdırma
       }
       durum.send(3);
   }

   void fırınYak(Tid durum, shared(Fırın) * fırın, ubyte derece) {
       uint soğumaZamanı = 6;

       while (true)
       {
           if(fırın.gaz > 0 && fırın.ısı != derece)
           {
               fırın.gaz--;
               fırın.ısı++;
           } else {
               durum.send(5);
           }
           Thread.sleep(dur!"msecs"(soğumaZamanı/_x_HIZ));
           durum.send(4);
           if(++soğumaZamanı % 6 == 0)
           {
               if(fırın.ısı > 19)
               {
                   fırın.ısı -= 5;
               } else {
                   durum.send(0);
                   writeln("Fırın oda sıcaklığına geldiği için şirketi kapa!");
                   writefln("- Harcanan Gaz: %d", milyar - fırın.gaz);
                   break;

               }
           }
       }
   }

void main() {
   shared auto kiler = Kiler(milyar, milyar, milyar, milyar);
   shared auto fırın = Fırın(milyar, 19);

   Hamuru ekmekÇeşiti = Hamuru.ince;

   spawn(&ekmekYap, thisTid, &kiler, ekmekÇeşiti);
   spawn(&fırınYak, thisTid, &fırın, cast(ubyte)250);

   int xDurum = 1;
   while(xDurum)
   {
       xDurum = receiveOnly!int();
       if(xDurum == 1) kiler.Durumu();
       else if(xDurum == 3)
       {
           kiler.ekmek++;
           if (kiler.ekmek == 100) break;
           spawn(&ekmekYap, thisTid, &kiler, ekmekÇeşiti);
       }
       else if(xDurum == 5 && kiler.ekmek < 5)
       {
           writefln("\t(FIRIN HAZIR) Gaz %d, Fırın %d °C",
                                     fırın.gaz, fırın.ısı);
           spawn(&ekmekYap, thisTid, &kiler, ekmekÇeşiti);
       }
   }
   writefln("- Harcanan Tuz: %d", milyar - kiler.tuz);
   writefln("Hala fırın çalışıyor ve şu an %d °C sıcaklığında;", fırın.ısı);
}/*
[Un 999959784, Su 999979892, Yağ 999969838, Tuz 999989946]: Ekmek = 999
- Harcanan Tuz: 10054
[Un 999995820, Su 999997910, Yağ 999996865, Tuz 999998955]: Ekmek = 99
- Harcanan Tuz: 1045
[Un 999999428, Su 999999714, Yağ 999999571, Tuz 999999857]: Ekmek = 9
- Harcanan Tuz: 143
*/

Komiktir, aşağıdaki dip notu "uyuşmayabilir!" diye bitirmişim. Sanırım değerler de uyuşmuyor ve ben henüz bunun neden olduğunu anlayamadım. Belki Ali hocamın işaret ettiği gibi baş belası bir durum. Aslında fırıncı patronluk vazifesini yaparken (5 ekmek üretilene kadar) sanırım 30-40 thread oluşturuyor olmalı. Yani 100 ekmek için 1000 değil de 1045 birim tuz harcamasına etkisinin olmaması gerekiyordu. Ama her seferinde yaklaşık %5'lik hata payı var ki değer olarak hep aynı. Zamanı hızlandırma (tam sayıları böldüğümüzde küsüratlı bir şekilde ifade edememiz) ile alakalı olabilir. Çünkü hız değişliklerinde değerlerde aşırı sapma var!

Bir de programın gerçekten sonlanması (konsola düşmesi) azıcık daha vakit alıyor! Tamam fırın en geç sonlanan olduğu için böyle ama neden ekrana yazılan değerler (log'lar) düştüğünde işlevden kuramsal açıdan çıkmasın! Bir şeyler karışıyor ama dediğim gibi henüz anlayamadım. Gerçi anladığım bir şey var o da patronluğu fırıncı devir aldığında (durum == 5'de thread kurulduğunda) program sonlanmasına kadar ekmeler 7'şer 7'şer üretilmekte ama 64x'de patron dükkandan çıkamadığı için değerlerde sapıtma yok ki karmaşık durumlarda, thread'lerin kimliklerini (Tid) ve terminate durumlarını sorgulamamız anlamına gelebilir.

Dip Not: Çok fazla beklemekten sıkılırsanız 64x hoşunuza gidebilir. Ama siz yine de bunu kullanmayın çünkü hata payını gerçekçi hesaplayabilmek için kiler.ekmek < 5 yaptığımdan test sonuçlarımız uyuşmayabilir.

Başarılar...

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

April 06, 2012

Alıntı (Salih Dinçer):

>

Ne integer gerçekten tam sayılar kümesini temsil ediyor ne de long veya cent gibi değişkenler yeterince büyükler. Gün gelecek bütün bunlar da yetmeyecek.

Tamsayıları sonsuz basamaktan oluşan diller var. D'de de BigInt kullanılabilir. Sorun, o türlerin mikro işlemci tarafından desteklenmemeleri. Hız önemli olmadığı sürece bir BigInt türü kullanılabilir. Hatta başka dil de kullanılabilir. ;)

Alıntı:

>

Gerçi her şey eksiye gidiyor ve malzeme deposu ortak ve yeni ürün alımı yapılmadığında herşey eksiliyor. Isının yükseldiği de tek bir fırın var. Belki de sorun olmaz bilemiyorum.

Şu anda sorun olmayabilir. Ama eksiye götüren iki iş parçacığı olduğu zaman bu sefer de 42'nin 40'a inmesi gerekirken 41'e inmiş olabilir.

Veri paylaşımına dayalaı geleneksel multithreaded programlama vebalıymış gibi kaçınılması gereken bir yöntemdir. Ortaya çıkan sorunların sonu gelmez. Veri paylaşımının bazı sorunlarını şurada "Veri paylaşmak için shared" başlığı altında göstermişim:

http://ddili.org/ders/d/es_zamanli.html

Orada bir de BankaHesabı örneğine bakmanızı öneririm. O da programın takılıp kaldığı çok tanıdık bir örneği gösterir.

Alıntı:

>

Teknik açıdan iki program (master ve slave) olacak ve master siparişi veren ayrı bir derlenmiş D programcığı olacak. Bu iki program JSON ile haberleşecek.

O güzel çünkü farklı programlar olunca aynı verinin paylaşımı söz konusu olmuyor. Veri ancak mesajlaşarak iletiliyor.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

April 06, 2012

Alıntı (Salih Dinçer):

>

Onu oradan çıkartıp senelerin enum'u sokmak zor olacak ama deneyeceğim.

enum olarak tanımlanan değişkenler senelerin enum'undan farklılar çünkü bir enum türu oluşturmuyorlar. Bu kullanımda enum, C'de #define ile tanımlanan sabit değerlerin yerine geçiyor:

   enum SERMAYE   = 1000;

Alıntı:

>

Yani ben 1 değerini verdiğimde kümedeki ikinci değeri, yani 1'e eşitlenmiş enum'u verse.

O fazla tehlikeli kabul ediliyor. Her tamsayının enum değer karşılığı bulunmadığı için çalışma zamanında arama yapılması gerekir. Çözümü tür dönüşümü:

   enum E { yazı, tura }
   E e = cast(E)1;
   assert(e == E.tura);

Alıntı:

>

Bir de D'de önemli bir eksilik var ki o da INC (veya DEC) enum yaptığımızda (örn. cast(Hamuru) hamur++) eğer son elemandaysa baştaki elemanın değerini döndüreceğine, son elemanın değerini bir arttırıyor.

Onu bazen ben de istiyorum ama herhalde fazla özel bir davranış olarak görüyor olmalılar. Ne yazık ki kendimiz yapmak zorundayız. Bazen şu yeterli oluyor:

   import std.traits;

   foreach (e; (__traits(allMembers, E))) {
       writeln(e);
   }

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

April 09, 2012

Bu tür örnekleri seviyorum. Hem sorunu daha somut hale getiriyor hemde öğrenmesi ve kavramlar üzerinde tartışılması daha kolay olur. Ayrıca benimde çok hoşuma gitti. Cuma günü ilk gördüğümde ilgilenmek istedim ama yoğunluktan bu güne kaldı. En son eklediğin kod üzerinde biraz inceleme yaptım. main için aklıma takılanlar şunlar;

void main()
{
   shared auto kiler = Kiler(milyar, milyar, milyar, milyar);
   shared auto fırın = Fırın(milyar, 19);

   Hamuru ekmekÇeşiti = Hamuru.ince;

   // Fırın daha hazır olmadan ekmek yaomak doğrumu? Ayrıca biz piza yapmıyor muyuz?
   spawn(&ekmekYap, thisTid, &kiler, ekmekÇeşiti);

   spawn(&fırınYak, thisTid, &fırın, cast(ubyte)250);

   int xDurum = 1;
   while(xDurum)
   {
       xDurum = receiveOnly!int();

       if(xDurum == 1)
       {
           kiler.Durumu();
       }
       else if(xDurum == 3)
       {
           kiler.ekmek++;
           if (kiler.ekmek == 100) break;
           spawn(&ekmekYap, thisTid, &kiler, ekmekÇeşiti);
       }
       else if(xDurum == 5 && kiler.ekmek < 5)
       {
           writefln("\t(FIRIN HAZIR) Gaz %d, Fırın %d °C",
                                     fırın.gaz, fırın.ısı);
           spawn(&ekmekYap, thisTid, &kiler, ekmekÇeşiti);
       }

       // Fırın durumunu kontrol etmek için fırının hazır durumu geldiği anda programı durdurdum.
       if (xDurum == 5 || xDurum == 0)
       {
           writefln("xDurum : %s", xDurum);
           system("PAUSE");
       }
   }

Burada döngüden önce yani fırın yanmadan önce ekmek olayına başlamışız bu doğru mu?

Ayrıca döngü içinde fırın hazır olduğunda ekranda 4 tane ekmek (piza) hazırlanmıştı sanırım burada da bir sorun var yada olayı ben tam anlamadım?

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

April 09, 2012

Az önce, şuradaki (http://forum.dlang.org/thread/914242.19794.qm@web33606.mail.mud.yahoo.com) tartışmayı (std.concurrency'nin doğuşunu) okudum ve ilk sürümlerden biri olan aşağıdaki sınıfı denemeye çalıştım:

http://www.invisibleduck.org/sean/src/concurrency.d

Tabi başarılı olamadım çünkü eski bir sınıf olduğu için bir çok yerine el atılması gerekiyordu. Ben de D2'nin hangi sürümüyle uyumlu olduğunu öğrenmeye çalıştım. Aslında teorik olarak 2.048 (8 Ağustos 2010) sürümünde çalışması gerekiyordu ama şu hatayı verdi:
Alıntı:

>

std\format.d(306): Error: cannot implicitly convert expression (& arg) of type shared(int)* to const(void)*

Ayrıca 2.051 sürümü de dahil arada kalanlarda ise "dur!: duration" hatası veriyor ki yazdığım programın (ekmekYap.d) core.thread ile de uyumsuzluğu anlamına geliyordu. Bende denemelerimi son bir seneki sürümler üzerine odakladım...:)

İlk dikkatimi çeken derleme boyutlarındaki ciddi farklılık oldu. Aslında bu doğal olabilir çünkü geçen sene DMD linker ve runtime kısmında epey bir düzeltme yapmış. Ama 2.056 sürümünde 4 kata çıkması çok ilginç görünüyor. Ben de diğer dış kaynaklı hatalardan emin olmak için testi daha kararlı olduğunu düşündüğümden'*****' lisanslı Windows7-32 bit platformunda yaptım. Özetle aşağıda göreceğiniz üzere binary dosyaların çoğu şu an ki sürüme göre en az iki kat daha büyük boyutlarda oluşuyor. Asıl önemli olan da, yeni DMD sürümlerine göre daha kararlı çalışmalarıydı, hatta yukarıdaki kod tam da istediğim gibi çoğunda doğru çalıştı:

Alıntı:

>
  • Harcanan Tuz: 1000 (2.052)
    09.04.2012 15:10 541.212 ekmekYap.exe

  • Harcanan Tuz: 1000 (2.053)
    09.04.2012 15:19 536.604 ekmekYap.exe

  • Harcanan Tuz: 1000 (2.054)
    09.04.2012 15:30 507.420 ekmekYap.exe

  • Harcanan Tuz: 1000 (2.055)
    09.04.2012 15:42 549.916 ekmekYap.exe

  • Harcanan Tuz: 1000 (2.056)
    09.04.2012 15:51 1.108.508 ekmekYap.exe

  • Harcanan Tuz: 1024 (2.057)
    09.04.2012 15:57 890.908 ekmekYap.exe

  • Harcanan Tuz: 1015 (2.058)
    09.04.2012 16:01 255.004 ekmekYap.exe

Yukarıdaki son iki test raporundan anlaşılacağı üzere program 2.057'den itibaren doğru çalışmıyor. Çünkü 100 ekmek için 1000 birim tuz harcanması gerekiyordu. Bunun olası cevabı fırınYak() işlevinin devreye girememesi olabilir. Ama buna neyin sebep olduğunu bilmiyorum. Tek bildiğim son sürümde de programın göçtüğü...:)

'*****' Son sürümde program sonlanması gerekirken, Windows göçme raporu verdi:

Alıntı:

>

Sorun imzası:
Sorunlu Olay Adı: APPCRASH
Uygulama Adı: ekmekYap.exe
Uygulama Sürümü: 0.0.0.0
Uygulama Zaman Damgası: 00000000
Hata Modülü Adı: StackHash_e98d
Hata Modülü Sürümü: 0.0.0.0
Hata Modülü Zaman Damgası: 00000000
Özel Durum Kodu: c0000005
Özel Durum Uzaklığı: 01330d05
OS Sürümü: 6.1.7601.2.1.0.256.48
Yerel Kimlik: 1055
Ek Bilgiler 1: e98d
Ek Bilgiler 2: e98dfca8bcf81bc1740adb135579ad53
Ek Bilgiler 3: 6eab
Ek Bilgiler 4: 6eabdd9e0dc94904be3b39a1c0583635

Sevgiler, saygılar...

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

April 09, 2012

Alıntı (Salih Dinçer):

>

Tek bildiğim son sürümde de programın göçtüğü...:)

Alıntı:

>

[Un 999995848, Su 999997924, Ya─ş 999996886, Tuz 999998962]: Ekmek = 98
[Un 999995824, Su 999997912, Ya─ş 999996868, Tuz 999998956]: Ekmek = 99
[Un 999995824, Su 999997912, Ya─ş 999996868, Tuz 999998956]: Ekmek = 99
[Un 999995824, Su 999997912, Ya─ş 999996868, Tuz 999998956]: Ekmek = 99
[Un 999995824, Su 999997912, Ya─ş 999996868, Tuz 999998956]: Ekmek = 99
[Un 999995824, Su 999997912, Ya─ş 999996868, Tuz 999998956]: Ekmek = 99
[Un 999995824, Su 999997912, Ya─ş 999996868, Tuz 999998956]: Ekmek = 99
-> firinYak while donuyor...
-> firinYak while donuyor...
-> firinYak while donuyor...
[Un 999995820, Su 999997910, Ya─ş 999996865, Tuz 999998955]: Ekmek = 99

  • Harcanan Tuz: 1045
    Hala firin calisiyor ve su an 248 ┬░C sicakliginda;
    -> firinYak while donuyor...
    -> firinYak while donuyor...
    -> firinYak while donuyor...
    -> firinYak while donuyor...
    -> firinYak while donuyor...
    -> firinYak while donuyor...
    -> firinYak while donuyor...
    -> firinYak while donuyor...
    -> firinYak while donuyor...
    -> firinYak while donuyor...
    -> firinYak while donuyor...
    -> firinYak while donuyor...
    -> firinYak while donuyor...
    -> firinYak while donuyor...
    -> firinYak while donuyor...
    -> firinYak while donuyor...
    PS E:\Proje - D\SubLime_Test>

Salih, acaba program sonlanmasına rağmen fırınYak() için başlattığın kanalın (thread) halen devam ediyor olması programın çökmesine sebep olabilir mi?

Ayrıca main() içinde ekmekYap() için iki ayrı kanal başlatıyorsun birisi döngüden önce, o kanal ne için gerekiyor? Belki programın tutarsız değerler üretmesine neden olan o kanaldır. Ayrıca daha fırın hazır değilken ekmekYap() çağrılması doğru mu?

Bu arada bence fırını projenin içinden çıkarıp ayırabilsek hem kodlama daha rahat olur hemde sistem daha esnek olur bence. Bu sebeple basit bir sınıf hazırlamaya çalıştım, amacım fırını kendi başına ayrı bir modül kullanarak girdi vermek ve çıktı almak dışında programdan uzakta tutmak, her türlü eleştiriyi bekliyorum, eksikleri çok biliyorum :)

class Firin
{
   private int _firinSicakligi = 0;     // 0..300 birim sıcaklık arasında çalışır.
   private int _mevcutGazMiktari = 0;   // 0...10_000 birim gaz depolanabilir.

   public this(int mevcutGazMiktari, int firinSicakligi)
   {
       _mevcutGazMiktari = mevcutGazMiktari;
       _firinSicakligi = firinSicakligi;
   }

   private void FiriniYakSicakligiAyarla()
   {
       // Her 100 birim sıcaklık için 5 birim gaz yakar.
       int harcananGazMiktari = _firinSicakligi * 5;

       assert(_mevcutGazMiktari < harcananGazMiktari, "Firindaki gaz miktari yetersiz.");
   }

   public void PizayiFirinaVer(Hamuru pizaHamuru)
   {
       assert(_firinSicakligi == 0, "Firin sicakligi yetersiz.");

       if (_firinSicakligi > 0)
       {
           switch (pizaHamuru)
           {
               case Hamuru.ince :
                   mevcutGazMiktari -= 2;  // Pişirme için harcanan gaz
                   break;

               case Hamuru.orta :
                   mevcutGazMiktari -= 3;
                   break;

               case Hamuru.kalın :
                   mevcutGazMiktari -= 4;
                   break;
           }

           //Piza pişiyor..
           Thread.sleep!("seconds")(10);   // 10 saniye bekle
       }
   }
}

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

« First   ‹ Prev
1 2 3