Mayıs 2009 Arşivi

Programımız hafızada kaç KB yer kaplıyor ?

// 16 Mayıs 2009 // 1 Yorum » // Delphi, Programlama

Yazdığımız programların hafızada ne kadar yer kapladıkları bilgisini elde etmenin pek çok yolu olmasına rağmen sanırım en iyi yöntem PSAPI.DLL içindeki metodları kullanmak. Bizim sevgili Delphi’miz sağolsun bu DLL’in içindeki metodları psAPI.pas(WinNT process API Interface Unit) içinde deklere etmiş. Bizlere sadece kullanmak kalıyor. Unit’i incelediğimizde pek çok yararlı metodun tanımlı olduğunu gözlemleyebiliyoruz. Processleri listeleyenlerinden tutunda, makinanızdaki device driverları listeleyen yada programınızın gereksiz kullandığı hafıza bloklarını serbest bırakmaya yarayacak bir diğer metod olan EmptyWorkingSet‘e kadar pek çok yararlı metod mevcut.(Bknz.)

Biz bu metodlardan GetProcessMemoryInfo isimli metodu kullanacağız makalemizde. Bu metod psAPI.pas’da aşağıdaki şekilde tanımlanmıştır:

function GetProcessMemoryInfo(Process: THandle;
  ppsmemCounters: PPROCESS_MEMORY_COUNTERS; cb: DWORD): BOOL;

(more…)

Nedir bu Thread’lerden çektiğimiz..!

// 16 Mayıs 2009 // 8 Yorum » // Delphi, Programlama

Uzun yıllık programcılık hayatımda pek çok defalar Thread kullandım ancak ilk defa bu kadar yoğun ve derinlemesine kullanma ihtiyacı hissettiğim bir projede çalıştım. Bu projemde TThread sınıfı ile uğraşırken karşılaştığım bazı sorunları sizlerle de paylaşmak istedim. Sizler önlemlerinizi baştan alın ki, saç baş yolmayın…

Eğer gerçekten time-critical işler yapıyorsanız thread’iniz içerisinde kesinlikle Synchronize kullanmayın.Çünkü Synchronize çağrısı thread’in çalışmasını kesip main thread’e geçirir.

Eğer siz TThread sınıfından türettiğiniz kendi sınıfınızda Execute metodunda bütün işi Synchronize metoduna teslim etmiş iseniz o zaman siz MTA (Multi Threaded Application) değil STA (Single Threaded Application) geliştiriyorsunuz demektir.. Yani ha formunuzun bir metodunu çağırmışsınız ha bir Thread create etmişsiniz.Arada hiçbir fark olmaz.! Bir örnek vermek gerekir ise:

TMyThread = class(TThread)
private
  fErrorString : String;
  procedure CallExternalProc;
protected
  procedure Execute; override;
public
  constructor Create;
  property ErrorString read fErrorString write fErrorString;
end;

constructor TMyThread.Create;
begin
  inherited Create(true); // Bekler vaziyette oluştur.!
  FreeOnTerminate := true; // Thread terminate olduğunda nesneyi Free et.!
  Resume; // Thread başlasın artık
end;

procedure TMyThread.CallExternalProc;
begin
  frmMain.Bilmemne;
  frmMain.BaskabirMetod;
  ...
  ...
 // Burada ise pek çok hesaplama vs. yaptığınızı düşünelim.!
end;

procedure TMyThread.Execute;
begin
  inherited;

  try
    Synchronize(CallExternalProc);
  except on E: Exception do
  begin
    ErrorString := Format('TMyThread: Error occured. %s, %s', [E.ClassType.ClassName, E.Message]);
  end;
end;

(more…)

Delphi Win32 & Lambda Expressions

// 16 Mayıs 2009 // 8 Yorum » // Delphi, Programlama

C# 3.0 ile birlikte gelen Lambda Expressionlar hakkında hemen hemen pek çok yerde makale yada yazıya rastlamak mümkün. Bu makalelerin bazılarında Lambda ifadelerin geleceğin programlama özelliği olduğu yönünde abartılı görüşler olsa da yine de faydalı ve olması gereken özellikler olduğu kanaatindeyim bende. Ancak bazı Lambdacıların da bilmesi gerekir ki bu programlama alemine kesinlikle yeni girmiş bir unsur değildir. Bazı programlama dillerinde bu yetenek çok uzun zamanlardan beri mevcut. Ancak maalesef Delphi’de henüz yok. En azından Win32 versiyonunda yok, Delphi Prism’de var.

