Hlavní navigace

GLib: Cache (2)

Michal Burda 20. 2. 2001

Minule jsme načali téma o mechanizmu pro úsporu paměti - "keších" knihovny GLib. Dnes nás čeká ještě pár detailů o tomto nástroji a příklad ze života, na kterém si použití GCache demonstrujeme.

Procházení všemi prvky keše

Funkce typu „foreach“ jsou všem pravidelným čtenářům jistě dobře známy. Stejný nástroj je implementován i do keší.

void g_cache_key_foreach(GCache *cache, GHFunc func,
                         gpointer user_data);

void (*GHFunc) (gpointer key, gpointer value,
                gpointer user_data);

Tato funkce zavolá na každý klíč keše cache uživatelskou funkci func a předá jí kromě klíče a sdílených dat i pointer user_data. Jak jste si určitě všimli, funkce func je typu GHFunc, který už známe z dřívějška, konkrétně z kapitoly o hash-tabulkách.

Pro procházení keší je zde ale i jiná funkce:

void g_cache_value_foreach(GCache *cache, GHFunc func,
                           gpointer user_data);

Její použití bych si ale dovolil nedoporučovat. Pokud jsem správně pochopil zdrojový kód knihovny, funkce g_cache_value_foreach() prochází všemi prvky keše cache a volá na ně uživatelskou funkci func (která je rovněž typu GHFunc). Této funkci ale jako klíč ( key) předává pointer na sdílená data a jako hodnotu ( value) ukazatel na speciální vnitřní datový typ, ke kterému by uživatel knihovny správně neměl mít vůbec přístup! Uživateli je tato datová položka naprosto k ničemu a proto se mi zdá tento přístup poněkud matoucí a nebezpečný. Patrně se tvůrcům GLib tato funkce nechtěně zatoulala do veřejné části rozhraní. Uděláte jenom dobře, budete-li ji ignorovat. (Jestli se pletu, tak mě opravte!!! :-)

A to je z rozhraní mechanizmu GCache vše. Pojďme rychle na nějaký konkrétní příklad…

Příklad:

#include <glib.h>

/* nase struktura definujici jednu texturu */
typedef struct {
  char *name;         /* nazev textury */
  int transparency;   /* pruhlednost */
  int array[200*200]; /* samotna textura */
} Texture;


/* funkce pro duplikaci klice */
static gpointer dup_key(gpointer key) {
  return (gpointer) g_strdup((gchar *) key);
}


/* vytvoreni textury podle klice (nahrani z disku) */
static gpointer load_texture(gpointer key) {
  Texture *t;
  
  printf("Nacitam texturu %s ", key);
  
  /* inicializace */
  t = g_new0(Texture, 1);
  t->name = (char *) dup_key(key);
  
  /* skutecne nacteni je pro jednoduchost vypusteno */
}


/* HLAVNI PROGRAM */
gint main(void) {
  GCache *textures; /* cache */
  Texture *obj[10]; /* pole objektu */
  Texture *mramor;  /* jedna textura */
  int x;            /* pomocna promenna */

  /* vytvoreni nove cache */
  textures = g_cache_new(load_texture, g_free, dup_key,
      g_free, g_str_hash, g_direct_hash, g_str_equal);

  /* inicializace pole objektu */
  obj[0] = g_cache_insert(textures, "Mramor");
  obj[1] = g_cache_insert(textures, "Plast");
  obj[2] = g_cache_insert(textures, "Mramor");
  obj[3] = g_cache_insert(textures, "Drevo");
  obj[4] = g_cache_insert(textures, "Drevo");
  obj[5] = g_cache_insert(textures, "Mramor");
  obj[6] = g_cache_insert(textures, "Kov");
  obj[7] = g_cache_insert(textures, "Plast");
  obj[8] = g_cache_insert(textures, "Drevo");
  obj[9] = g_cache_insert(textures, "Mramor");

  /* kontrolni vypis */
  puts("");
  for (x = 0; x < 10; x++) {
    printf("obj[%d]: %s, %d ", x, 
        obj[x]->name, obj[x]->transparency);
  }

  /* editace jedne z textur */
  mramor = g_cache_insert(textures,
        "Mramor");                  /* nacteni */
  mramor->transparency = 255;       /* editace */
  g_cache_remove(textures, mramor); /* uvolneni */

  /* kontrolni vypis */
  puts("");
  for (x = 0; x < 10; x++) {
    printf("obj[%d]: %s, %d ", x, 
        obj[x]->name, obj[x]->transparency);
  }

  /* dealokace objektu (uvolneni textur) */
  for (x = 0; x < 10; x++) {
    g_cache_remove(textures, obj[x]);
  }

  /* dealokace cache */
  g_cache_destroy(textures);
}

Výše uvedený příklad prosím chápejte jako nástin části kódu jakéhosi grafického programu, který na různé geometrické objekty aplikuje textury. V ukázce se definuje struktura Texture, která slouží k uložení informací o texturách a právě ona bude předmětem kešování. Jejími prvky je jméno textury ( name), průhlednost ( transparency) a pole bajtů uchovávající samotnou texturu ( array).

Klíčem textur bude řetězec – název.

Kromě hlavní funkce jsou v programu ještě dvě rutiny. Obě slouží pro účely mechanizmu kešování:

