30 Aralık 2016 Cuma

Sistemin Endian Tipini Anlamak

Örnek 1 - byte pointer
Şöyle yaparız. Little Endian da yazmaya soldan başlayacağımız için ilk byte'a 1 yazılır. char'a cast edince de ilk byte 1 olarak gelir.
bool IsLittleEndian(){

  int a = 1;

  char* ptr = (char*)&a;

  return *ptr;
}
Örnek 2  - byte pointer
Şöyle yaparız.
int i = 7;
char* p = reinterpret_cast<char*>(&i);
if(p[0] == '\x7')
  std::cout << "This system is little-endian\n";
else
  std::cout << "This system is big-endian\n";
Çalışma şekli şudur.
Big endian:

+-----+-----+-----+-----+
|  0  |  0  |  0  |  7  |
+-----+-----+-----+-----+
   ^ pointer to int points here

Little endian:

+-----+-----+-----+-----+
|  7  |  0  |  0  |  0  |
+-----+-----+-----+-----+
   ^ pointer to int points here
Örnek 3 - byte pointer
Ya da şöyle bulunabilir. Big Endian da yazmaya sağdan başladığımız için ilk byte'a 0x01 yazılır. char'a cast edince de ilk byte 1 olarak gelir.
long test = 0x01020304;
char* ptr = (char*)&test;
int isSystemBigEndian = (ptr[0] == 0x01);
Örnek 4 - htons
Şöyle yaparız
#include <stdio.h>
#include <arpa/inet.h>

int main(int argc, char *argv[]) {
  uint16_t num = 123;

  if (htons(num) == num) {
    printf("big endian\n");
  } else {
    printf("little endian\n");
  }
}
Örnek 5 - union
byte pointer yöntemine benziyor. Şöyle yaparız
#include <stdio.h>
#include <stdint.h>

union echeck {
  uint32_t i;
  char c[4];
} echeck = { .c = { 0x01, 0x02, 0x03, 0x04 } };

int main()
{
  if (echeck.i == 0x01020304) {
    printf("big endian\n");
  } else if (echeck.i == 0x04030201) {
    printf("little endian\n");
  } else if (echeck.i == 0x02010403) {
    printf("pdp endian\n");
  } else {
    printf("other endian\n");
  }
  return 0;
}

27 Aralık 2016 Salı

std::chrono::steady_clock Sınıfı

Giriş
Şu satırı dahil ederiz.
#include <chrono>
Bazı derleyiciler steady_clock'ı system_clock olarak sunuyorlar. Aslında bu bir hile. VS 2012'de şöyle tanımlı.
class steady_clock : public system_clock
{   // wraps monotonic clock
public:
  static const bool is_monotonic = true;    // retained
  static const bool is_steady = true;
};
Dolayısıyla insanlar kendi clock sınıflarını yazmak durumunda kalıyorlar. Şöyle yaparız.

Accuracy
VS 2012'ye kadar bu sınıf altta GetSystemTimeAsFileTime() metodunu kullanıyor. Açıklaması şöyle
GetSystemTimeAsFileTime have a precision of 10 to 15 milliseconds.
is_steady alanı
Bu sınıfın is_steady_alanı true döner.
typedef steady_clock clock;
printf("clock::is_steady: %s\n", clock::is_steady ? "yes" : "no");
now metodu
Şöyle yaparız.
std::chrono::steady_clock::time_point tend = std::chrono::steady_clock::now()
                                            + std::chrono::minutes(1);
while (std::chrono::steady_clock::now() < tend)
{
  // do your game
}
period alanı
Açıklaması şöyle. Saniyede kaç defa tick olduğunu belirtir.
A clock's ::period member is defined as "The tick period of the clock in seconds." It is a specialization of std::ratio which is a template to represent ratios at compile-time. It provides two integral constants: num and den, the numerator and denominator of a fraction, respectively.
Kendi saatimi yazarken şöyle yaparız.
struct qpc_clock {
  typedef std::chrono::nanoseconds  duration;      // nanoseconds resolution
  typedef duration::rep             rep;
  typedef duration::period          period;

  ...
};
period::num alanı 1 değerine sahiptir.

period::den alanını yazdırırsak örneğin 1000000 elde ederiz. Saniyede 1 milyon tick var anlamına gelir. Bu saatimizin mikrosaniye çözünürlüğünde olduğunu gösterir.

1000000000 (1 milyar) elde edersek saatimizin nanosaniye çözünürlüğünde olduğunu gösterir.
Kendi saatimizi yazarken şöyle yaparız. Önce Windows'taki zaman bulunur. Daha sonra bu benim saatimiz çözünürlüğüne çevrilir. Örneğin Windows'ta 1000000 nanosaniye geçmiş olsun. Benim saatim ise 1/1000000 çözünürlüğünde. Çarpma işleminden sonra döndürülen duration'daki count alanı 1 olur.
LARGE_INTEGER counter;
QueryPerformanceCounter(&counter);
return time_point(duration(static_cast<rep>((double)
  counter.QuadPart / frquency.QuadPart *
  period::den / period::num)
));


