Haftalık C++ 40 – std::chrono – 2 (clocks, time_point)

Evet yazılımperver dostlarım, std::chrone kütüphanesi maceramıza devam ediyoruz. İlk yazımı okumayan yazılımperver dostlarımızın, öncelikle o yazıma bakmalarında fayda var. Aşağıya ilgili yazının bağlantısını ekliyorum:

Haftalık C++ 39 – std::chrono – 1

İlk yazımızda, std::chrono tarafından sunulan üç önemli kavram olan, süre (“duration”), saat (“clock“) ve zaman noktası (“time_point“)’a değinmiş ve süre kavramını ve kabiliyetlerini detaylı bir şekilde incelemiştik. Bu yazımızın konusu ise saat ve zaman noktaları olacak. O zaman saatler ile başlayalım.

Saatler (“clock”)

std::chrono, saati, bir başlangıç zamanı (“epoch”) ve bu zamandan itibaren olan süre için kullanılacak olan ilerleme periyot (“tick period”) bilgileri ile tanımlar. Hemen hızlı bir örnek ile netleştirmeye çalışayım. Örneğin, bir saat Unix Epoch’u (1 Ocak 1970) başlangıç ve periyodu da milisaniye cinsinden ifade ediyor olabilir. Benzer şekilde başka saat, saniye cinsinden de tutuyor olabilir. Bunlar farklı saatleri temsil eder. Bu saatlerin başlangıç zamanları da farklı olabilir.

Peki bu farklı saatler konusunda neye dikkat etmemiz gerekiyor? Her ne kadar daha bahsetmemiş olsak da, zaman noktaları (“time point”) muhakkak bir saat ile ilişkilendirilirler. Farklı saatler ile ilişkilendirilmiş, zaman noktalarını bir diğeri ile kullanamazsınız. Şimdi biraz daha detaylara inelim.

std::clock tipleri <chrono> başlık dosyası ve std::chrono adres uzayı içerisinde tanımlanmaktadır. Uygulamaların ihtiyaçlarına göre birçok saat kullanılıyor olabilir. En son std::chrono referans sayfasına baktığımda aşağıdaki saatlerin tanımlanmış olduklarını gördüm. Bunların bir kısmı C++ 20 ile sunuluyor:

system_clock (C++11)
Gerçek zamanlı sistem saati sınıfı
steady_clock (C++11)
Değiştirilemeyen monoton saat sınıfı
Sistem tarafından sunulan en kısa periyoda sahip saat sınıfı
utc_clock (C++20)
Coordinated Universal Time (UTC) sınıfı
tai_clock (C++20)
International Atomic Time (TAI) sınıfı
gps_clock (C++20)
GPS zaman sınıfı
file_clock (C++20)
Dosya zaman snıfı
local_t (C++20)
Yerel zamanı ifade eden “pseudo-clock” saat sınıfı

Ayrıca ilgili tipin, saat olup/olmadığını kontrol etmek için C++ 20 ile birlikte is_clock ve is_clock_v API’leri de sunulmakta.

Gelelim, bu saatlere ilişkin, her bir saat sınıfı ile sunulması gereken tiplere ve statik üyelere. Bu üyeler aracılığı ile ilgili saatlere ilişkin daha detaylı bilgi edinebiliyoruz:

İlgili ÜyeAçıklama
clock::durationSaat’in kullandığı süre (“duration”) tipini tanımlar (std::chrono::duration<rep, period>)
clock::repSaat’in kullandığı süreyi ifade etmek için kullandığı ilerlemelerin (“tick”) aritmetik tipini ifade eder (std::chrono::duration::rep)
clock::periodSaat’in kullandığı periyodun tipini ifade eder (std::chrono::duration::period)
clock::time_pointSaat’in kullandığı zaman noktasının tipini ifade eder
clock::is_steady     İlgili saatin sürekli/istikrarlı olup olmamasını ifade eder. Buna aşağıda biraz daha değineceğim
clock::now()Şu anı ifade eden zaman noktasını (time_point) döner

Kodsal olarak gösterecek olsak, şu şekilde ifade edilebilir:

