Commit 24c2daef authored by Hanspeter Portner's avatar Hanspeter Portner

Squashed 'xpress.lv2/' changes from 04dbdd75..24011092

24011092 small fixes.
c5bb93f0 fix logic flaws in last commit.
f77ec5c1 migrate from binary search to quadratic probing.

git-subtree-dir: xpress.lv2
git-subtree-split: 24011092089865f901c2c7545959e90c134f63a4
parent 7d5028c3
......@@ -61,9 +61,10 @@ _dump(plughandle_t *handle)
{
XPRESS_VOICE_FOREACH(&handle->xpressI, voice)
{
lv2_log_trace(&handle->logger, "%"PRIu32" (%"PRIu32")", voice->uuid, voice->source);
if(!voice->uuid) continue;
lv2_log_trace(&handle->logger, "\t%"PRIu32" (%"PRIu32")", voice->uuid, voice->source);
}
lv2_log_trace(&handle->logger, "%s", "");
}
static void
......
......@@ -163,6 +163,7 @@ struct _xpress_t {
void *data;
unsigned max_nvoices;
unsigned mask_nvoices;
unsigned nvoices;
xpress_voice_t voices [1];
};
......@@ -175,18 +176,18 @@ struct _xpress_t {
xpress_voice_t XPRESS_CONCAT(_voices, __COUNTER__) [(MAX_NVOICES - 1)]
#define XPRESS_VOICE_FOREACH(XPRESS, VOICE) \
for(xpress_voice_t *(VOICE) = &(XPRESS)->voices[(int)(XPRESS)->nvoices - 1]; \
for(xpress_voice_t *(VOICE) = &(XPRESS)->voices[(int)(XPRESS)->max_nvoices - 1]; \
(VOICE) >= (XPRESS)->voices; \
(VOICE)--)
#define XPRESS_VOICE_FREE(XPRESS, VOICE) \
for(xpress_voice_t *(VOICE) = &(XPRESS)->voices[(int)(XPRESS)->nvoices - 1]; \
for(xpress_voice_t *(VOICE) = &(XPRESS)->voices[(int)(XPRESS)->max_nvoices - 1]; \
(VOICE) >= (XPRESS)->voices; \
(VOICE)->uuid = 0, (VOICE)--, (XPRESS)->nvoices--)
(VOICE)->uuid = 0, (VOICE)--)
// non rt-safe
static inline int
xpress_init(xpress_t *xpress, const size_t max_nvoices, LV2_URID_Map *map,
xpress_init(xpress_t *xpress, const unsigned max_nvoices, LV2_URID_Map *map,
xpress_map_t *voice_map, xpress_event_t event_mask, const xpress_iface_t *iface,
void *target, void *data);
......@@ -273,91 +274,45 @@ _xpress_urn_uuid(LV2_URID_Map *map)
return map->map(map->handle, uuid);
}
static inline void
_xpress_qsort(xpress_voice_t *A, int n)
{
if(n < 2)
return;
const xpress_voice_t *p = A;
int i = -1;
int j = n;
while(true)
{
do {
i += 1;
} while(A[i].uuid > p->uuid);
do {
j -= 1;
} while(A[j].uuid < p->uuid);
if(i >= j)
break;
const xpress_voice_t tmp = A[i];
A[i] = A[j];
A[j] = tmp;
}
_xpress_qsort(A, j + 1);
_xpress_qsort(A + j + 1, n - j - 1);
}
static inline xpress_voice_t *
_xpress_bsearch(xpress_uuid_t p, xpress_voice_t *a, int n)
_xpress_voice_get(xpress_t *xpress, xpress_uuid_t uuid)
{
xpress_voice_t *base = a;
for(int N = n, half; N > 1; N -= half)
for(unsigned i = 0, idx = (uuid + i*i) & xpress->mask_nvoices;
i < xpress->max_nvoices;
i++, idx = (uuid + i*i) & xpress->mask_nvoices)
{
half = N/2;
xpress_voice_t *dst = &base[half];
base = (dst->uuid < p) ? base : dst;
}
xpress_voice_t *voice = &xpress->voices[idx];
return (base->uuid == p) ? base : NULL;
}
static inline void
_xpress_sort(xpress_t *xpress)
{
_xpress_qsort(xpress->voices, xpress->nvoices);
}
if(voice->uuid == uuid)
{
return voice;
}
}
static inline xpress_voice_t *
_xpress_voice_get(xpress_t *xpress, xpress_uuid_t uuid)
{
return _xpress_bsearch(uuid, xpress->voices, xpress->nvoices);
return NULL;
}
static inline void *
_xpress_voice_add(xpress_t *xpress, LV2_URID source, xpress_uuid_t uuid, bool alive)
{
if(xpress->nvoices >= xpress->max_nvoices)
return NULL; // failed
xpress_voice_t *voice = &xpress->voices[xpress->nvoices++];
voice->source = source;
voice->uuid = uuid;
voice->alive = alive;
void *target = voice->target;
_xpress_sort(xpress);
return target;
}
for(unsigned i = 0, idx = (uuid + i*i) & xpress->mask_nvoices;
i < xpress->max_nvoices;
i++, idx = (uuid + i*i) & xpress->mask_nvoices)
{
xpress_voice_t *voice = &xpress->voices[idx];
static inline void
_xpress_voice_free(xpress_t *xpress, xpress_voice_t *voice)
{
voice->uuid = 0;
if(voice->uuid == 0)
{
voice->source = source;
voice->uuid = uuid;
voice->alive = alive;
void *target = voice->target;
_xpress_sort(xpress);
return target;
}
}
xpress->nvoices--;
return NULL;
}
static xpress_shm_t *
......@@ -413,15 +368,15 @@ _xpress_shm_deinit(xpress_shm_t *xpress_shm)
}
static inline int
xpress_init(xpress_t *xpress, const size_t max_nvoices, LV2_URID_Map *map,
xpress_init(xpress_t *xpress, const unsigned max_nvoices, LV2_URID_Map *map,
xpress_map_t *voice_map, xpress_event_t event_mask, const xpress_iface_t *iface,
void *target, void *data)
{
if(!map || ( (event_mask != XPRESS_EVENT_NONE) && !iface))
return 0;
xpress->nvoices = 0;
xpress->max_nvoices = max_nvoices;
xpress->mask_nvoices = max_nvoices - 1;
xpress->map = map;
xpress->voice_map = voice_map;
xpress->event_mask = event_mask;
......@@ -615,27 +570,20 @@ xpress_advance(xpress_t *xpress, LV2_Atom_Forge *forge, uint32_t frames,
}
}
unsigned freed = 0;
XPRESS_VOICE_FOREACH(xpress, voice)
{
if(!voice->uuid) continue;
if( (voice->source == source->body)
&& !voice->alive )
{
if( (xpress->event_mask & XPRESS_EVENT_DEL) && xpress->iface->del)
xpress->iface->del(xpress->data, frames, voice->uuid, voice->target);
freed += 1;
voice->uuid = 0; // invalidate
}
}
if(freed > 0)
{
_xpress_sort(xpress);
xpress->nvoices -= freed;
}
return 1;
}
......@@ -647,6 +595,8 @@ xpress_pre(xpress_t *xpress)
{
XPRESS_VOICE_FOREACH(xpress, voice)
{
if(!voice->uuid) continue;
voice->alive = false;
}
}
......@@ -666,25 +616,18 @@ xpress_synced(xpress_t *xpress)
static inline void
xpress_post(xpress_t *xpress, int64_t frames)
{
unsigned freed = 0;
XPRESS_VOICE_FOREACH(xpress, voice)
{
if(!voice->uuid) continue;
if(!voice->alive)
{
if( (xpress->event_mask & XPRESS_EVENT_DEL) && xpress->iface->del)
xpress->iface->del(xpress->data, frames, voice->uuid, voice->target);
freed += 1;
voice->uuid = 0; // invalidate
}
}
if(freed > 0)
{
_xpress_sort(xpress);
xpress->nvoices -= freed;
}
}
static inline void *
......@@ -708,7 +651,7 @@ xpress_free(xpress_t *xpress, xpress_uuid_t uuid)
if(!voice)
return 0; // failed
_xpress_voice_free(xpress, voice);
voice->uuid = 0; // invalidate
return 1;
}
......@@ -800,6 +743,8 @@ xpress_alive(xpress_t *xpress, LV2_Atom_Forge *forge, uint32_t frames)
{
XPRESS_VOICE_FOREACH(xpress, voice)
{
if(!voice->uuid) continue;
if(ref)
ref = lv2_atom_forge_int(forge, voice->uuid);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment