From af666e6f949ddb4f2cdfc4d3564fbe82e8b8d81b Mon Sep 17 00:00:00 2001 From: mdw Date: Sat, 2 Feb 2002 22:43:50 +0000 Subject: [PATCH] Provide a decent interface for finding out about the audio cache and configuring its capacity. --- au.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++------- au.h | 45 ++++++++++++++++++++++++++++++++-- rxglue.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 190 insertions(+), 11 deletions(-) diff --git a/au.c b/au.c index 80382b8..5c90186 100644 --- a/au.c +++ b/au.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: au.c,v 1.1 2002/02/02 19:16:28 mdw Exp $ + * $Id: au.c,v 1.2 2002/02/02 22:43:50 mdw Exp $ * * High-level audio subsystem * @@ -29,6 +29,10 @@ /*----- Revision history --------------------------------------------------* * * $Log: au.c,v $ + * Revision 1.2 2002/02/02 22:43:50 mdw + * Provide a decent interface for finding out about the audio cache and + * configuring its capacity. + * * Revision 1.1 2002/02/02 19:16:28 mdw * New audio subsystem. * @@ -68,7 +72,7 @@ static unsigned au_flags = 0; static sym_table au_tab; /* Sample cache, by name */ static const char *au_dir = AUDIODIR; /* Directory containing samples */ static struct { au_data *next, *prev; } au_spare; /* Lists for sample data */ -static size_t au_sz, au_max; /* Size of cached samples */ +static au_cacheinfo cache; /* Cache usage information */ #define AU_SPARE ((au_data*)&au_spare) #define f_init 1u @@ -106,18 +110,21 @@ static const char *filename(const char *tag) static void prune(void) { T( trace(T_AU, "au: pruning cache (%lu/%lu)", - (unsigned long)au_sz, (unsigned long)au_max); ) - while (au_sz > au_max && AU_SPARE->next != AU_SPARE) { + (unsigned long)cache.sz_total, (unsigned long)cache.sz_max); ) + while (cache.sz_total > cache.sz_max && AU_SPARE->next != AU_SPARE) { au_data *a = AU_SPARE->next; au_sample *s = a->s; assert(!a->ref); AU_SPARE->next = a->next; a->next->prev = AU_SPARE; s->a = 0; - au_sz -= a->sz; + cache.sz_spare -= a->sz; + cache.sz_total -= a->sz; + cache.n_spare--; + cache.n_total--; ausys_free(a); T( trace(T_AU, "au: ... discarded `%s' (%lu/%lu)", SYM_NAME(s), - (unsigned long)au_sz, (unsigned long)au_max); ) + (unsigned long)cache.sz_total, (unsigned long)cache.sz_max); ) } } @@ -149,7 +156,7 @@ void au_init(const char *dir, size_t max) sym_create(&au_tab); AU_SPARE->next = AU_SPARE->prev = AU_SPARE; - au_max = max; + cache.sz_max = max; /* --- Initialize the system-specific subsystem --- */ @@ -178,6 +185,42 @@ void au_shutdown(void) T( trace(T_AU, "au: shutdown ok"); ) } +/* --- @au_getcacheinfo@ --- * + * + * Arguments: @au_cacheinfo *c@ = where to put the information + * + * Returns: --- + * + * Use: Extracts audio cache information. + */ + +void au_getcacheinfo(au_cacheinfo *c) +{ + ausys_lock(); + *c = cache; + ausys_unlock(); + assert(c->sz_spare + c->sz_queue == c->sz_total); + assert(c->n_spare + c->n_queue == c->n_total); +} + +/* --- @au_setcachelimit@ --- * + * + * Arguments: @size_t max@ = new cache limit + * + * Returns: --- + * + * Use: Reconfigures the maximum cache size. This probably isn't + * very useful, but it was easy... + */ + +void au_setcachelimit(size_t max) +{ + ausys_lock(); + cache.sz_max = max; + prune(); + ausys_unlock(); +} + /* --- @au_find@ --- * * * Arguments: @const char *tag@ = sample tag string @@ -251,6 +294,11 @@ au_data *au_fetch(au_sample *s) a->prev->next = a->next; a->next->prev = a->prev; a->next = a->prev = 0; + cache.sz_spare -= a->sz; + cache.sz_queue += a->sz; + cache.n_spare--; + cache.n_queue++; + cache.hits++; } a->ref++; T( trace(T_AU, "au: reusing sample `%s'", SYM_NAME(s)); ) @@ -302,7 +350,6 @@ au_data *au_fetch(au_sample *s) if ((a = ausys_decode(s, d.buf, d.len)) == 0) goto fail_0; - au_sz += a->sz; a->ref = 1; a->next = a->prev = 0; a->s = s; @@ -311,6 +358,11 @@ au_data *au_fetch(au_sample *s) /* --- Done --- */ ausys_lock(); + cache.sz_queue += a->sz; + cache.sz_total += a->sz; + cache.n_queue++; + cache.n_total++; + cache.misses++; prune(); ausys_unlock(); goto done; @@ -385,6 +437,10 @@ void au_free_unlocked(au_data *a) a->prev = AU_SPARE->prev; AU_SPARE->prev->next = a; AU_SPARE->prev = a; + cache.sz_queue -= a->sz; + cache.sz_spare += a->sz; + cache.n_queue--; + cache.n_spare++; T( trace(T_AU, "au: drop last ref to `%s'", SYM_NAME(a->s)); ) prune(); } diff --git a/au.h b/au.h index 7678943..891bdf4 100644 --- a/au.h +++ b/au.h @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: au.h,v 1.1 2002/02/02 19:16:28 mdw Exp $ + * $Id: au.h,v 1.2 2002/02/02 22:43:50 mdw Exp $ * * Audio handling * @@ -29,6 +29,10 @@ /*----- Revision history --------------------------------------------------* * * $Log: au.h,v $ + * Revision 1.2 2002/02/02 22:43:50 mdw + * Provide a decent interface for finding out about the audio cache and + * configuring its capacity. + * * Revision 1.1 2002/02/02 19:16:28 mdw * New audio subsystem. * @@ -93,7 +97,21 @@ typedef struct au_data { size_t sz; /* Size of sample file data */ } au_data; -#define AU_CACHEMAX 0x01000000 /* Maximum resident sample data */ +/* --- Audio cache information --- */ + +typedef struct au_cacheinfo { + size_t sz_max; /* Maximum allowed cache size */ + size_t sz_total; /* Total size used by samples */ + size_t sz_spare; /* Size used by `spare' samples */ + size_t sz_queue; /* Size used by queued samples */ + unsigned n_total; /* Total number of cached samples */ + unsigned n_spare; /* Number of `spare' samples */ + unsigned n_queue; /* Number of queued samples */ + unsigned long hits; /* Number of cache hits */ + unsigned long misses; /* Number of cache misses */ +} au_cacheinfo; + +#define AU_CACHEMAX 0x01000000 /* Default cache maximum size */ /*----- Functions provided ------------------------------------------------*/ @@ -120,6 +138,29 @@ extern void au_init(const char */*dir*/, size_t /*max*/); extern void au_shutdown(void); +/* --- @au_getcacheinfo@ --- * + * + * Arguments: @au_cacheinfo *c@ = where to put the information + * + * Returns: --- + * + * Use: Extracts audio cache information. + */ + +extern void au_getcacheinfo(au_cacheinfo */*c*/); + +/* --- @au_setcachelimit@ --- * + * + * Arguments: @size_t max@ = new cache limit + * + * Returns: --- + * + * Use: Reconfigures the maximum cache size. This probably isn't + * very useful, but it was easy... + */ + +extern void au_setcachelimit(size_t /*max*/); + /* --- @au_find@ --- * * * Arguments: @const char *tag@ = sample tag string diff --git a/rxglue.c b/rxglue.c index d57d798..75e0f96 100644 --- a/rxglue.c +++ b/rxglue.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: rxglue.c,v 1.3 2002/02/02 19:17:41 mdw Exp $ + * $Id: rxglue.c,v 1.4 2002/02/02 22:43:50 mdw Exp $ * * REXX glue for C core functionality * @@ -29,6 +29,10 @@ /*----- Revision history --------------------------------------------------* * * $Log: rxglue.c,v $ + * Revision 1.4 2002/02/02 22:43:50 mdw + * Provide a decent interface for finding out about the audio cache and + * configuring its capacity. + * * Revision 1.3 2002/02/02 19:17:41 mdw * New audio subsystem. * @@ -575,6 +579,83 @@ static APIRET APIENTRY rxfn_aunum(const char *fn, ULONG ac, RXSTRING *av, return (0); } +/* --- @AUCACHE([FLAG], [VALUE, ...]@ --- * + * + * Arguments: @FLAG@ = operation to perform + * + * Returns: Dependent on operation. + * + * Use: If @FLAG@ is omitted or `Info', returns audio cache usage + * information as words in the following order: + * + * sz_max Maximum allowed cache size + * sz_total Total size used by samples + * sz_spare Size used by `spare' samples + * sz_queue Size used by queued samples + * n_total Total number of cached samples + * n_spare Number of `spare' samples + * n_queue Number of queued samples + * hits Number of cache hits + * misses Number of cache misses + * + * If @FLAG@ is `Max', sets the maximum cache size to the first + * @VALUE@ (if set), and returns the old maximum on its own. + * + * If @FLAG@ is `Usage', returns the `sz_*' items, as a list of + * words. + * + * If @FLAGS@ is `Numbers', returns the `n_*' items, as a list + * of words. + * + * If @FLAGS@ is `Hits', returns `hits' and `misses' as a pair + * of words. + */ + +static APIRET APIENTRY rxfn_aucache(const char *fn, ULONG ac, RXSTRING *av, + const char *sn, RXSTRING *r) +{ + int i = 1; + au_cacheinfo c; + + au_getcacheinfo(&c); + if (ac < 1 || !av[0].strlength) + goto info; + switch (av[0].strptr[0]) { + case 'i': case 'I': info: + rxs_putf(r, "%lu %lu %lu %lu %u %u %u %lu %lu", + (unsigned long)c.sz_max, (unsigned long)c.sz_total, + (unsigned long)c.sz_spare, (unsigned long)c.sz_queue, + c.n_total, c.n_spare, c.n_total, c.hits, c.misses); + break; + case 'm': case 'M': + if (ac > i) { + long max; + if (rxs_tol(&av[i], &max)) + return (-1); + au_setcachelimit(max); + i++; + } + rxs_putf(r, "%lu", (unsigned long)c.sz_max); + break; + case 'u': case 'U': + rxs_putf(r, "%lu %lu %lu %lu", + (unsigned long)c.sz_max, (unsigned long)c.sz_total, + (unsigned long)c.sz_spare, (unsigned long)c.sz_queue); + break; + case 'n': case 'N': + rxs_putf(r, "%u %u %u", c.n_total, c.n_spare, c.n_total); + break; + case 'h': case 'H': + rxs_putf(r, "%lu %lu", c.hits, c.misses); + break; + default: + return (-1); + } + if (i > ac) + return (-1); + return (0); +} + /* --- @MILLIWAIT(MILLIS)@ --- * * * Arguments: @MILLIS@ = how long (in milliseconds) to wait @@ -616,6 +697,7 @@ static const struct rxfntab rxfntab[] = { { "txready", rxfn_txready }, { "auplay", rxfn_auplay }, { "aufetch", rxfn_aufetch }, + { "aucache", rxfn_aucache }, { "aunum", rxfn_aunum }, { "milliwait", rxfn_milliwait }, { 0, 0 } -- 2.11.0