Yukarıdaki tiplerin çoğu kendini ifade etse de, bir ikisine burada değinmekte fayda var:

  • Bunlardan ilki: “is_steady” özellikliği. bu özellik ilgili saatin hiç bir zaman değiştirilip/değiştirelemeyeceğine ilişkin bilgiyi verir (windows üzerinden saati bir şekilde değiştirme olarak da düşünebilirsiniz) . Kısaca, bu saatin sunduğu zaman noktaları  hiç bir zaman geriye gitmez. Bu özelliğe saat tiplerinde de değineceğiz,
  • Bir diğeri ise: “now()” fonksiyonu. Bu fonksiyon ile, ilgili saati kullanan mevcut anı, zaman noktası nesnesi olarak alabiliyoruz. Tahmin edebileceğiniz üzere, saatler için en önemli fonksiyonlardan birisi budur.

Yazımın başında, STL tarafından sunulan birtakım saatlerin listesini sizler ile paylaştım. Bu yazımda, STL ile gelen üç temel saate bakıyor olacağız. Bunlar: system_clock, steady_clock ve high_resolution_clock.

  • system_clock:
    • Mevcut sistemde bulunan gerçek zamanlı saat alt yapısı ile sunulan zaman noktalarını almanıza olanak sağlar. Bu saat ayrıca, to_time_t() ve from_time_t() fonksiyonları aracılığıyla C tarafından sunulan time_t ile std::chrono tarafından sunulan time_point tipleri arasında dönüşüm yapmanıza olanak sağlar.
    • Bu iki API sayesinde, saatleri de kullanarak, takvimsel saat metinlerini oluşturabilirsiniz (ör. Mon May 23 13:44:00 2011). Nasıl mı? Hemen bakalım:
    • Kısaca takvimsel operasyonlar için bu saat tipini kullanabilirsiniz.
    • C++ 20 ile birlikte, formatlama ile ilgili bir takım ek kabiliyetler de eklenmiştir. İlgili referans sayfasında bu konuda daha net bilgi edinebilirsiniz.
  • steady_clock:
    • Bu hiçbir zaman değişmeyeceği garantisi verilen bir saattir. Fiziksel zaman ilerlerken, bu saate ilişkin anlık zamanlar hiçbir zaman azalmazlar ve orantılı şekilde/oranda ilerlerler. Bu ne demek?
    • Bu saat tipi de, özelllikle belirli bir süre bekleme veya bir süreye kadar bekletme için tercih edilmektedir. “Stopwatch” benzeri özellikler için de bu saat kullanılmalıdır. Örneğin, bu amaçla sistem saati kullandığınız durumda, windows üzerinde kullanıcı eğer saati değiştirir ise, sonuç değişir. Fakat, steady_clock’ta böyle bir durum söz konusu değil.
    • Bu saati kullanarak da, günün saati veya günü, ayı öğrenemezsiniz!
    • Bu saatin başlangıç zamanı genelde PC’lerde boot zamanı olabiliyor 😉
  • high_resolution_clock:
    • Bu saat, sistem üzerinde en kısa ilerleme periyodunu veren saati temsil eder. Bir diğer ifade ile en hassas saati ve zaman anlarını sağlar.
    • Çoğu sistemde genelde yukarıda bahsettiğimiz iki saat tipini kullanır ya da farklı bir saat de olabilir.
    • Her ne kadar süre ve benzeri ölçümlerde, bu saat tipini insanın kullanası gelse de, referans sayfasında da ifade edildiği üzere, steady_clock, bu anlamda daha doğru bir seçim olacaktır.

C++ standardı ve STL kütüphaneleri, bu saatlere ilişkin, başlangıç zamanı, minimum/maksimum zaman anı ve çözünürlüğüne dair bir garanti vermez. Bu sebeple, katı isterleri bulunan uygulamalar için, mevcut saatlerin sunduğu kabiliyetler sorgulanmalıdır. Aşağıda buna ilişkin örnek bir kod parçasını görebilirsiniz. Bu kod parçası, yukarıdaki üç saat tipi için ilgili bilgileri sizlere sunar:

Benim makinemde, yukarıdaki kod aşağıdaki gibi bir sonuç verdi. Gördüğünüz üzere high_resolution_clock, steady_clock ile benzer özellikleri sergiliyor.

