Temizlik İşleyicileri
Önceki POSIX Evreleri Sonraki
Temizlik İşleyicileri
Temizlik işleyicileri, pthread_exit çağrılarak veya iptal nedeniyle bir evre sonlandığında çağrılan işlevlerdir. Temizlik işleyicileri yığıta benzer bir disiplinde kurulurlar ve kaldırılırlar.
Temizlik işleyicilerinin amacı bir evrenin tuttuğu kaynakları evre sonlandığı zaman serbest bırakmaktır. Eğer bir evre kilitli bir karşılıklı red nesnesine (mutex)[103] sahipken çıkarsa veya iptal edilirse, nesne sonsuza kadar kilitli kalır ve diğer evrelerin normal işletilmesini engeller. Bundan kaçınmanın en iyi yolu, karşılıklı red nesnesini kilitlemeden az önce, nesnenin kilidini kaldıracak bir temizlik işleyicisinin kurulmasıdır. Temizlik işleyicileri malloc ile ayrılmış blokların serbest bırakılmasında veya evre sonlandırıldığında dosya tanımlayıcılarının kapatılmasında da kullanılabilir.
Burada mut kilitliyken evre iptal edilirse, kilidinin kaldırılmasında gerektiği gibi bir mut nesnesinin nasıl kilitlenebileceğini görüyoruz.
pthread_cleanup_push(pthread_mutex_unlock, (void *) &mut);
pthread_mutex_lock(&mut);
/* biraz çalış */
pthread_mutex_unlock(&mut);
pthread_cleanup_pop(0);
Son iki satır
pthread_cleanup_pop(1);
ile değiştirilebilir.
Unutmayınız ki yukarıdaki kod sadece ertelenmiş iptal kipinde güvenlidir (bkz. pthread_setcanceltype). Zamanuyumsuz iptal kipinde, bir iptal pthread_cleanup_push ve pthread_mutex_lock arasında veya pthread_mutex_unlock ve pthread_cleanup_pop arasında oluşur, evrenin her iki durumunda muteksin kilidini açmayı deneyen geçerli evre tarafından kilitlenmez. Bu zamanuyumsuz iptalin kullanımının neden zor olduğunun ana sebebidir.
Eğer yukarıdaki kodun zamanuyumsuz iptal kipinde de çalışması gerekiyorsa, muteksi kilitlemek ve kilidi açmak için ertelenmiş iptal kipine çevrilmelidir:
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);
pthread_cleanup_push(pthread_mutex_unlock, (void *) &mut);
pthread_mutex_lock(&mut);
/* Birşeyler yap */
pthread_cleanup_pop(1);
pthread_setcanceltype(oldtype, NULL);
Yukarıdaki kod taşınabilir değildir. pthread_cleanup_push_defer_np ve pthread_cleanup_pop_restore_np işlevlerinin kullanılmasıyla daha kısa ve verimli bir şekilde tekrar yazılabilir:
pthread_cleanup_push_defer_np(pthread_mutex_unlock, (void *) &mut);
pthread_mutex_lock(&mut);
/* Birşeyler yap */
pthread_cleanup_pop_restore_np(1);
void pthread_cleanup_push
(void (*işlev) (void *),
 void  *arg)
işlev
pthread_cleanup_push işlev işlevini arg argümanıyla bir temizlik işleyicisi olarak yükler. Bu noktadan itibaren pthread_cleanup_pop ile ilişkili işlev işlevi, ne zaman evre pthread_exit veya iptal ile sonlansa, arg argümanlarıyla çağrılacaktır. Eğer bu noktada çok sayıda temizlik işleyicileri etkinse, LIFO sırasıyla çağrılırlar: en son yüklenen ilk çağrılır.
void pthread_cleanup_pop
(int çalıştır)
işlev
pthread_cleanup_pop en son yüklenen temizlik işleyicisini kaldırır. Eğer çalıştır argümanı 0 değilse, aynı zamanda işlev işlevini arg argümanlarıyla çağırarak işleyiciyi de işletir. Eğer çalıştır argümanı 0 ise, işleyici sadece kaldırılır, işletilmez.
pthread_cleanup_push ve pthread_cleanup_pop işlevlerinin eşleşen çiftleri aynı işlev içinde aynı blok yuvalama seviyesinde gerçekleşmelidir. Aslında, pthread_cleanup_push ve pthread_cleanup_pop birer makrodur, ve pthread_cleanup_push bir bloğu başlatan kaşlı ayraca {, pthread_cleanup_pop ise bunun kapatan kaşlı ayraca } karşılık gelir.
void pthread_cleanup_push_defer_np
(void (*işlev) (void *),
 void  *arg)
işlev
pthread_cleanup_push_defer_np, pthread_cleanup_push ile pthread_setcanceltype'ı birleştiren taşınabilir olmayan bir oluşumdur. Sadece pthread_cleanup_push'un yaptığı gibi bir temizlik işleyicisi iter, fakat aynı zamanda geçerli iptal türünü kaydeder ve onu ertelenmiş iptale ayarlar. Bu temizleme mekanizmasının ilk başta zamanuyumsuz iptal kipinde olsa bile verimli olduğunu temin eder.
void pthread_cleanup_pop_restore_np
(int çalıştır)
işlev
pthread_cleanup_pop_restore_np, pthread_cleanup_push_defer_np ile tanıştırılan bir temizlik işleyicisini çeker ve iptal türünü pthread_cleanup_push_defer_np çağrıldığında olan değerine geri yükler.
pthread_cleanup_push_defer_np ve pthread_cleanup_pop_restore_np eşleşen çiftlerde aynı blok yuvalama seviyesinde gerçekleşmelidir.
pthread_cleanup_push_defer_np(routine, arg);
...
pthread_cleanup_pop_defer_np(execute);
sıralaması
{
  int oldtype;
  pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);
  pthread_cleanup_push(routine, arg);
  ...
  pthread_cleanup_pop(execute);
  pthread_setcanceltype(oldtype, NULL);
}
ile işlevsel olarak denktir.(fakat daha kısa ve verimlidir)


[103] [Ç.N.] mutex (mutual exclusion'dan kısaltma): Bir karşılıklı red (muteks) nesnesi paylaşımlı özkaynaklara erişimi eşzamanlayan çoklu evreleri mümkün kılar. Bir muteks iki durumda olabilir: kilitli, kilitsiz. Bir muteks bir evre tarafından bir kere kilitlendi mi onu kilitlemeye çalışan diğer evreler engellenir. Kilitli evre muteksi bıraktığında (kilidini kaldırdığında) engellenen bloklardan biri onu kilitler ve işlem böyle sürüp gider.
Önceki Üst Ana Başlık Sonraki
İptaletme Başlangıç Muteksler
Bir Linux Kitaplığı Sayfası