4 Mayıs 2016 Çarşamba

std::abort

Giriş
std::abort() Linux ve Windows dünyasındaki sinyallere değindiği için bana hep çok itici geliyor. Bu metodu kullanmamak gerektiğini düşünüyorum.

Kullanmak için şöyle yaparız.
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
  printf("bla bla bla\n");
  abort();
}

Windows
Eğer uygulama console uygulaması ise şöyle bir çıktı alırız.
This application has requested the Runtime to terminate it in an unusual
way. Please contact the application's support team for more information.
Eğer uygulama GUI uygulaması ise şöyle bir mesaj görürürüz.
... has stopped working -- A problem caused the program to stop working correctly. Windows will close the program and notify you if a solution is available.
Windows'ta abort çağrısını durdurmanın bir yolu var mı bilmiyorum.

Linux
Console uygulamasında şöyle bir çıktı alırız.
Aborted
Bu metod çağırılınca SIGABRT sinyali gönderiliyor. Uygulama SIGABRT sinyalini dikkate almamak için kod yazmışsa bile abort bir şekilde default handler'ı çağırıyor.
If the SIGABRT signal is ignored, or caught by a handler that returns, the abort() function will still terminate the process. It does this by restoring the default disposition for SIGABRT and then raising the signal for a second time.
Netice de SIGABRT için signal handler atansa bile, uygulamayı kesinkes kapatıyor.

abort handler
Şöyle bir kod yazılabilir. Ama handler içinde ne yapılabilir bilmiyorum.
#include <stdlib.h>
#include <signal.h>
#include <stdio.h>

void handle_abort(int sig)
{
   // do something (e.g write to log)

}

int main(void)
{    
    signal(SIGABRT, handle_abort);

    abort();
}
assert
assert makrosu ile de std::abort() metodunu çağırır 


3 Mayıs 2016 Salı

tzset

Sistemin saat dilimini değiştirir. Şöyle yaparız.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main (int argc, char *argv[])
{
    struct tm *mt;
    time_t mtt;
    char ftime[10];

    setenv("TZ", "PST8PDT", 1);
    tzset();
    mtt = time(NULL);
    mt = localtime(&mtt);
    strftime(ftime,sizeof(ftime),"%Z %H%M",mt);

    printf("%s\n", ftime);
}

strptime

Giriş
Şu satır dahil edilir.
#include <ctime>
formatlı string'i struct tm yapısına çevirir. Yani C#'taki DateTime.ParseExact () metoduna benziyor. Tekrar formatlı string'e çevirmek için strftime kullanılır.

Bu metodun tersini yani struct tm yapısını formatlı string'e çevirme işini strftime yapar.

1. C dili ile strftime ile formatlanan bir string'i tekrar struct tm yapısına çevirmenin bir yolu yok. Ancak POSIX standardı ile gelen strptime bunu başarabiliyor. 
2. C++ ile std::get_time kullanılabilir.

Temel Kullanım
Şöyle kullanırız.
char myDate[] = "2012-01-01";

struct tm result;
char *end = strptime(myDate, "%Y-%m-%d", &result);
Tüm string'in düzgünce parse edildiğini şöyle kontrol ederiz.
if (end != NULL && *end == '\0') {...}

Hata varsa end null değerine eşittir
if (end == NULL)
{
  printf("Invalid date\n");
}
%Y : Yıl - 2016 gibi
%a : Kısa gün ismi - Mon gibi.
%b : Kısa ay ismi - Mar gibi
%d : gün - 15 gibi
%H : Saat - 09 gibi
%M : Dakika - 23 gibi
%S : Milisaniye - 6000000 gibi
%Z : Saat dilimi

Ay/Gün/Yıl için şöyle yapılır
struct tm tm;
strptime("01/26/12", "%m/%d/%y", &tm);
Saat dakika için şöyle yapılır.
std::tm tm = {};
char* snext = ::strptime("2016-Mar-15 09:23:58.665068", "%Y-%b-%d %H:%M:%S", &tm);

Saat Dilimi
Normalde tm yapısı içinde saat dilimi alanı yok. Bu alan bir GNU extension. Dolayısıyla derlerken time.h'tan önce şu #define'ları yapmak gerekiyor. Aslında benim anladığım sadece _GNU_SOURCE tanımlamasını yapmak yeterli.
#define __USE_XOPEN
#define _GNU_SOURCE

#include <time.h>
Ya da derleyiciye bu seçenekleri vermek gerekiyor.
gcc -Wall test.c -o test -D__USE_XOPEN -D_GNU_SOURCE