Saatlere bu kadar eğildikten sonra, sıra geldi, std::chrono konusunda değineceğimiz zaman anlarına bir diğer ifade ile “time_point”.

Zaman Anları (“time_point”)

std::chrono ile sunulan zaman anlarını her ne kadar sona bıraksak da, aslına bakarsanız, bu kütüphanenin en önemli sınıflarından birisidir kendisi. Daha önce de ifade ettiğimiz üzere, zaman anı (“time_point”), bir saat, bu saatin başlangıç zamanı (“epoch”) ve ondan bu yana geçen süre ile tanımlanan anı ifade eder.

İlk yazımda, sizler ile paylaştığım bir figür ile bu kavramı sizlere ifade etmeye çalışacağım. Aslına bakarsanız, zaman anı, belirlenen bu epoch zamanından, belirli bir süre önce ya da sonraki anı ifade eden kavramdır.

Hatta yukarıda, “MakeTimePoint” fonksiyonu ile birlikte herhangi bir takvim tarih/saatinden zaman anı nasıl elde edeceğimizi de görmüştük. Bu sınıf aşağıdaki gibi tanımlanmaktadır:

Her bir saat ile sunulan dört önemli zaman anı bulunmaktadır (tahmin edeceğiniz üzere bunlar sunulan API’ler ile sağlanıyor, kaynak için bu sayfaya bakabilirsiniz:)

  • epoch: başlangıç zaman anı. Bunun için bir API yok. İlgili time_point varsayılan yapıcısı ile oluşturulan, zaman anı nesnesi bunu ifade eder,
  • now(): mevcut zaman anını ifade eden değeri almak için kullanılabilecek statik fonksiyon,
  • min(): bu saat ile ifade edilen minimum zaman anını ifade eden değeri almak için kullanılabilecek statik fonksiyon,
  • max(): bu saat ile ifade edilen maksimum zaman anını ifade eden değeri almak için kullanılabilecek statik fonksiyon.

Yukarıda tanımlamaya başladığımız ChronoUtils sınıfına birkaç fonksiyon daha ekleyelim hadi.

yukarıdaki kodu çalıştırdığımda aşağıdaki gibi bir sonuç alıyoruz:

Zaman anları ile ilgili bir diğer önemli konu da, bu nesneleri (elbette aynı saate ait) birbirleri ile aritmetik operasyonlarda kullanabilmenizdir (toplama, çıkarma, karşılaştırma, vb. Tam liste için referans sayfasına başvurabilirsiniz). Ör. Basitçe iki zaman anı arasındaki süreyi ölçmek istiyoruz ne yapacağız? Aşağıdaki iki üç satırlık kod ile ne yapılabileceğini görebilirsiniz. Umarım kafanızda şimdi daha netleşmiştir. Bu ve benzeri kullanımlara ilişkin de ayrıca bir yazı yazmayı planlıyorum bu arada.

Evet, sevgili yazılımperver dostlarım bir diğer önemli C++ 11 kütüphanesine ilişkin yazımın da sonuna gelmiş bulunuyoruz. Elbette, std::chrono’a ilişkin bütün kabiliyetler bunlar ile sınırlı değil ama umuyorum ki, bu yazılar size, daha detaylı bilgilere dalma ve kabiliyeti kullanmak için yardımcı olur. Bundan sonra da std::chrono ile ilgili bir kaç örnek kod parçasını da sizler ile paylaşıyor olacağım (çeşitli açık kaynak projelerden ya da kendi yazdığım kodlardan). Yazıyı bitirmeden önce, bu kütüphane ile ilgili izlediğim bir video ve bu videoya ilişkin sunumu da sizler ile paylaşıyorum. Bu yazı biraz haftalık video yazılarımdan da rol çaldı ama olsun 🙂

 

Videoya ilişkin sunuma da buradan ulaşabilirsiniz.

Bir sonraki yazımda görüşmek dileğiyle kendinize çok iyi bakın, sağlıkla kalın. Bol kodlu günler 🙂

Kaynaklar

 

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

This site uses Akismet to reduce spam. Learn how your comment data is processed.