Yığınaklar (Obstacks)
Önceki Yazılım Verisine Saklama Alanı Ayrılması Sonraki
Yığınaklar (Obstacks)
Bir yığınak bir nesne yığını içeren bir bellek havuzudur. Çok sayıda ayrı yığınak oluşturabilir ve nesneleri bunların içinde ayırabilirsiniz. Her yığınağın içinde ayrılan son nesneye karşılık daima ilki serbest bırakılır ancak her yığınak diğerinden bağımsızdır.
Serbest bırakma ile ilgili bu kısıtlama dışında yığınaklar tamamen geneldir: Bir yığınak farklı boyutlarda olabilen çok sayıda nesne içerebilir. Yığınaklar makrolarla gerçeklenmiştir. Böylece, nesneler küçük oldukları sürece ayırma işlemi çok hızlı yapılır. Her nesneyi belli bir adım aralığı ile oluşturmak gerektiğinden her nesne için sabit yer ayrılır.
Yığınak Oluşturma
Yığınaklar üzerinde işlem yapmak için gereken araçlar obstack.h başlık dosyasında bildirilmiştir.
struct obstack
veri türü
Bir yığınak struct obstack türünde bir veri yapısı ile ifade edilir. Bu veri yapısı çok küçük ve sabit boyutludur. Nesnelerin içinde ayrıldıkları alanın nasıl bulunacağı ve yığınağın durumu hakkında bilgileri kaydeder. Nesnelerin kendileri hakkında bir bilgi içermez. Bu yapının içeriğine doğrudan erişmeye çalışmayın; sadece bu bölümde açıklanmış olan işlevleri kullanın.
Değişkenleri struct obstack türünde bildirebilir ve onları yığınak olarak kullanabilirsiniz ya da bir yığınağı diğer nesne çeşitlerinde olduğu gibi özdevimli olarak ayırabilirsiniz. Yığınakların özdevimli olarak ayrılması yazılımınızın çok sayıda farklı yığınağa sahip olmasını mümkün kılar. (Hatta bir yığınak yapısını bir başka yığınağın içinde ayırabilirsiniz ancak bu pek kullanışlı olmaz.)
Yığınaklar ile çalışan işlevlerin tümü hangi yığınağın kullanılacağının belirtilmesini gerektirir. Bunu struct obstack * türünden bir gösterici ile yapabilirsiniz. Bundan sonra bir yığınaktan bahsettiğimizde ona bir gösterici üzerinden eriştiğiniz kabul edilecektir.
Yığınaktaki nesneler tomar olarak adlandırılan büyük bloklar halindedir. struct obstack yapısı ise bu tomarlardan oluşan bir zincirin kaydını tutar.
Yığınak kütüphanesi, önceki tomara sığmayan bir nesne ayırdığınızda, yeni bir tomar oluşturur. Yığınak kütüphanesi tomarları özdevinimli olarak yönettiğinden bu işlemlere fazla dikkat etmeniz gerekmez. Ancak, yığınak kütüphanesinin bir tomarı ayırırken kullanacağı bir işlevi sağlamanız gerekir. Bu işlev malloc işlevini doğrudan ya da dolaylı kullanmalıdır. Ayrıca bir tomarı serbest bırakacak bir işlev daha sağlamanız gerekir. Bu konular aşağıdaki bölümde açıklanmıştır.
Yığınakları Kullanıma Hazırlama
Yığınak işlevlerini kullanmayı tasarladığınız her kaynak dosyası obstack.h başlık dosyasını aşağıdaki gibi içermelidir:
#include <obstack.h>
Ayrıca, kaynak dosyası obstack_init makrosunu da kullanıyorsa, yığınak kütüphanesi tarafından kullanılmak üzere iki işlev veya makro bildirmeli ya da tanımlamalıdır. Biri, içine nesnelerin paketleneceği bellek tomarlarını ayırmada kullanılacak olan obstack_chunk_alloc işlevi diğeri ise, içindeki nesneler serbest bırakıldığında bellek tomarlarını sisteme döndürecek olan obstack_chunk_free işlevidir. Bu makrolar kaynak dosyaları içinde yığınaklar kullanılmadan önce tanımlanmış olmalıdır.
Bunlar xmalloc (Özgür Bellek Ayırma) araortamı üzerinden malloc kullanacak şekilde tanımlanır. Bu tanımlama aşağıdaki makro tanım çifti ile yapılır:
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
Yığınak kullanarak ayırdığınız bellek gerçekte malloc'dan gelmesine karşın, yığınakların kullanılması daha hızlıdır çünkü daha büyük bellek blokları halinde olduğundan malloc daha az sıklıkta çağrılır. Daha ayrıntılı bilgi için Yığınak Tomarları bölümüne bakınız.
Çalışma anında yazılım, yığınak olarak bir struct obstack yapısını kullanmaya başlamadan önce bir obstack_init çağrısı ile yığını ilklendirmelidir.
int obstack_init
(struct obstack *yığınak)
işlev
Nesnelerin ayrılacağı yığınak nesnesini ilklendirir. Bu işlev yığınağın obstack_chunk_alloc işlevini çağırır. Eğer bellek ayırma işlemi başarısız olursa obstack_alloc_failed_handler tarafından gösterilen işlev çağrılır. obstack_init işlevi daima 1 ile döner.
Uyumluluk bilgisi
Yığınak kütüphanelerinin daha şekilci sürümleri bu işlev başarısız olduğunda 0 ile döner.
Aşağıda bir yığınak için alan ayrılması ve onun ilklendirilmesi üzerine iki örnek bulunmaktadır. İlkinde yığınak bir durağan değişkendir:
static struct obstack myobstack;
…
obstack_init (&myobstack);
İkincisinde ise yığınak kendisini özdevimli ayırmaktadır:
struct obstack *myobstack_ptr
  = (struct obstack *) xmalloc (sizeof (struct obstack));

