Re: [linux-audio-dev] API design again [code]

New Message Reply About this list Date view Thread view Subject view Author view Other groups

Subject: Re: [linux-audio-dev] API design again [code]
From: David Olofson (audiality_AT_swipnet.se)
Date: to loka   07 1999 - 19:58:24 EDT


On Fri, 08 Oct 1999, Roger Larsson wrote:
> I guess I have to take another look at Davids API and try to merge...
> [where is it]

I think I've posted about all code I have for the current version on the list.

Anyway, I still have a problem, I think... In the last version I posted, the
plug-in gets the event buffer in the form of an array of "event descriptors".
The event port is the highest level interface to the event system:

---8<------------------------------
struct event_port_t {
        qm_heap_t *heap; /* For dynamic allocation */
        int events; /* Number of events
                                                 * currently in the buffer
                                                 */
        int maxevents; /* Size of the buffer */
        event_descriptor_t **buffer;
};
------------------------------>8---

(qm_heap_t is the fast, inline dynamic memory allocator I presented earlier. In
short; one conditional and a few simple operations per qm_malloc(); a function
call if the current heap buffer is exhausted.)

In order to be able to send events to multiple recipients (with different time
bases), send events based on static data, send the same event multiple times,
sort/merge event buffers, and other things with minimal copying, I invented
event_descriptor_t:

---8<------------------------------
struct event_descriptor_t {
        event_time_t time;
        event_t *event;
};
------------------------------>8---

And the event, of course... (I think that **from should be removed from the
basic version - I'd guess most kinds of events aren't replied to anyway.)

---8<------------------------------
struct event_t {
        event_code_t code; /* What is this? */
        event_port_t **from; /* Who is this from? */
        int size; /* Number of data bytes */
};
------------------------------>8---

So for the problem: What happens when a plug-in (or someone else for that
matter) is sending events to a port?

Memory for the _events_ is allocated using

qm_malloc(destinationPort->heap,<SIZE>);

but the array of event descriptors? The descriptors are rather small, so
perhaps just setting up fixed buffers of adequate size is enough, but I don't
like it. It's clumsy, inflexible and a waste of RAM.

A few ideas:

A check will have to be done for every event in any case, unless we require
the engine to set up the MMU hardware to handle it. One conditional here, and
one for the event allocation...

A quick "fix" would be to use smaller buffers for the arrays, adding buffers
as they fill up. Unlimited number of events, but it's a real mess.

Quick fix 2:
---8<------------------------------
struct event_descriptor_t {
        event_descriptor_t *next; /* <- Right here... */
        event_time_t time;
        event_t *event;
};
------------------------------>8---

A lot cleaner, but now it starts to look like an entry in some damn Maximum
Indirection Design contest... Where does this start to cost more than the extra
copying that would be needed without it? Or; How frequently will events be
reused, and how big data sections will these reused events have?

This is another solution...:

---8<------------------------------
typedef unsigned int event_code_t;
#define EV_CLASS_MASK 0xff000000 /* EVC_SYSTEM, EVC_CONTROL,... */
#define EV_FLAGS_MASK 0x00ff0000 /* EVF_REQUEST, EVF_REPLY... */
#define EV_KIND_MASK 0x0000ffff /* Exactly what event is this? */

struct event_t;

struct event_port_t {
        qm_heap_t *heap; /* For dynamic allocation */
        event_t *events; /* First event */
};

struct event_t {
        event_t *next;
        event_time_t time;
        event_code_t code; /* What is this? */
        int size; /* Number of data bytes */
};
------------------------------>8---

Nice, simple, and perhaps the extra copying doesn't make much difference,
considering the added complexity when trying to avoid it? After all, events are
supposed to be pretty small most of the time... And moving pointers around is
data copying as well.

Of course, events may include pointers... And qm_malloc() doesn't care much
what it's allocating memory for. Adding an EVC_EXTDATA event class that adds
pointer + size entries to event_t allows the engine to keep track of this
correctly, even accross networks and other messy settings.

Note: Zapped the reply port here. Should be the first entry in the data area
of events with (code & EVF_REQUEST).

Note2: The event_port_t events pointer it just what you see from the plug-in
(or client) side; it can be changed (or copied, or whatever) by the engine for
each "context switch" in order to optimize the merging of events for ports that
recieve events from multiple senders. Better ideas may emerge as we dig into
the "connection control system"...

Hmm... 02:40 local time. Bed time, I think...

//David

 ·A·U·D·I·A·L·I·T·Y· P r o f e s s i o n a l L i n u x A u d i o
- - ------------------------------------------------------------- - -
    ·Rock Solid David Olofson:
    ·Low Latency www.angelfire.com/or/audiality ·Audio Hacker
    ·Plug-Ins audiality_AT_swipnet.se ·Linux Advocate
    ·Open Source ·Singer/Composer


New Message Reply About this list Date view Thread view Subject view Author view Other groups

This archive was generated by hypermail 2b28 : pe maalis 10 2000 - 07:27:13 EST