O zaman bende kolları sıvadım ve tam anlamı ile Lambda Expressions gibi olmasa , onun gücüne yakınlaşamasa da, yine de benzer bir yapıyı kodlamak istedim. Lambda ifadelerinin genel kullanım amacı SQL sorgularında olduğu gibi bir veri kümesini filtrelemek olarak düşünülebilir. Bizde Delphi’de yazacağımız bir liste sınıfına bu özelliği kazandırmaya çalışacağız örneğimizde. Hatalarımız, eksiklerimiz olursa şimdiden affola diyerek başlayalım kodlamaya.

  TOperator = (opEqual, opGreater, opSmaller, opDifferent, opLike);

  TMyList = class(TList)
  public
    function Where(const PropertyName, PropertyValue : Variant; Operator : TOperator = opEqual) : TMyList;
    function InheritsFrom(const aClass : TClass) : TMyList;
  end;

(more…)

Uygulamamızın kullandığı hafıza miktarını nasıl düşürebiliriz ?

// 16 Mayıs 2009 // 8 Yorum » // Delphi, İşletim Sistemi, Programlama, Win32

Hepimizin bildiği gibi yazdığımız uygulamalar işletim sisteminde Process olarak adlandırılmaktadır. Her bir process en az bir main thread’e sahiptir. Bu iş parçacıkları, derlenmiş ikilik formattaki ham bilginin işletim sisteminin bellek yöneticisi vasıtası ile hafızaya yüklenerek işletilmesi ile hayat bulur. İşletim sistemlerinin bellek yönetimini nasıl yaptıkları son derece karmaşık bir konudur. Bir işletim sisteminde aynı anda birden fazla iş parçacığının çalışabilme ihtimali olduğu için bu işlemlerin bellekte kaplayacakları alanların ve bu bellek bölgeleri arasındaki etkileşimlerin son derece dikkatle hesaplanması gerekmektedir. İşletim sistemlerinde bir process fiziksel bellek ile iletişim halinde değildir. Bunun yerine her bir iş parçacığı için ayrılmış olan hafıza bloklarında her bir işlem kendisini fiziksel belleğin hakimi sanmaktadır. Bu tasarım, her bir işlem parçacığının teoride fiziksel belleğin kendisinden de daha fazla hafıza bloğuna sahip olabilmesini sağlamaktadır. Tüm bunları detaylıca anlatacak ne yerim ne de yeterince malümatım var ancak, bildiklerim ışığında izah etmeye devam edeyim. Process’lerin yani iş parçacıklarının fiziksel bellekten daha fazla alan kullanabilmesine imkan tanıyan teorik yaklaşıma Virtual Memory adı verilir. Virtual Memory modern işletim sistemlerinde disk vb. depolama cihazlarının kapasitelerinin bir kısmının fiziksel hafıza alanı gibi kullanması anlamına gelir. Örneğin Windows işletim sistemlerinde bu pagefile.sys dosyasıdır. İşletim sistemi bir iş parçacığının çalışması için gerekecek hafıza bloğunun karşılanamaması durumunda disk üzerindeki bahsi geçen dosyayı bir hafıza alanı gibi kullanarak fiziksel hafıza alanını rahatlatmaya çalışmaktadır. Ancak RAM’de tutulamayan verilerin sürekli disk ve RAM arasında yazılıp okunması elbette iş parçacığının çalışma performansını olumsuz yönde etkiler.

İşletim sistemleri, RAM ile sanal bellek arasındaki adreslemeleri fiziksel bellek haritasını kullanarak gerçekleştirirler. Her bir işlem için ayrılmış izole hafıza bloğundaki $101112 gibi bir adres fiziksel adresteki aynı adres demek değildir. Bu adresin fiziksel adresteki karşılığı başka bir tabloda tutulur ve fiziksel hafızaya erişim için bu tablodan istifade edilir. Modern işletim sistemleri, iş parçacıkları için ayırdıkları hafıza bloklarının tamamen izole olmasından sorumludurlar. Bir iş parçacığının diğer birisinin kullandığı hafıza bloğuna erişimi, o blokta yapabileceği değişiklikler tehlikeli durumlara sebebiyet verecektir. İşte bu sebeple arada sırada da olsa Protection Fault gibi hatalar alırız. Aynı zamanda işletim sistemleri, mevcut fiziksel hafızayı iş parçacıkları üzerinde adil dağıtma gibi bir misyonu da bünyelerinde barındırmak durumundadırlar.
(more…)

Bir TStringList türevi..

// 15 Mayıs 2009 // 7 Yorum » // Delphi, Programlama