obstack_init (myobstack_ptr);
obstack_alloc_failed_handler
değişken
Bu değişkenin değeri, obstack_chunk_alloc işlevi bellek ayırma sırasında başarısız olduğunda çağıracağı işleve bir göstericidir. Bu göstericiye belirteceğiniz işlev ya exit (Yazılımın Sonlandırılması) ya da longjmp (Yerel Olmayan Çıkışlar) çağırmalı, yani dönmemelidir.
void my_obstack_alloc_failed (void)
…
obstack_alloc_failed_handler = &my_obstack_alloc_failed;
Bir Yığınağa Nesne Eklenmesi
Bir nesne için bir yığınakta yer ayırmanın en kestirme yolu, malloc çağırır gibi obstack_alloc çağrısı yapmaktır.
void *obstack_alloc
(struct obstack *yığınak,
 int             boyut)
işlev
İşlev, bir yığınakta boyut baytlık bir ilkendirilmemiş blok ayırır ve onun adresi ile döner. Burada yığınak, içinde blok ayrılacak olan yığınağı belirten struct obstack yapısının adresidir. Her yığınak işlevi ya da makrosu ilk argüman olarak daima bir * yığınak belirtmeyi gerektirir.
Bellekte yeni bir tomar ayrılması gerekirse bu işlev yığınağın obstack_chunk_alloc işlevini çağırır. obstack_chunk_alloc işlevi bellek ayırmada başarısız olursa obstack_alloc_failed_handler işlevi çağrılır.
Aşağıdaki örnekte, string_obstack yığınağında string dizgesinin bir kopyası için yer ayrılmaktadır:
struct obstack string_obstack;

char * copystring (char *string)
{
  size_t len = strlen (string) + 1;
  char *s = (char *) obstack_alloc (&string_obstack, len);
  memcpy (s, string, len);
  return s;
}
İçeriğini belirterek bir blok ayırmak için obstack_copy işlevi kullanılır:
void *obstack_copy
(struct obstack *yığınak,
 void           *adres,
 int             boyut)