Anladığım kadarıyla bu metod saat dilimini çevirirken başarılı değil. Saati dilimi için %Z kullanılır.
Açıklaması şöyle
The %Z format specifier only accepts time zone abbreviations of the local time zone, or the value "GMT". This limitation is because of ambiguity due to of the over loading of time zone abbreviations. One such example is EST which is both Eastern Standard Time and Eastern Australia Summer Time.
Dolayısıyla yerel saat dilimi ve GMT dışında başka bir saat dilimi veremiyoruz. Eğer yerel saat dilimimiz EST ise şöyle yaparız.
const char* format =  "%b %d, %Y %H:%M:%S %Z";
const char* myDate = "Feb 19, 2016 01:00:00 EST";

struct tm result = {0};
char* end = strptime(myDate, format, &result);



29 Nisan 2016 Cuma

std::default_random_engine - Bir Pseudo-random number generator (PRNG)

Giriş
Şu satırı dahil ederiz.
#include<random>
C++ kütüphanesinin gerçekleştirimine bırakılmış. Açıklaması şöyle
Remark: The choice of engine type named by this typedef is implementation-defined. [ Note: The implementation may select this type on the basis of performance, size, quality, or any combination of such factors, so as to provide at least acceptable engine behavior for relatively casual, inexpert, and/or lightweight use. Because different implementations may select different underlying engine types, code that uses this typedef need not generate identical sequences across implementations. — end note ]
Bence bu sınıfı kullanmamak gerekir. Bu sınıf GCC'de minstd_rand0 olarak gerçekleştirilmiş.
VS2012'de ise mt19937 olarak gerçekleştirilmiş .

constructor - default
Sınıfı şöyle yaratabiliriz. Ancak bu durumda seed vermediğimiz için hep aynı sonuçları elde ederiz.
std::default_random_engine generator;
constructor - time
Sistem saatini kullanarak şöyle yaparız.
std::default_random_engine generator( (unsigned int)time(0) );
constructor - chrono time
Chrono kullanarak şöyle yaparız.
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
std::default_random_engine generator (seed));
constructor - random_device
Donanım tabanlı bir üreteci kullanarak şöyle yaparız.
std::default_random_engine generator( std::random_device{}() ); 




20 Nisan 2016 Çarşamba

std::atexit

Giriş
atexit main metod içinden return ile çıkılınca veya exit() metodu çağırılınca işletilen bir metodları eklemek için kullanılır

POSIX standardında pthread_cleanup_push() herhangi bir thread'den çıkınca işlem yapmak için kullanılır.

Şöyle yaparız.
#include <iostream>
#include <cstdlib>

void atexit_handler_1() 
{
    std::cout << "at exit #1\n";
}

void atexit_handler_2() 
{
    std::cout << "at exit #2\n";
}

int main() 
{
    const int result_1 = std::atexit(atexit_handler_1);
    const int result_2 = std::atexit(atexit_handler_2);

    if ((result_1 != 0) or (result_2 != 0)) {
        std::cerr << "Registration failed\n";
        return EXIT_FAILURE;
    }

    std::cout << "returning from main\n";
    return EXIT_SUCCESS;
}


19 Nisan 2016 Salı

std::get_money

Giriş
Şu satırı dahil ederiz.
#include <locale>
std::get_money metodu
Elimizde şöyle bir satır olsun.
$89.99
Bu satırı okumak için şöyle yaparız. Doldurulan parametre long double veya string olmalıdır. Değerin kuruş biriminde olduğu varsayalır.
long double price;   get_money only supports long double
ifstream filein("bookfile.txt");

filein.imbue(std::locale("en_US.UTF-8"));
filein >> std::get_money(price);
price /= 100;  //get_money uses the lowest denomination, in this case cents


15 Nisan 2016 Cuma

std::mutex Sınıfı

Giriş
Yeni mutex tipleri şunlar. Bu tipler POSIX'teki mutex tipleri ile aynı.

std::mutex, std::timed_mutex (C++11)
std::recursive_mutex, std::timed_recursive_mutex (C++11)
std::shared_mutex (C++17) , std::shared_timed_mutex (C++14)

Mutex Lockable kavramını getirir.

Mutex temel olarak şu metodları sunar.
  • lock
  • unlock
  • try_lock
Windows'ta std::mutex
std::mutex Windows'ta altta CriticalSection ile gerçekleştirilmiş. Mutex içinde şöyle bir kod var.
struct _Mtx_internal_imp_t
{   /* Win32 mutex */
    int type; // here MS keeps particular mutex type
    Concurrency::critical_section cs;
    long thread_id;
    int count;
};
Aslında ne ile gerçekleştirilmiş olduğunun pek bir önemi yok. CriticalSection ve std::mutex farklı şeyler. CriticalSection aynı thread tarafından birden fazla kilitlenebilir. Yani recursive bir yapıdır. std::mutex ise sadece bir kere kilitlenebilir.

try_lock metodu
Bu metodu hiç bir zaman kullanmamak en iyisi. unique_lock kullanmak en güzel çözüm.
unique_lock( mutex_type& m, std::try_to_lock_t t );
Şöyle kullanılırsa çok fazla işlemci yer.
std::mutex m;
while (!m.try_lock()) {}
# do work
m.unlock();