Bir istek üzerine , mevcut VCL sınıflarından birisine onun bünyesinde barındırmadığı bir event yazma ile ilgili bir makale yayınlayacağım.Düşündüm taşındım hangi nesneye ne eklesem diye, VCL’in üreticileri sağolsunlar pek çok şeyi düşünmüşler.Benimde aklıma TStringList sınıfına birkaç olay eklemek geldi. Zaten amaç genel olarak ne yapıldığını anlayabilmek ondan sonrasında siz değerli arkadaşlarım kendi isteklerinize göre istediğiniz sınıfı özelleştirirsiniz. Bu yazım da OnBeforeAdd, OnAfterAdd olaylarını eklemeyi düşündüm önce.Ama daha sonra aklıma, filtreleme özelliği de eklemek geldi.Nasıl yani filtreleme ? Biz istediğimiz kadar kötü kelime (badword) belirtebilseydik, ve TStringList nesnemize ekleme yaparken sınıfımız eklemek istediğimiz metnin içerisinde kötü bir kelime geçiyor ise bize bir event’le cevap verseydi , sonra bizde o eventte “Evet, kabul ediyorum” yada “hadi oradan..!” diyebilseydik ne güzel olurdu değil mi ? Eh o zaman demek ki birde OnBadwordFind diye bir olay daha oluşturmalıyız. Sınıfın anafikrini sizlerle paylaştığımıza göre, gelin TStringList sınıfı etrafında biraz dolanalım..Araştırma yapmadan olmuyor bu işler.. ;) Yine her zamanki gibi Delphi Help’i açtık ve yazdık TStringList diye..Metodlarına bakıyoruz. Evet bizim kullanmamız gereken metodu Add metodu..Gelin tanımına şöyle bir bakalım:
(more…)

Absolute (votka değil!)

// 15 Mayıs 2009 // Yorum Yok » // Delphi, Programlama

Absolute direktifi bir değişkenin kendisinden önce tanımlanmış bir başka değişken ile aynı hafıza bloğunu kullanmasını sağlar.

var
  iValue : Cardinal;
  iOther : Cardinal absolute iValue;
begin
 iValue := 250;
 ShowMessage(InttoStr(iValue) + ‘-’ + InttoStr(iOther)); // 250-250

 iOther := 555;
 ShowMessage(InttoStr(iValue) + ‘-’ + InttoStr(iOther)); // 555-555
end;

Yukarıda görüldüğü üzere iki değişken de aynı hafıza bölgesini paylaşıyorlar ve birinde yapılan değişiklik diğerine otomatikman yansıyor.Ancak absolute direktifini gösterdiği tip ile aynı tipte vermeyebilirsiniz.Şöyle ki:
(more…)

Protected özellikleri Hack’leyelim ;)

// 15 Mayıs 2009 // 2 Yorum » // Delphi, Programlama

Delphi sınıflarının benden çekeceği var :) Ne yapsalar nasıl saklasalar değişkenleri bir şekilde ulaşıyoruz. :) Private özellikleri değiştirme yönteminden sonra daha değişik bir konu olan protected özelliklere ulaşmayı anlatacağım bu makalemde..

Delphi’de en yaygın olarak kullanılan 4 adet erişim belirleyicisi vardır.Bunlar private, protected, public, ve published‘dır. Bunların ne işe yaradıklarından detaylıca bahsetmeyeceğim.Konumuz protected. Protected bloğunda tanımlanmış olan tüm üyeler sınıfın tasarımcısı tarafından sınıf kullanıcılarından gizlenmiştir. Ancak bu sınıfı miras alan sınıflarda erişime açıktırlar. Mesela bir formumuz olsun ve üzerinde 3 adet TEdit nesnemiz olsun. Edit bileşenlerimizin hepsinin OnClick yordamını aynı yere ayarlayalım ve OnClick yordamında aktif olan kontrolün rengini kırmızı yapmak isteyelim. Hadi bakalım kodlamaya başlayalım:

procedure TForm1.Edit1Click(Sender : TObject);
var
  cControl : TWinControl;
begin
  cControl := Screen.ActiveControl;
  cControl.Color := clRed;
end;

Yukarıdaki kodu çalıştırmayı denediğimizde “Undeclared identifier:Color” diye bir hata mesajı alıyoruz. İyide bu hata da ne ki şimdi..Hemen Delphi Help’i açıyoruz ve TEdit’e bakıyoruz..Hiyerarşiye bir bakıyoruz şöyle:
(more…)

Delphi, ilginçlikler diyarı..!

// 15 Mayıs 2009 // Yorum Yok » // Delphi, Programlama

Delphi gerçekten de çok güçlü bir dildir..Ama onu hepimiz yeterince iyi kullanabiliyormuyuz işte orası tatışılır. Sizlerle birkaç ilginç kullanımı paylaşmak ve dilim döndüğünce anlatmak istiyorum.Mesela hemen hemen her Delphi programcısı herhangi bir nesnenin OnClick olay yöneticisinde belli başlı kodlar yazmıştır.Tüm OnClickler şöyle görünür.

  procedure …Click(Sender : TObject);