işlev
Bu işlev bir blok ayırır ve adres adresinden başlayan boyut baytlık veriyi ayrılan yere kopyalayarak bloğu ilklendirir. obstack_chunk_alloc tarafından bellek ayırma işlemi başarısız olursa obstack_alloc_failed_handler işlevini çağırır.
void *obstack_copy0
(struct obstack *yığınak,
 void           *adres,
 int             boyut)
işlev
obstack_copy işlevi gibidir, farklı olarak, bir boş karakter ekler. Bu fazladan bayt boyut'a dahil değildir.
Bu işlev, bir yığınağa bir dizgeyi bir boş sonlandırmalı dizge olarak kopyalamanın en uygun yoludur. Aşağıdaki bir kullanım örneğine bakınız:
char * obstack_savestring (char *addr, int size)
{
  return obstack_copy0 (&myobstack, addr, size);
}
Önceki örnekte aynı işi yapan copystring işlevi için malloc (Özdevimli Olarak Basit Bellek Ayırma) kullanılmıştı.
Bir Yığınaktan Nesne Çıkarılması
Yığınaktan bir nesneyi çıkarmak için obstack_free işlevi kullanılır. Bir yığınak aslında bir nesne yığıtı olduğundan, serbest bırakılan nesne kendinden sonra ayrılan diğer nesnelerin de serbest bırakılmasına sebep olur.
void obstack_free
(struct obstack *yığınak,
 void           *nesne)
işlev
nesne hiçbir şey göstermiyorsa yığınaktan tüm nesneler çıkarılır. Aksi takdirde, gösterdiği nesne ve o nesneden sonra yığınağa konulmuş tüm nesneler serbest bırakılır.
Not
nesne hiçbir şey göstermiyorsa işlevin sonucu ilklendirilmemiş bir yığınaktır. Bir yığınağı boşaltmak ve onu kullanılabilir yapmak isterseniz obstack_free işlevini yığınaktaki ilk nesnenin göstericisi ile çağırmalısınız:
obstack_free (obstack_ptr, first_object_allocated_ptr);
Bir yığınaktaki nesneler tomarlar halinde gruplanır. Bir tomardan tüm nesneler çıkarıldığında yığınak kütüphanesi tomarı özdevinimli olarak serbest bırakır (Bkz. Yığınakları Kullanıma Hazırlama). Böylece diğer yığınaklar ve bellek ayırma işlemleri için tomar alanı yeniden kullanılabilir.
Yığınak İşlevleri ve Makroları
Derleyiciye bağlı olarak, yığınakların kullanılmasını sağlayan arayüzler bir işlev ya da makro olarak tanımlanabilir. Yığınak oluşumu ISO C ve geleneksel C içeren tüm C derleyicileri ile çalışır, ancak GNU C derleyicisi dışındaki derleyicileri kullanacaksanız almanız gereken bazı önlemler vardır.
Eski moda, ISO C olmayan bir derleyici kullanıyorsanız, tüm yığınak işlevleri aslında birer makro olarak tanımlanmalıdır. Bu makroları birer işlev gibi çağırabilirsiniz ama bir işlevin sağladığı diğer kolaylıklardan (işlev adresini almak gibi) yararlanamazsınız.
Makroların çağrılması bir özel önlem almayı gerektirir: İsim olarak, ilk terim (yığınak göstericisi) herhangi bir yan etki barındırmamalıdır. Örneğin,
obstack_alloc (get_obstack (), 4);
yazarsanız, get_obstack defalarca çağrılacaktır. Ya da yığınak göstericisi argümanı olarak *obstack_list_ptr++ kullanırsanız, defalarca arttırım uygulanacağından çok tuhaf sonuçlar elde edebilirsiniz.
ISO C'de her işlevin bir makro bir de işlev olarak tanımı vardır. Bir işlevi çağırmadan sadece adresini almak isterseniz işlev tanımı kullanılır. Normal bir işlev çağrısında ise öntanımlı olarak makro tanımı kullanılır, ancak isterseniz işlev ismini parantez içinde kullanarak işlev tanımını kullanabilirsiniz. Örnek:
char *x;
void *(*funcp) ();