26 Aralık 2016 Pazartesi

std::timed_mutex Sınıfı

Giriş
Şu satırı dahil ederiz.
#include <mutex>
Açıklaması şöyle
 std::timed_mutex has non-recursive ownership semantics. It's forbidden to acquire the lock (include try_lock family) second time on the same thread.
Mutex'e ek olarak şu metodları sunar.
try_lock_for (duration)
try_lock_until (time_point)
Constructor
Şöyle yaparız.
std::timed_mutex m;
lock ve unlock metodları
Şöyle yaparız.
void test()
{
  m.lock();
  ...
  m.unlock();
}
try_lock_for metodu
Şöyle yaparız.
bool got_lock = m.try_lock_for (std::chrono::seconds(10));
if (got_lock) {
  ...
  m.unlock();}


22 Aralık 2016 Perşembe

Store

Giriş
Bir projede Cache diye isimlendirdiğimiz boost multi_index'e benzeye bir yapı kurduk. Tasarım kararları şöyleydi.

1. Cache N (örneğin 100) tane farklı veri tipi içerebilecek
2. Her veri tipi için kapasite belirlenebilecek. Yani en fazla N tane A tipi nesne saklanabilecek. Her A instance'ı için N tane de sample saklamayı düşündük ancak sonrada ihtiyacımız olmadığı ortaya çıktı.
3. Veri tipine dizi olarak erişilebilecek. Dizi bir LRU list olacak. Böylece kapasite üst sınırına erişirsek en eski nesne silinebilecek.
4. Veri tipine hash ile O (1)'de erişilebilecek. O (1)'de get, update, delete işlemleri yapılabilecek.

ObjectRoot Sınıfı
Sınıfın ismi konusunda çok kafa patlatmak gerekti :) Bu sınıf tüm veri tiplerinin ortak atası.

getId metodu
İmzası şöyle. Bu metod ile kaç numaralı veri tipi olduğu belirtilir. Store içinde ilgili StoreManager kolayca bulunur.
virtual int getId ();
hashCode metodu
İmzası şöyle
virtual int hashCode ();
equals metodu
İmzası şöyle. Kendi hash yapımızı kullandığımı için eşitlik kontrolü olarak bu metodu kullandık.
virtual bool equals (ObjectRoot* right);
clone metodu
İmzası şöyle.
virtual ObjectRoot* clone ();
Daha sonra bu metodu bir havuzdan nesne alacak hale getirdik. Havuza giren nesneleri temizlemek için reset diye bir metod yazmak gerekti.

IntrusiveTopicInstance Sınıfı
Linked list icin right ve left isimli iki pointer tutar.
Hash Index #1 icin h1right ve h2left isimli iki pointer tutar.

HasMap Sınıfı 
Bu sınıf ObjectRoot nesnelerini hash'leyerek saklar. STL hash yapılarını kullanmak yerine kendi sınıfımızı yazdik.

TopicManager Sınıfı
Bu sınıf hem sequential hem de hash indeks'i barındırır. Her manager nesnesine dışarıdan bir TopicDefinition nesnesi verilir. Bu yapıda 
int ID
int maxIntanceCount
int maxSampleCount
bool hasHashIndex

alanları bulunur.

TopicList Sınıfı 
Bu sınıf 100 tane Topic barındıran bir dizi. 

ProcessorList Sınıfı 
Bu sınıf 5 tane IProcessor barındıran bir dizi. 

IProcessor Arayüzü 
Sadece arayüz sağlar. 
İki tane önemli metodu var.
void Process (ObjectRoot* pObject)
void PreDispose (ObjectRoot * pObject);

Cache Sınıfı
Bu sınıf N tane TopicManager nesnesini barındırır. 

20 Aralık 2016 Salı

Singleton

call_once Singleton
Lazy Singleton mutex kullanmadan şöyle yazılabilir.
class Singleton{

private:
  static std::unique_ptr<Singleton> instance;
  static std::once_flag onceFlag;
  Singleton();

public:
  static Singleton& getInstance(){
    std::call_once(onceFlag,[&]{
       instance = std::unique_ptr<Singleton>(new Singleton());    
    });
    return *instance;
  }

};
Thread Local Static Singleton
Template kullanarak şöyle yaparız. static nesne uygulamadan çıkarken (application exit) temizlenir (cleanup).
template <class T>
class Singleton
{
public:
  static T& getinstance()
  {
    static T t;
    return t;
  }
};
Eğer static uygulamadan çıkarken otomatik yok olmasın istersek pointer kullanırız. Şöyle yaparız.
Singleton & Singleton::getInstance()
{
  static Singleton* instance = new Singleton ();
  return *instance;
}