Funkce dup_key() slouží pro duplikaci klíče a bude se předávat funkci g_cache_new() jako parametr  key_dup_func.

Stejně tak funkce load_texture(). I ona bude volána výhradně z vnitřku mechanizmu kešování. Funkci g_cache_new() se bude předávat jako argument value_new_func a jejím účelem je vytvořit nový záznam o textuře; načíst texturu z disku do datové struktury Texture. Pro jednoduchost je však kód obstarávající načtení ze souboru vypuštěn.

Hlavní program obsahuje proměnnou textures, což je samotná keš, pole obj, které klidně chápejte jako jakési pole geometrických objektů (pro jednoduchost jsou v poli uloženy jen záznamy o texturách objektů), a pomocné proměnné mramorx.

Po inicializaci keše textures se inicializuje i pole objektů obj. Z kontrolního výstupu můžete sledovat, že každý druh textury se opravdu inicializuje (načítá z disku) jen jednou.

Následuje editace atributů textury „Mramor“. Nejprve se do proměnné mramor uloží voláním g_cache_insert() pointer na záznam v keši, poté se položka modifikuje a nakonec se pointer keši zase vrátí ( g_cache_remove()). Je důležité nezapomínat každý „získaný“ pointer zase „vracet“!

Po kontrolním výpisu se už jen uvolní z paměti všechny objekty a nakonec i samotná keš.

Výstupem programu by mělo být:

Nacitam texturu Mramor
Nacitam texturu Plast
Nacitam texturu Drevo
Nacitam texturu Kov

obj[0]: Mramor,  0
obj[1]: Plast,   0
obj[2]: Mramor,  0
obj[3]: Drevo,   0
obj[4]: Drevo,   0
obj[5]: Mramor,  0
obj[6]: Kov,     0
obj[7]: Plast,   0
obj[8]: Drevo,   0
obj[9]: Mramor,  0

obj[0]: Mramor,  255
obj[1]: Plast,   0
obj[2]: Mramor,  255
obj[3]: Drevo,   0
obj[4]: Drevo,   0
obj[5]: Mramor,  255
obj[6]: Kov,     0
obj[7]: Plast,   0
obj[8]: Drevo,   0
obj[9]: Mramor,  255

Co si z příkladu odnést? Možná to, že na funkce g_cache_insert() a g_cache_remove() je dobré pohlížet jako na dvojici funkcí g_malloc() a g_free(): každý ukazatel, který funkcí g_cache_insert() získáme, je velice vhodné (!) po použití „rádoby-dealokovat“ voláním g_cache_remove(). Jen tak si mechanizmus GCache udrží pravdivý údaj o počtu ukazatelů na sdílená data a jen tak dosáhneme správné funkce celého systému kešování a úspory paměti.

Toť pro dnešek z mé strany vše. U dalšího pokračování se těší

Našli jste v článku chybu?
120na80.cz: Bojíte se encefalitidy?

Bojíte se encefalitidy?

Podnikatel.cz: Přehledná titulka, průvodci, responzivita

Přehledná titulka, průvodci, responzivita

DigiZone.cz: Česká televize mění schéma ČT :D

Česká televize mění schéma ČT :D

Root.cz: Vypadl Google a rozbilo se toho hodně

Vypadl Google a rozbilo se toho hodně

Lupa.cz: Google měl výpadek, nejel Gmail ani YouTube

Google měl výpadek, nejel Gmail ani YouTube

Vitalia.cz: Chtějí si léčit kvasinky. Lék je jen v Německu

Chtějí si léčit kvasinky. Lék je jen v Německu

Lupa.cz: Babiš: E-shopů se EET možná nebude týkat

Babiš: E-shopů se EET možná nebude týkat

DigiZone.cz: Recenze Westworld: zavraždit a...

Recenze Westworld: zavraždit a...

120na80.cz: Pánové, pečujte o svoje přirození a prostatu

Pánové, pečujte o svoje přirození a prostatu

Lupa.cz: Proč firmy málo chrání data? Chovají se logicky

Proč firmy málo chrání data? Chovají se logicky

Vitalia.cz: Láska na vozíku: Přitažliví jsme pro tzv. pečovatelky

Láska na vozíku: Přitažliví jsme pro tzv. pečovatelky

Vitalia.cz: Tesco: Chudá rodina si koupí levné polské kuře

Tesco: Chudá rodina si koupí levné polské kuře

120na80.cz: Rakovina oka. Jak ji poznáte?

Rakovina oka. Jak ji poznáte?

Podnikatel.cz: Na poslední chvíli šokuje vyjímkami v EET

Na poslední chvíli šokuje vyjímkami v EET

Měšec.cz: Jak vymáhat výživné zadarmo?

Jak vymáhat výživné zadarmo?

Lupa.cz: Co se dá měřit přes Internet věcí

Co se dá měřit přes Internet věcí

Podnikatel.cz: 1. den EET? Problémy s pokladnami

1. den EET? Problémy s pokladnami

Měšec.cz: Finančním poradcům hrozí vracení provizí

Finančním poradcům hrozí vracení provizí

Podnikatel.cz: Prodává přes internet. Kdy platí zdravotko?

Prodává přes internet. Kdy platí zdravotko?

Měšec.cz: Zdravotní a sociální pojištění 2017: Připlatíte

Zdravotní a sociální pojištění 2017: Připlatíte