/* Makro kullanımı.  */
x = (char *) obstack_alloc (ynk_gstr, boyut);

/* İşlev çağrısı.  */
x = (char *) (obstack_alloc) (ynk_gstr, boyut);

/* İşlev adresinin alınması.  */
funcp = obstack_alloc;
Aynı durum ISO C'deki standart kütüphane işlevleri için de geçerlidir. Bkz. Makro Olarak Tanımlanmış İşlevler.
Uyarı
ISO C'de bile, makroları kullanırken ilk terimin yan etkiler oluşturmasına karşı önlem almanız gereklidir.
GNU C derleyicisini kullanıyorsanız, bu önlem gereksizdir, çünkü GNU C'deki çeşitli dil oluşumları, makroların, her argümanının bir kere hesaplanmasını sağlayacak şekilde tanımlanmasına izin verir.
Büyüyen Nesneler
Yığınak tomarları içindeki bellek sıralı erişimle kullanıldığından, bir nesneyi, nesne için ayrılan alanın sonuna bayt ya da baytlar ekleyerek adım adım oluşturmak mümkündür. Bu teknikle, bir nesneye veri aktarırken acaba yer kaldı mı diye düşünmeniz gerekmez. Bu tekniğe Nesnelerin Büyütülmesi diyoruz. Bu bölümde nesneleri sonuna veri ekleyerek büyütmek için kullanılan özel işlevlere yer verilmiştir.
Bu işlevlerden birini kullanarak nesneye veri eklemek istediğinizde nesnenin büyütülmesi özdevinimli olarak gerçekleştiğinden, bir nesneyi büyütmeye başladığınızda özel olarak hiçbir şey yapmanız gerekmez. Ancak büyütme işlemi bittiğinde, bittiğinin belirtilmesi gerekir. Bunun için obstack_finish işlevi kullanılır.
Büyütme işleminin bittiği belirtilene kadar her veri eklemesinde nesne yeni bir tomara kopyalandığı için nesnenin büyütülmesi bitene kadar nesnenin gerçek adresi bilinmez.
Bir yığınak bir nesneyi büyütmek için kullanıldığında, bir başka nesneyi o yığına yerleştiremezsiniz. Bunu yapmayı denerseniz, eklediğiniz nesneye ayrı bir nesne olarak erişilemez; büyütülen nesneye bir alan eklenmiş olur ve eklediğiniz nesne büyütülen nesnenin bir parçası haline gelir.
void obstack_blank
(struct obstack *yığınak,
 int             boyut)
işlev
Bir büyüyen nesneye alan oluşturmak için kullanılır. obstack_blank ilklendirilmemiş bir alan oluşturur.
void obstack_grow
(struct obstack *yığınak,
 void           *veri,
 int             boyut)
işlev
İlklendirilmiş bir blok eklemekte kullanılır. obstack_grow işlevi nesne büyüten bir obstack_copy işlevi gibi düşünülebilir. Büyüyen nesneye boyut uzunlukta veri ekler.
void obstack_grow0
(struct obstack *yığınak,
 void           *veri,
 int             boyut)
işlev
Nesne büyüten bir obstack_copy0 işlevi gibi düşünülenilir. Büyüyen nesneye boyut uzunlukta veri sonuna bir boş karakter getirilerek eklenir.
void obstack_1grow
(struct obstack *yığınak,
 char            c)
işlev
obstack_1grow işlevi büyüyen nesneye bir defada sadece bir karakter eklemek için kullanılır. Büyüyen nesneye c karakterini içeren bir bayt ekler.
void obstack_ptr_grow
(struct obstack *yığınak,
 void           *veri)
işlev
Bir oluşumun gösterici değerini büyüyen nesneye eklemek için kullanılır. Büyüyen nesneye veri’nin değerini içeren sizeof (void *) bayt ekler.
void obstack_int_grow
(struct obstack *yığınak,
 int             veri)