Peki düşündük mü acaba , “yahu bu Sender : TObject de nereden geliyor ?” diye.. Bu tanım aslında TNotifyEvent adlı bir tanımdan gelmektedir. Delphi Help’i açar ve TNotifyEvent’de neymiş diyip bakarsanız şöyle bir tanım göreceksiniz:

  type TNotifyEvent = procedure (Sender: TObject) of object;

Hımm bu da ne şimdi ? TNotifyEvent diye bir şey tanımlanmış ve ona sen bir proceduresin denmiş TObject türünde de bir parametren var denilmiş. Ehh biraz anladık, iyi de o sondaki of object de ne oluyor ? Açıklayacağız meraklanmayın.Ancak ondan önce farkettiğimiz daha doğrusu aklımıza gelen bazı cinlikleri deneyelim.
(more…)

Class of ……

// 15 Mayıs 2009 // 1 Yorum » // Delphi, Programlama

Interface’lerla ilgili örneğim de TRadioGroup nesnesi üzerinden yapılan bir seçimle çeşit çeşit veritabanına bağlanıyorduk.Bu benim aklıma başka bir şey daha getirdi.Onu da sizlerle paylaşmak istedim. Bazen çalışma anında(run-time) bazı nesnelerin üretilmesi kullanıcının yapacağı seçime bağlı olur. Hemen somut bir örnek verelim. Mesela TRadioGroup nesnemizde üç seçenek olsun, kullanıcı birinciyi seçerse bir adet TMemo oluşturmamız, ikinciyi seçerse TEdit ve üçüncüyü seçerse de TPanel oluşturmamız gereksin. Bu durum şimdiye kadar başınıza gelmedi ise bundan sonra gelmesi kuvvetle muhtemel bir durumdur. Eee bu durumda ne yapacağız ? Şöyle bir şey yapsak olur mu acaba :

var
 mem : TMemo;
 edt  : TEdit;
 pnl  : TPanel;
 begin
  case RadioGroup.ItemIndex of
    0 :
        begin
          mem := TMemo.Create(Self);
          mem.Left := 10;
          mem.Top := 10;
          mem.Width := 100;
          mem.Height := 100;
          mem.Parent := Self;
        end;
    1 :
        begin
          edt := TEdit.Create(Self);
          edt.Left := 10;
          edt.Top := 10;
          edt.Width := 100;
          edt.Height := 100;
          edt.Parent := Self;
        end;
    2 :
        begin
          pnl := TPanel.Create(Self);
          pnl.Left := 10;
          pnl.Top := 10;
          pnl.Width := 100;
          pnl.Height:= 100;
          pnl.Parent := Self;
        end;
  end; //case
end;

(more…)

Interface’ler ile bir senaryo..

// 15 Mayıs 2009 // 1 Yorum » // Delphi, Programlama

Bu konu çok derin bir konu ancak kısaca bir giriş yapmak istiyorum. Aslında koddan çok kullanım amacını anlatmaya çalışacağım.O yüzden bir senaryo üreteceğim.Diyelim ki; siz component üreten bir firmada yazılım proje yöneticisisiniz. Her türlü tasarım sizden geçiyor ve diyelim ki veritabanı bağlantıları ile ilgili componentler geliştirmeniz gerekiyor.Ekibinizde yeterli sayıda programcınız var.Ancak programcıların çok başına buyruk marjinal insanlar olduklarını da deneyimlerinizle biliyorsunuz ve onlara da yeterince güvenmiyorsunuz ;) Mesela, daha somut örnekler verirsek. Diyelim ki, üretilecek olan componentler SQL Server’a, Sysbase’e , Oracle’a , Interbase’e , Informix’e , DB2′ya bağlanabilmeli diye bir zorunluluk var.Bunu sağlayabilmek adına ekibi topladınız ve programcılarınızın yetenekleri ölçüsünde her bir sınıfın tasarımını ilgili kişilere verdiniz.Ve biliyorsunuz ki herhangi bir veritabanına bağlanacak olan bir sınıfın temelde uygulaması gereken iki metod var Open ve Close ve siz de programcılarınıza bu tecrübenizi ve bilginizi aktardınız. Ama dedik ya programcılar marjinal insanlardır diye. Bakın programcılarımız ne yaptı:

TSQLConnection = class(TBaseConnection)
public
  procedure OpenConnection;
  procedure CloseConnection;
end;

TOracleConnection = class(TBaseConnection)
public
  procedure Open;
  procedure Close;
end;

TSybaseConnection = class(TBaseConnection)
public
  procedure Connect;
  procedure Disconnect;
end;

(more…)