Haftalık C++ 39 – std::chrono – 1 (std::chrono::duration)

Evet, sevgili yazılımperver dostlarım, C++ yazılarımıza hız kesmeden devam ediyoruz (evet hızımız 1-2 ppm [post per month] olsa da). C++ 11 STL kütüphanesi ile gelen, önceki bir çok yazımda değindiğim ve muhtemelen C++ 11’e ilişkin değineceğim son önemli kabiliyetlerden biri olan ve uzun süredir sizler ile paylaşmayı planladığım std::chrono kütüphanesini sayfamıza konuk ediyoruz. Bu sefer diğer yazılarımdan farklı olarak, kütüphane ve ilgili kabiliyeti tek bir yazıda aktarmaktansa, bir kaç yazıda sizler ile paylaşmayı planlıyorum. Bu yazı biraz girizgah, temel kavramlarda giriş olacak ve bu kavramlardan birisini masaya yatıracağız. Sonraki yazılarımda da, kalan kavramlara daha yakında bakıyor olacağız.

Her ne kadar, C++ 11’den önce de POSIX uyumlu kütüphaneler sunuluyor olsa da, bunlar standart bir API/arayüz üzerinden sunulmuyorlardı ve genelde ilgili işletim sistemi ve platforma göre de farklılıklar gösterebiliyordu. C++ 11 ile gelen std::chrono kütüphanesinin bizlere kazandırdığı en önemli özellik, bu kabiliyetlerin derlenerek standart bir şekilde sunulması oldu diyebiliriz. Ayrıca, geliştirilen bir çok uygulamada da kullandığımız için de çok önemli bir kabiliyet olduğunu değerlendiriyorum.

Bu kütüphanenin geliştirilmesinde göz önünde bulundurulan bir diğer husus da, zamanlayıcı ve saatlerin farklı sistemlerde farklı çözünürlük ve hassasiyet sunabilecekleridir ki. Özellikle gömülü ve gerçek zamanlı yazılım geliştirenlerinizin, bu konuyu yakinen tecrübe ettiklerini düşünüyorum. Bu noktada, STL geliştiricileri, bu hususları kotarabilmek adına üç önemli kavram geliştirmişlerdir. Bunlar: süre (“duration”), zaman noktası (“time point“) ve saat (“clock“)’tir. Bu yazımda ilk kavram olan, süreyi detaylı bir şekilde sizler ile paylaşacağım. Zaman noktası, belirli bir referans zamandan geçen süreyi ifade eder. Saat’ler ise sistemlerden ilgili referans noktasını ve geçen süreyi almak için kullanılacak olan nesnelerdir.

Aşağıda verilen figür, bu ilişkiyi zannımca gayet iyi göstermektedir:

5.7. Clocks and Timers | The C++ Standard Library: Utilities | InformIT

Bu kütüphaneyi kullanmak için <chrono> başlık dosyasını eklemeniz yeterlidir. Ayrıca çoğu sınıf ve fonksiyonlarda std::chrono adres uzayı içerisinde yer alır (olaki adres uzayını belirtmezsem ve hata alırsanız diye diyorum).

Şimdi, bu yazımızın yakışıklısına bakalım.

Süre (“Duration”)

Bu kütüphane içerisinde belirli bir zaman biriminde tanımlı olan bir süre/zaman aralığını ifade etmek için kullanılan sınıftır. Bu birimler neler olabilir? Saniye, dakika, saat gibi bilindik süre birimleri olabileceği gibi sizlerin tanımlayacağı süre birimleri de olabilir. İlgili birime göre süre değişir ve bunlar arasında dönüşüm yapılabilir. Burada önemli olan bu sürenin bir adet/miktar bilgisi (“tick”) bilgisi içermesidir. Peki bunu nasıl tanımlıyoruz? Hemen referans sayfasında verilen bilgileri inceleylim. Öncelikle sınıf tanımına bakalım:

template< class Rep,  class Period = std::ratio<1> > class duration;

göreceğiniz üzere şablon bir sınıf ve iki temel şablon parametresi kullanılıyor: “Rep” ve “Period”. Amaç, bu iki parametre ile süre merfhumunu ifade etmek.

  • Rep: İlgili süreye ilişkin adet bilgisini ifade edecek aritmetik veri tipini ifade eder ki genelde bu bir tam sayı (int) olur ama zorunlu da değildir (yani float ya da double da olabilir),
  • Period: İlgili sürenin saniye cinsinden karşılığını ifade eder. Bir diğer deyiş ile saniyede kaç adetinin olduğunu ifade eden bir oranı temsil eder. Mealen 🙂 kaç saniye ile bu süreyi ifade ederim. Ör. 1 sn için bu oran 1’dir. Yukarıda da verdiğim sayfada ifade edildiği gibi bu bilgi sadece dönüşümlerde kullanılmaktadır.
    • Eminim burada kullanılan std::ratio sınıfı dikkatinizi çekmiştir. Bu sınıf da, C++ 11 ile gelen ve derleme zamanın rasyonel sayıları ifade etmek için kullanılabilecek bir mekanizma sunan sınıftır. Bu sınıfın tanımı şu şekilde: ‘template<std::intmax_t Num, std::intmax_t Denom = 1> class ratio;’, burada Num, pay’ı ve Denom da paydayı ifade eder.

Yukarıdaki ifade ile temel süreleri ya da kendi tanımlamalarınızı aşağıdaki gibi tanımlayabilirsiniz:

İyi de sevgili yazılımperver, bu süreleri her uygulamam için, hele de temel süre tipleri için her seferinde tanımlamalı mıyım? Elbette hayır, kütüphane içerisinde bilindik tipler için bunlar tanımlı.

Peki hangileri ve bunların tipi ne? Hemen, onları da sizler ile paylaşayım:

Süre Birimi Tip Tanım
Nano saniye std::chrono::nanoseconds std::chrono::duration</*signed integer type of at least 64 bits*/std::nano>
Mikro saniye std::chrono::microseconds std::chrono::duration</*signed integer type of at least 55 bits*/std::micro>
Mili saniye std::chrono::milliseconds std::chrono::duration</*signed integer type of at least 45 bits*/std::milli>
Saniye std::chrono::seconds std::chrono::duration</*signed integer type of at least 35 bits*/>
Dakika std::chrono::minutes std::chrono::duration</*signed integer type of at least 29 bits*/std::ratio<60>>
Saat std::chrono::hours std::chrono::duration</*signed integer type of at least 23 bits*/std::ratio<3600>>

Ayrıca, buraya şunu da ekleyelim ki C++ 20 ile birlikte, gün, hafta, ay ve yıl da eklenmiştir. Sevgili yazılımperver dostlarım, burada şu konuya da yeri gelmişken değineyim. Bazen, C++ 11 veya daha sonra dile eklenen özelliklere, yeni C++ standartları ile de eklemeler olabilmektedir. Bu sebeple bunları kullanırken, elinizin altındaki derleyiciye ve “cppreference” gibi sayfalara başvurmayı unutmayın.

Gelelim bu “duration” sınıfı ile sunulan API’lere.

Bunlardan en önemlisi, “count()” API’si. Bu API kullanarak, ilgili süreyi ifade eden sayısal adeti elde edebilirsiniz. Hemen bir örnek ile bunu inceleyelim:

Bunların yanında, bu sınıf ile birlikte, yukarıdaki örnekte de görebileceğiniz üzere, süreler ile temel aritmetik işlemler ya da karşılaştırma işlemleri de yapabilirsiniz.

Yukarıdaki örneklerde de görebileceğiniz üzere bir takım dolaylı dönüşümler gerçekleştirilebilmektedir. Burada, önemli olan bunun yönüdür. Dönüşüm yönü, daha detaylı birime yönelik olursa bir sıkıntı yok. Yani saniyeyi, milisaniyeye dolaylı bir şekilde sıkıntısız çevirebilirsiniz. Fakat tersi durum, her zaman mümkün olmayabilir ve bilgi/keskinlik kaybedebiliriz. Hemen bir örnek ile buna bakalım:

Peki bu durumlarda ne yapacağız? Bu tarz dönüşümler için de “std::duration_cast” ‘i kullanıyoruz. Nasıl mı hemen bakalım.

Bu dönüşümler özellikle ifade edilen süreler için kullanılan aritmetik veri tipleri farklı ise daha önemli bir hal alır.

Şimdi, bu noktaya kadar gördüğümüz kabiliyetlere ilişkin bir örnek kodu inceleyelim. Bu kod parçası ile amacımız verilen bir süreyi, saat, dakika ve saniye’lere ayırmak:

Burada önemli olan iki nokta: dönüşümlerde yuvarlama değil, kırpma yapılmasıdır (Tavan ya da taban ya da yuvarlama için C++ 17 ile bir takım API’ler de sunulduğunu burada ifade etmekte fayda var). Modülo operatörünün de bu süre değişkenleri ile kullanılabilmesinin ne kadar büyük kolaylık sağlaması.

Yukarıdaki API’ler yanında, statik olan aşağıdaki API’ler de sunulmaktadır:

  • zero(): 0 saniye döner,
  • min/max(): minimum ve maksimum süre bilgilerini döner.

Son olarak C++14 ile gelen, kullanıcı tanımlı değişmezler de mevcut. Bu da ne demek diyorsanız, ilerlemeden önce aşağıdaki yazıma bir göz atabilirsiniz 😉

Haftalık C++ 34 Kullanıcı Tanımlı Değişmezler

Yanlız bunları kullanmak için “std::literals::chrono_literals” adres uzayını ortama eklemeli ya da tiplerin önüne eklemelisiniz. Bunun ile birlikte aşağıdaki kullanımlar mümkün olabilmekte:

Kullanıcı Tanımlı Chrono Değişmezleri
Saat ifade eden std::chrono::duration değişmezi
Saat ifade eden std::chrono::duration değişmezi
Saat ifade eden std::chrono::duration değişmezi
Saat ifade eden std::chrono::duration değişmezi
Saat ifade eden std::chrono::duration değişmezi
Saat ifade eden std::chrono::duration değişmezi

Bunlara ilişkin de basit bir örneğe bakalım:

Evet dostlar, std::chrono kütüphanesine ilişkin, std::duration sınıfına detaylı bir bakış attık. Bu konu ile ilgili kaynaklar kısmına da bir sayfa ekliyorum. Vakti olanlar oraya da bakabilirler. Bir sonraki yazımda görüşmek dileğiyle bol kodlu günler diliyorum.

Kaynaklar

Bir cevap yazın

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

Bu site, istenmeyenleri azaltmak için Akismet kullanıyor. Yorum verilerinizin nasıl işlendiği hakkında daha fazla bilgi edinin.