işlev
Büyüyen nesneye int türünde tek bir değer eklemek için kullanılır. Büyüyen nesneye sizeof (int) bayt ekler ve veri'nin değeri ile ilklendirir.
void *obstack_finish
(struct obstack *yığınak)
işlev
Bir büyüyen nesne ile işiniz bittiğinde onu kapatmak ve son adresini almak için bu işlevi kullanacaksınız.
Büyüyen bir nesneyi bitirdiğinizde, yığınak, normal nesne ayırma ya da yeni bir büyüyen nesne oluşturmak için kullanılabilir.
Bu işlev obstack_alloc işlevi gibi aynı koşullar altında bir boş gösterici ile de dönebilir. Bkz. Bir Yığınağa Nesne Eklenmesi.
Bir büyüyen nesne ile çalışırken ne büyüklüğe ulaştığını bilmek isteyebilirsiniz. Bir büyüyen nesneyi bitirmeden obstack_object_size işlevini kullanarak yığınağın eriştiği boyutu öğrenebilirsiniz:
int obstack_object_size
(struct obstack *yığınak)
işlev
Bu işlev, büyüyen nesnenin o andaki bayt cinsinden uzunluğu ile döner. Bu işlevin nesneyi bitirmeden çağrılabileceğini unutmayın. Nesneyi bitirdikten sonra obstack_object_size işlevi sıfır değeri ile döner.
Bir büyüyen nesne oluşturduktan sonra onu iptal etmek isterseniz, önce onu bitirin sonra da serbest bırakın. Örnek:
obstack_free (obstack_ptr, obstack_finish (obstack_ptr));
Nesne bir büyüyen nesne değilse bu etkisizdir.
Bir nesneyi küçültmek için obstack_blank işlevini bir negatif boyutla çağırabilirsiniz. Ancak nesneyi küçültürken boyunun sıfırın altına inmemesine dikkat edin, aksi takdirde neler olacağı bilinemez.
Çok Hızlı Büyüyen Nesneler
Büyüyen nesneleri büyütürken o anki tomarın yeterli yere sahip olup olmadığının denetlenmesi için işlevler içinde yapılan işlemler bir sürü masraf kalemi oluşturur. Üstelik siz bu nesneleri küçük küçük adımlarla ve sıklıkla büyütürseniz bu israf kaydadeğer olmaya başlar.
Bu masrafı, bu denetimlerin yapılmadığı özel "hızlı büyütme" işlevlerini kullanarak düşürebilirsiniz. Sağlam bir yazılım istiyorsanız bu denetimleri kendiniz yapmalısınız. Bu denetimi en basit yolla, nesneye veri eklemeye hazırlanırken yaparsanız hiçbir şeyi saklamak zorunda kalmazsınız, çünkü normal büyütme işlevleri de bunu zaten böyle yapar. Bu düzenlemeyi ne kadar az sıklıkta yaparsanız yazılımınız o kadar hızlı olur.
obstack_room işlevi kullanılan tomar içindeki kullanılabilir alanın miktarı ile döner:
int obstack_room
(struct obstack *yığınak)
işlev
Bu işlev, kullanılmakta olan (ya da yeni oluşturulan) yığınak büyüyen nesnesine yeni bir tomar oluşturmadan hızlı büyütme işlevleri kullanılarak eklenebilecek baytların sayısı ile döner.
Ne kadar yeriniz olduğunu bildiğinize göre aşağıdaki hızlı büyütme işlevlerini kullanarak büyüyen nesnenize güvenle veri ekleyebilirsiniz:
void obstack_1grow_fast
(struct obstack *yığınak,
 char            c)
işlev
yığınak’taki büyüyen nesneye c karakterini içeren tek bir bayt eklemekte kullanılır.
void obstack_ptr_grow_fast
(struct obstack *yığınak,
 void           *veri)
işlev
yığınak’taki büyüyen nesneye veri değerini içeren sizeof (void *) bayt ekler.
void obstack_int_grow_fast
(struct obstack *yığınak,
 int             veri)
işlev
yığınak’taki büyüyen nesneye veri değerini içeren sizeof (int) bayt ekler.
void obstack_blank_fast
(struct obstack *yığınak,
 int             boyut)
