Jump to page: 1 2
Thread overview
Web sayfasından uygulama çalıştırmak
Jun 01, 2017
zafer
Jun 03, 2017
zafer
Jun 04, 2017
Salih Dinçer
Jun 06, 2017
zafer
Jun 06, 2017
Salih Dinçer
Jun 06, 2017
zafer
Jun 08, 2017
Salih Dinçer
Jun 09, 2017
Salih Dinçer
Feb 18, 2018
zafer
June 02, 2017

Merhaba,

Web sayfamda bulunan bir düğme ile bir konsol uygulaması başlatmak istiyorum. Bu işlem için std.process (https://dlang.org/phobos/std_process.html#.spawnProcess) modülünde bulunan spawnProcess metodunu kullanıyorum.

Buradaki sorun, uygulama çalıştığı sürece web sayfam bloke oluyor. spawnProcess metodunun dönüş değerini kullanmazsam sayfa bloke olmuyor ancak bu seferde işlemin bittiğini bilemiyorum. Kısaca spawnProcess metodunu eşzamansız çalıştırmak mümkün mü?

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

June 02, 2017

spawnProcess'in sonucunu wait() ile alıyorsan program bekliyormuş. O zaman bir seçenek, thread kullanmak:

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

void main() {
   // Bunların gelen isteklerle ilgili olduklarını varsayalım
   // (Anahtar istek id'si, değer de istenen işlem)
   immutable(string[])[int] istekler = [ 42 : [ "/bin/sleep", "3" ],
                                         99 : [ "/bin/sleep", "4" ],
                                         7 :  [ "/bin/sleep", "2" ] ];

   // İstekleri burada baştan başlatıyoruz ama tabii ki ana döngü sırasında
   // ilgisiz zamanlarda da başlatılabilirler
   foreach (t; istekler.byKeyValue) {
       spawn(&işlemci, t.key, t.value);
   }

   // Programın ana döngüsü
   int toplamSonlanan;
   while (toplamSonlanan < istekler.length) {
       writeln("Ana döngü bekliyor...");
       Thread.sleep(500.msecs);
       receiveTimeout(0.msecs,
                      (int id, int sonuç) {
                          writefln("%s numaralı istek %s değeriyle sonlandı", id, sonuç);
                          ++toplamSonlanan;
                      });
   }
}

void işlemci(int id, immutable string[] işlem) {
   auto pid = spawnProcess(işlem);
   writefln("%s numaralı isteğin işlemi başladı: %s", id, işlem);
   auto sonuç = wait(pid);
   writefln("%s işlemi %s değeriyle sonlandı", pid, sonuç);
   ownerTid.send(id, sonuç);
}

Bir çıktısı:
'
Ana döngü bekliyor...
99 numaralı isteğin işlemi başladı: ["/bin/sleep", "4"]
42 numaralı isteğin işlemi başladı: ["/bin/sleep", "3"]
7 numaralı isteğin işlemi başladı: ["/bin/sleep", "2"]
Ana döngü bekliyor...
Ana döngü bekliyor...
Ana döngü bekliyor...
Ana döngü bekliyor...
std.process.Pid işlemi 0 değeriyle sonlandı
7 numaralı istek 0 değeriyle sonlandı
Ana döngü bekliyor...
Ana döngü bekliyor...
std.process.Pid işlemi 0 değeriyle sonlandı
42 numaralı istek 0 değeriyle sonlandı
Ana döngü bekliyor...
std.process.Pid işlemi 0 değeriyle sonlandı
99 numaralı istek 0 değeriyle sonlandı
'

Başka yöntem ise sonucu tryWait() ile beklemekmiş:

import std.stdio;
import std.process;
import core.thread;
import std.array;
import std.algorithm;

struct Beklenen {
   int id;
   Pid pid;
}

void main() {
   // Bunların gelen isteklerle ilgili olduklarını varsayalım
   // (Anahtar istek id'si, değer de istenen işlem)
   immutable(string[])[int] istekler = [ 42 : [ "/bin/sleep", "3" ],
                                         99 : [ "/bin/sleep", "4" ],
                                         7 :  [ "/bin/sleep", "2" ] ];

   Beklenen[] beklenenler;

   // İstekleri burada baştan başlatıyoruz ama tabii ki ana döngü sırasında
   // ilgisiz zamanlarda da başlatılabilirler
   foreach (t; istekler.byKeyValue) {
       auto pid = spawnProcess(t.value);
       writefln("%s numaralı isteğin işlemi başladı: %s", t.key, t.value);
       beklenenler ~= Beklenen(t.key, pid);
   }

   // Programın ana döngüsü
   size_t adet;
   // Öylesine bir sonlanma koşulu
   while (adet < 10) {
       ++adet;
       writeln("Ana döngü bekliyor...");
       Thread.sleep(500.msecs);

       if (beklenenler.empty) {
           writeln("Beklenen işlem yok");
       } else {
           foreach (ref beklenen; beklenenler) {
               auto sonuç = tryWait(beklenen.pid);
               if (sonuç.terminated) {
                   writefln("%s numaralı istek %s değeriyle sonlandı", beklenen.id, sonuç.status);
                   // Daha sonradan silmek için işaretleyelim (döngüdeki ref'e dikkat)
                   beklenen.id = int.min;
               }
           }
           // Bunun için daha etkin yöntemler var. Burada çok basitçe:
           beklenenler = beklenenler.filter!(b => b.id != int.min).array;
       }
   }
}

Onun çıktısı:
'
7 numaralı isteğin işlemi başladı: ["/bin/sleep", "2"]
42 numaralı isteğin işlemi başladı: ["/bin/sleep", "3"]
99 numaralı isteğin işlemi başladı: ["/bin/sleep", "4"]
Ana döngü bekliyor...
Ana döngü bekliyor...
Ana döngü bekliyor...
Ana döngü bekliyor...
7 numaralı istek 0 değeriyle sonlandı
Ana döngü bekliyor...
Ana döngü bekliyor...
Ana döngü bekliyor...
42 numaralı istek 0 değeriyle sonlandı
Ana döngü bekliyor...
99 numaralı istek 0 değeriyle sonlandı
Ana döngü bekliyor...
Beklenen işlem yok
Ana döngü bekliyor...
Beklenen işlem yok
'

Ali

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

June 02, 2017

Yukarıda şöyle demiştim:

           // Bunun için daha etkin yöntemler var. Burada çok basitçe:
           beklenenler = beklenenler.filter!(b => b.id != int.min).array;

Diziden eleman çıkartmanın etkin bir yöntemi, std.algorithm.remove'u (program için kabul edilebiliyorsa SwapStrategy.unstable ile) kullanmaktır:

import std.random;
import std.range;
import std.algorithm;
import std.stdio;

auto rasgeleSayılar(size_t adet) {
   return iota(adet).map!(_ => uniform(0, 100));
}

void main() {
   auto a = rasgeleSayılar(20).array;
   writefln("Önce : %s", a);

   auto b = a.remove!(e => e % 2);

   // a'nın yerinde değiştiğini kanıtlayalım:
   assert(a.ptr == b.ptr);

   writefln("Sonra: %s", b);
}

assert'ün gösterdiği gibi, a yerinde değişmiştir. Yani, b yeni bir dizi değildir.
'
Önce : [91, 98, 89, 26, 85, 93, 9, 19, 99, 13, 82, 5, 36, 22, 51, 71, 48, 71, 37, 76]
Sonra: [98, 26, 82, 36, 22, 48, 76]
'
Eğer elemanların sıraları önemli değilse şu genelde daha hızlıdır:

   auto b = a.remove!(e => e % 2, SwapStrategy.unstable);

Dikkat ederseniz, çıkartılan 89'un yerine sondaki 46 gelmiş (böylece elemanların kopyalanmaları aza indirgenmiştir), vs.:
'
Önce : [89, 95, 83, 15, 70, 99, 23, 37, 57, 70, 39, 21, 29, 80, 98, 63, 79, 59, 48, 46]
Sonra: [46, 48, 98, 80, 70, 70]
'

Her iki yöntemde de a degişmiştir ve herhalde artık kullanışlı değildir. (a'nın son tarafındaki elemanların bazıları a'nın baş tarafındakilerle aynıdır.) Dolayısıyla, normalde sonuç doğrudan a'ya atanın (ben farkını gösterebilmek için b tanımladım):

   a = a.remove!(e => e % 2, SwapStrategy.unstable);

Şimdi bir sorun, a'ya yeni eleman eklemeye kalktığımızda ortaya çıkabilir çünkü druntime a'nın sondaki elemanlarının kimse tarafından kullanılmamakta olduğunu bilemez ve yeni eleman eklediğimizde bütün diziyi yeni bir yere taşır:

   writefln("Eleman eklemeden önce  : %s", a.ptr);
   a ~= 222222;
   writefln("Eleman ekledikten sonra: %s", a.ptr);

Elemanlar artık yeni bir yerdedir :(:
'
Eleman eklemeden önce : 7FCC6E782080
Eleman ekledikten sonra: 7FCC6E784000
'
a'nın başka kimse tarafından kullanılmadığından eminsek assumeSafeAppend'i çağırabiliriz. assumeSafeAppend, dilimin kapasitesini yerinde arttırır. (Örneğin, kapasite en azından a'nın en baştaki uzunluğu kadar olacaktır.) (Ancak, bunu gösterebilmek için çok debelendim çünkü henüz giderilmemiş olan bir hata var: array() ile oluşturulan dilimlerin kapasiteleri hep 0 kalıyor. O yüzden örneği varolan bir dilimin sonuna eleman ekleyerek başlatacak biçimde değiştiriyorum.)

import std.random;
import std.range;
import std.algorithm;
import std.stdio;

auto rasgeleSayılar(size_t adet) {
   return iota(adet).map!(_ => uniform(0, 100));
}

void main() {
   // Değişiklik: .array çağırmak yerine bir diziye ekleyerek başlıyorum
   int[] a;
   rasgeleSayılar(20).each!(e => a ~= e);
   writefln("Önce : %s", a);

   a = a.remove!(e => e % 2, SwapStrategy.unstable);
   writefln("Sonra: %s", a);

   writefln("Eleman eklemeden önce  : %s (kapasite: %s)", a.ptr, a.capacity);
   assumeSafeAppend(a);
   a ~= 222222;
   writefln("Eleman ekledikten sonra: %s (kapasite: %s)", a.ptr, a.capacity);
}

Artık a'ya yeni eklenen eleman yerinde eklenmiştir çünkü assumeSafeAppend a'nın elde edebileceği bütün kapasiteyi ona vermiştir. (Dikkat: Artık işimize yaramayan a'nın sonundaki eski elemanlara eriştiren başka dilim bulunmadığını kendimiz sağlamalıyız.)
'
Eleman eklemeden önce : 7F3B51E15080 (kapasite: 0)
Eleman ekledikten sonra: 7F3B51E15080 (kapasite: 31)
'
Tabii bütün bu işlemleri otomatik olarak halleden bir tür kullanmak isteyebiliriz:

import std.random;
import std.range;
import std.algorithm;
import std.stdio;

struct YerindeDizi(T) {
   T[] elemanlar;

   void ekle(T e) {
       elemanlar ~= e;
   }

   void sil(alias kıstas, SwapStrategy swapStrategy = SwapStrategy.unstable)() {
       elemanlar = elemanlar.remove!(kıstas, swapStrategy);
       elemanlar.assumeSafeAppend();
   }

   // Dikkat: 'elemanlar' üyesine doğrudan erişime izin verilmemelidir çünkü
   // bu türü kullananların ellerindeki dilimler assumeSafeAppend ile geçersiz
   // (veya kullanışsız) hale gelebilir.
   //
   // Ben burada daha fazlasını gerçekleştirmeyeceğim.
}

auto rasgeleSayılar(size_t adet) {
   return iota(adet).map!(_ => uniform(0, 100));
}

void main() {
   auto a = YerindeDizi!size_t();

   foreach (i; 0 .. 100) {
       const önceki_ptr = a.elemanlar.ptr;
       rasgeleSayılar(20).each!(e => a.elemanlar ~= e);

       // (Bunu bir isimsiz işlev (lambda) yerine static bir yerel işlev olarak
       // tanımlamak zorunda kaldım. dmd'nin bilinen bir yetersizliği...)
       static bool kıstas(size_t eleman) {
           return eleman % 2;
       }

       a.sil!(kıstas, SwapStrategy.unstable);
       if (a.elemanlar.ptr != önceki_ptr) {
           writefln("Yer değişti - ptr: %s, length: %s, capacity: %s",
                    a.elemanlar.ptr, a.elemanlar.length, a.elemanlar.capacity);
       }
   }


   writefln("Son         - ptr: %s, length: %s, capacity: %s",
            a.elemanlar.ptr, a.elemanlar.length, a.elemanlar.capacity);
}

Sonuçta, başta gösterdiğim 'beklenenler' gibi yalnızca bir kaç eleman taşıyacak olan diziler yerine buradaki gibi YerindeDizi gibi bir tür kullanılırsa elemanlar hiç kopyalanmazlar. Yukarıdaki programda 100 kere 20 eleman ekleyip tek sayı olanlarını çıkartıyorum. Dolayısıyla bu dizi gerçekçi olmayan biçimde hep büyüse de (ortalamada 1000 eleman içerir) elemanlar yalnızca 5 kere kopyalanmak zorunda kalıyorlar:
'
Yer değişti - ptr: 7F01B8778100, length: 7, capacity: 31
Yer değişti - ptr: 7F01B877E000, length: 26, capacity: 63
Yer değişti - ptr: 7F01B877F000, length: 59, capacity: 127
Yer değişti - ptr: 7F01B877C800, length: 122, capacity: 255
Yer değişti - ptr: 7F01B7879010, length: 255, capacity: 509
Son - ptr: 7F01B7879010, length: 1007, capacity: 1021
'
Ali

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

June 03, 2017

Ali eline sağlık burada harika bilgiler ve güzel D olanaklarını örneklemişsin. Hepsini daha detaylı incelemek için sonraya bırakıyorum.

Thread fikri aklıma hiç gelmemişti. Sen bunu söyleyince Vibe.d üzerindeki Task (http://vibed.org/docs#tcp-client) olanağı aklıma geldi. Birde onunla deneme yapmayı düşünüyorum.

Ayrıca tetikleme işlemi web sayfası üzerinden olacak ve program çalışıyorsa ikinci bir örnek çalıştırılmayacak. Bu yüzden programın çalışıp çalışmadığınıda takip etmem gerekiyor.

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

June 03, 2017

Alıntı (zafer):

>

program çalışıyorsa ikinci bir örnek çalıştırılmayacak. Bu yüzden programın çalışıp çalışmadığınıda takip etmem gerekiyor.

O zaman en iyisi hiç thread başlatmadan gereken zamanlarda tryWait'i çağırmak (örneğin, belirli aralıklarda veya birisi tekrar tıklandığında). tryWait'in dönüş değerinin .terminated niteliği önceki işlemin sonlanıp sonlanmadığını bildiriyor.

Ali

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

June 04, 2017

Selamlar Zafer ve Ali hocam...

Çalıştığın projeyi hangi yapıda (server platform?) gerçekliyorsun? Sorumu sana yardımcı olabileceğimden değil de ilgimi çektiğinden sana yöneltmekteyim :)

Bu arada bunu yapabilmek için kiralık bir sunucuya ihtiyaç var değil mi? Yani D'de yazdığımız bir uygulama, CGI kullanılmadan çalıştırılıp yine sonuçları web interface ile ziyaretçiye gösterilmesi mümkün mü? Çok ilgimi çekti de bizzat basit bir örnek ile yardımcı olursan müteşekkir olurum.

Sevgiler, saygılar... (bu arada hoş bulduk :D)

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

June 05, 2017

Örnek olarak vibe.d gibi çatılar var. Biz de şu konuda doğrudan socket üzerinden incelemiştik:

http://ddili.org/forum/thread/1261

Sonuçta önemli olan, HTTP protokolünü uygulamak: İstek düzeni belli, yanıt düzeni belli. Yukarıdaki örnekte HTTP yanıtı şöyle oluşturulup gönderiliyor:

   enum başlık =
       "HTTP/1.0 200 OK\nContent-Type: text/html; charset=utf-8\n\n";

   string yanıt = başlık;
   yanıt ~= "<b>Merhaba Dünya!</b>\n";

   istemci.send(yanıt);

Ali

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

June 06, 2017

Selamlar Salih, seni gördüğüme sevindin :)

Ben projem için Vibe.d (http://vibed.org) çatısını kullanıyorum. Web tabanlı uygulamalar geliştirmek için gerekli altyapı ve olanakları Vibe.d sana sunuyor. Bundan dolayı kendi bilgisayarında tüm çalışmanı yapabilirsin.

Proje aşamasında bir sunucuya ihtiyacın yok. Web tarafı yani talepler, cevaplar, rotalar gibi tüm alt düzey işleri Vibe.d çatısı hallediyor. Yani D ile web tabanlı bir uygulama geliştirip sonucu bir web arayüzü (tarayıcı) ile ziyaretçilere sunabilirsin.

Merak ediyorsan Vibe.d github (https://github.com/rejectedsoftware/vibe.d) sayfasında başlaman için gerekli bilgi var. Takıldığın yerde hep burada ve yanındayız :)

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

June 06, 2017

Ben bu çatıya hiç alışamadım. Kontrol bende değilmiş izlenimi veriyor. D'nin kendi olanaklarıyla hareket etmek isterdim.

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

June 07, 2017

Alıntı (Salih Dinçer):

>

D'nin kendi olanaklarıyla hareket etmek isterdim.

Ali'nin önceki mesajlarda eklediği örnek üzerinden gidebilirsin. Tamamen D olanaklarını kullanıyor. Ancak projen gelişmeye başladığı zaman bir sunucu ile entegrasyonu, rotalar, yetkilendirme, mime türleri ve güvenli bağlantı (ssh) gibi konuları kendi başına çözmeyi göze almalısın.

D ile web tarafında ilerlemek istiyorsan Vibe.d bence güzel bir çatı. Halen bir çok eksiği var. Yinede oldukça modern olanaklara ve sade ve temiz bir kodlama yapısına sahip. Bence D ile web tarafında çalışacaklar için iyi bir tercih olur. Performansıda biraz daha iyi olsaydı daha iyi olurdu :( https://www.techempower.com/benchmarks/#section=data-r14&hw=ph&test=fortune

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

« First   ‹ Prev
1 2