işlev
yığınak’taki büyüyen nesneye ilklendirmeksizin boyut bayt ekler.
Kalan yeri obstack_room ile tespit ettiğinizde yeterli yer kalmadığını öğrenirseniz hızlı büyütme işlevlerini kullanmak artık güvenilir olmaz. Bu durmda, basitçe normal büyütme işlevlerine geçmek gerekir. Sonuç olarak, az yer kalmışsa normal büyütme işlevleri yeni bir tomar açar ve böylece bol bol yeriniz olur.
Demek ki, obstack_room ile yeterli yer kalmadığını her anladığınızda normal büyütme işlevlerini kullanabilecek ve nesneniz yeni bir tomara kopyalandığında tekrar hızlı büyütme işlevlerini kullanabileceğiniz güvenilir bir alana sahip olabileceksiniz.
Burada bir örnek var:
void dizge_ekle (struct obstack *yiginak, const char *dizge, int uzunluk)
{
  while (uzunluk > 0)
  {
    int bosyer = obstack_room (yiginak);
    if (bosyer == 0)
    {
      /* Yeterli boş yer yok. Bir karakter eklersek nesnemiz
         yeni bir tomara kopyalacak ve boş yer olacak. */
      obstack_1grow (yiginak, *dizge++);
      uzunluk--;
    }
    else
    {
      if (bosyer > uzunluk)
        bosyer = uzunluk;

      /* Boş yer olduğuna göre hızlı olarak ekleme yapabiliriz. */
      uzunluk -= bosyer;
      while (bosyer-- > 0)
        obstack_1grow_fast (yiginak, *dizge++);
    }
  }
}
Bir Yığınağın Durumu
Burada açıklanan işlevler kullanımdaki bir yığınağın durumu hakkında bilgi verirler. Buradaki işlevleri büyümekte olan nesneler hakkında bilgi edinmek için de kullanabilirsiniz.
void *obstack_base
(struct obstack *yığınak)
işlev
Bu işlev yığınak'da büyüyen nesnenin başlangıçta geçici olarak kullanılan adresi ile döner. Bu işlevin hemen ardından büyüyen nesne bitirilirse bu adres dönecektir. Ama bitirme işlemini nesneyi fazlaca büyüttükten sonra yaparsanız dönen adres farklı olabilecektir.
Büyüyen bir nesne yoksa, sonraki nesnenin başlangıç adresi ile döner (tomarın yeni bir nesne için yeterli olduğu varsayımıyla).
void *obstack_next_free
(struct obstack *yığınak)
işlev
yığınak'ın bulunduğu tomardaki ilk serbest baytın adresi ile döner. Bu adres, büyümekte olan nesnenin sonundadır. Eğer nesne bir büyüyen nesne değilse, obstack_base ile dönen adresin aynısı döner.
int obstack_object_size
(struct obstack *yığınak)
işlev
Büyümekte olan nesnenin uzunluğu ile döner. Bu değer aşağıdaki ifade ile elde edilen değere eşittir:
obstack_next_free (yiginak) - obstack_base (yiginak)
Yığınaktaki Verinin Adreslenmesi
Her yığınak bir adres boyu’na sahiptir. Yığınağa konulan ilk nesne özdevimli olarak bir adrese konur ve her nesne bu adresin belirtilen adres boyunun katlarındaki adreslere yerleştirilir. Öntanımlı olarak bu adres boyu her veri türünü tutabilecek bir nesneye gereken kadardır.
Adres boyunu öğrenmek için obstack_alignment_mask işlevi kullanılır:
int obstack_alignment_mask
(struct obstack *yığınak)
makro
Dönen değer bir bit maskesidir; değeri 1 olan bir bit, nesnenin adresinin ilgili bitinin 0 olması gerektiğini belirtir. Maske değeri, nesneler ikinin kuvvetlerindeki adres boylarında adreslendiğinden, ikinin kuvveti eksi birdir. Öntanımlı maske değeri hizalı nesnelerin her veri türünü tutmasını mümkün kılacak bir değerdir: Örneğin, maske değeri 3 ise adresleri 4'ün katları olan her veri türü saklanabilir. Maske değeri sıfırsa adresleme birer baytlıktır ve bu durumda adresleme yoktur denir.
obstack_alignment_mask makrosu bir sol taraf değeri olarak yorumlanır, yani maskı siz değiştirebilirsiniz. Örnek:
obstack_alignment_mask (yiginak) = 0;
Burada, belirtilen yığınakta adresleme işlemi kapatılmıştır.
Not
Adresleme boyu değişikliği bir nesne ayrıldıktan sonra ya da bitirildiğinde etkisizdir. Bir nesneyi hiç büyütmeden yeni bir adres boyu belirtip nesneyi obstack_finish ile sıfır uzunlukta bitirip sonraki nesneler için yeni adres boyunu geçerli yapabilirsiniz.
Yığınak Tomarları
Yığınaklar kendilerine büyük tomarlar halinde yer ayırırlar ve bu alanı sizin isteklerinizi karşılamak üzere parsellerler. Başka bir tomar uzunluğu belirtilmediği sürece öntanımlı tomar uzunluğu 4096 bayttır. Tomarın 8 baytlık bölümü nesneleri saklamakta kullanılmaz. Bir tomar uzunluğu belirtilmiş bile olsa, büyük nesneler için gerekirse daha büyük uzunlukta tomarlar ayrılabilir.
Yığınak kütüphanesi tomarları sizin tanımlayacağınız obstack_chunk_alloc işlevini çağırarak ayırır. İçindeki tüm nesnelerin çıkarılmasıyla boşalan bir tomarı yine sizin tanımlayacağınız obstack_chunk_free işlevini çağırarak serbest bırakır.
Bu iki işlev, obstack_init kullanılan her kaynak dosyasında ya makro olarak tanımlanmalı ya da işlev olarak bildirilmelidir. Bunlar makro olarak çoğunlukla aşağıdaki gibi tanımlanır:
#define obstack_chunk_alloc malloc
#define obstack_chunk_free free
Bunlar basit makrolardır (argümansız). Argümanlı makro tanımları çalışmayacaktır. Bu, obstack_chunk_alloc veya obstack_chunk_free nin, tek başına kendisi bir işlev değilse bir işlev ismi olarak kullanılacağından böyledir.
Tomarları malloc ile ayırırsanız tomar boyu ikinin kuvvetlerinden biri olmalıdır. Öntanımlı tomar boyu 4096 bayttır. Bu boyut, son tomarda kullanılmadan çok fazla bellek kalmasına yol açmayacak kadar küçük, sıradan isteklere yanıt verecek kadar da büyük bir bellek boyudur.
int obstack_chunk_size
(struct obstack *yığınak)
makro
Belirtilen yığınağın tomar boyu ile döner.
Bu makro bir sol taraf değeri olarak yorumlandığından ona yeni bir değer atayarak farklı bir tomar boyu belirtebilirsiniz. Bunun yapılması, mevcut ayrılmış tomarları etkilemez, sadece bu atamadan sonra ayrılan tomarlar etkilenir. Bir tomarı bu yöntemle daha küçük boylarda ayırmak mümkünse de, çok fazla nesne kullanacaksanız daha büyük tomar boyları daha verimli olacaktır. Örnek:
if (obstack_chunk_size (yiginak-gstr) < yeni-tomar-boyu)
  obstack_chunk_size (yiginak-gstr) = yeni-tomar-boyu;
Yığınak İşlevlerinin Listesi
Burada yığınaklarla ilgili işlevlerin bir özet listesine yer verilmiştir. Her biri ilk argüman olarak struct obstack * türünde bir yığınak adresi alır.
void obstack_init
(struct obstack *yığınak)
işlev
Bir yığınağı ilklendirir. Bkz. Yığınak Oluşturma.
void *obstack_alloc
(struct obstack *yığınak,
 int             boyut)
işlev
İlklendirmeden boyut baytlık bir nesneye yer ayrılır. Bkz. Bir Yığınağa Nesne Eklenmesi.
void *obstack_copy
(struct obstack *yığınak,
 void          *adres,
 int            boyut)
işlev
İçeriğini adres’ten kopyalayarak boyut baytlık bir nesneye yer ayırır. Bkz. Bir Yığınağa Nesne Eklenmesi.
void *obstack_copy0
(struct obstack *yığınak,
 void          *adres,
 int            boyut)
işlev
İçeriğini adres’ten kopyalayarak boyut baytlık bir nesneye sonuna bir boş karakter ekleyerek yer ayırır. Bkz. Bir Yığınağa Nesne Eklenmesi.
void obstack_free
(struct obstack *yığınak,
 void          *nesne)
işlev
nesne ve nesne’den sonra ayrılan tüm nesneleri yığınaktan çıkarır (serbest bırakır). Bkz. Bir Yığınaktan Nesne Çıkarılması.
void obstack_blank
(struct obstack *yığınak,
 int             boyut)
işlev
Büyüyen nesneye ilklendirilmemiş boyut bayt ekler. Bkz. Büyüyen Nesneler.
void obstack_grow
(struct obstack *yığınak,
 void          *adres,
 int            boyut)
işlev
Büyüyen nesneye içeriğini adres’ten kopyalarak boyut bayt ekler. Bkz. Büyüyen Nesneler.
void obstack_grow0
(struct obstack *yığınak,
 void          *adres,
 int            boyut)
işlev
Büyüyen nesneye içeriğini adres’ten kopyalarak boyut bayt artı bir boş karakter ekler. Bkz. Büyüyen Nesneler.
void obstack_1grow
(struct obstack *yığınak,
 char            karakter)
işlev
Büyüyen nesneye karakter içeren bir bayt ekler. Bkz. Büyüyen Nesneler.
void *obstack_finish
(struct obstack *yığınak)
işlev
Büyüyen nesneyi kapatarak (bitirerek) son adresi ile döner. Bkz. Büyüyen Nesneler.
int obstack_object_size
(struct obstack *yığınak)
işlev
Büyüyen nesnenin o andaki boyu ile döner. Bkz. Büyüyen Nesneler.
void obstack_blank_fast
(struct obstack *yığınak,
 int            boyut)
işlev
Yeterli yer olup olmadığını denetlemeksizin büyüyen nesneye ilklendirmeden boyut bayt ekler. Bkz. Çok Hızlı Büyüyen Nesneler.
void obstack_1grow_fast
(struct obstack *yığınak,
 char            karakter)
işlev
Yeterli yer olup olmadığını denetlemeksizin büyüyen nesneye karakter içeren bir bayt ekler. Bkz. Çok Hızlı Büyüyen Nesneler.
int obstack_room
(struct obstack *yığınak)
işlev
Büyüyen nesnede o andaki kullanılabilir alanın miktarı ile döner. Bkz. Çok Hızlı Büyüyen Nesneler.
int obstack_alignment_mask
(struct obstack *yığınak)
işlev
Bir nesnenin başlangıcını hizalamakta kullanılan maske ile döner. Bu bir sol taraf değeridir. Bkz. Yığınaktaki Verinin Adreslenmesi.
int obstack_chunk_size
(struct obstack *yığınak)
işlev
Ayrılan tomarların boyunu verir, ayrılacak tomarlar için boy belirtilir. Bir sol taraf değeridir. Bkz. Yığınak Tomarları.
void *obstack_base
(struct obstack *yığınak)
işlev
Büyüyen nesnenin geçici başlangıç adresi ile döner. Bkz. Bir Yığınağın Durumu.
void *obstack_next_free
(struct obstack *yığınak)
işlev
Belirtilen büyüyen nesnenin sonundan sonraki adres ile döner. Bkz. Bir Yığınağın Durumu.
Önceki Üst Ana Başlık Sonraki
Bellek Ayırmada Hata Ayıklama Başlangıç Değişken Boyutlu Özdevinimli Saklama
Bir Linux Kitaplığı Sayfası