API redesign progress

Jef Driesen jefdriesen at telenet.be
Wed Jul 4 15:53:41 UTC 2012


Hi,

Now that we are discussing major api improvements, let's also have a 
look at the sample parsing api. The current api generates a stream of 
sample values, where the time value is special in the sense that it 
starts a new sample. I think it would be cleaner to somehow return an 
opaque sample, and then get all the values available for that sample. 
Something similar to this:

void
sample_cb (dc_sample_t *sample, void *userdata)
{
    dc_sample_get_time (sample, ...);
    dc_sample_get_depth (sample, ...);
    dc_sample_get_something (sample, ...);
    ...
}

Let's discuss this a bit in more detail.

1. Sample types

The first question is of course which sample types do we want to 
support? The absolute minimum to support is:

  * time
  * depth
  * pressure
  * temperature

At the moment we also have:

  * events: Anything that happens only at specific point in time. All 
other sample types are typically measurements obtained from a sensor (or 
calculations based on them), with values available for each sample point 
(or at least every x sample points). But that is not the case for 
events. Typical examples are warnings, gas changes, etc. At the moment 
many events are supported, but the api sucks. The current plan is remove 
the events, use the vendor type instead (see below), and then add back 
support for the important events with a better api. The details of this 
last part are still unclear, but support for gas switches is definitely 
high on the list.

  * rbt: The RBT (remaining bottom time) is the time you can spend at 
the current depth and still have enough gas supply to make a safe 
ascent. It's currently available for the Uwatec Smart/Galileo only. 
Other air integrated dive computers often support a similar concept, so 
I think we can just keep this. Maybe rename it to the less cryptic 
"airtime"? Note that the actual interpretation may vary between models, 
depending on whether factors like the safety reserve, the ascent time, 
decompression time, etc are taking into account or not.

  * heartbeat: Another Uwatec Smart/Galileo feature. Although I don't 
know any other model that supports a heart monitor sensor, but it 
doesn't cause any trouble either. So I think we can keep this one too. 
BTW, is the correct name heartbeat or heartrate? I think it's heartrate, 
expressed in beats per minute (bpm). It's a bit confusing because both 
have the same translation in my native language.

  * bearing: Yet another Uwatec Smart/Galileo feature. There are several 
other models that have a digital compass, but they usually report it as 
an event, not a sample type. I also believe it makes more sense to 
consider a change in the compass bearing as an event. It's a setting you 
change, not some sensor that is polled every sample. I don't think any 
dive computer will ever generate a continuous stream with compass 
bearings. So I think we should drop this. BTW, is the correct name 
comnpass bearing or heading?

  * vendor: A vendor specific extension. This is intended for all 
samples that don't fit well into one of the types supported by the 
libdivecomputer library. The application is responsible for parsing the 
raw data, but at least it doesn't have to care about where and how the 
samples are stored. There are actually two variants of the vendor type 
today. For the first variant each piece of info gets its own vendor 
sample. That means a dc_sample_t can contain multiple vendor values. The 
second variant is the raw data representing the entire dc_sample_t data. 
Both have their use, so I propose to reserve the vendor type for the 
first case, and add a new raw type for the second case.

What else should we support? Some common requests I get are:

  * gas switches
  * no decompression time
  * decompression stops
  * ...

Decompression is a bit troublesome. Some models have just a simple deco 
flag. Others provide a time and depth, which is typically the time to 
surface (TTS) (e.g. total time for all stops and ascent combined) and 
the depth of the current stop. But their are plenty of other 
interpretations possible too. I won't be surprised some of the more 
technical dive computers provide a full decoplan (e.g. time at each 
depth). I have no idea how to support something like this in a clean 
way.

Note that an alternative solution would be to implement a decompression 
algorithm in the application and calculate all kinds of deco related 
parameters (tissue saturation, deco stops, etc) that way. It won't 
necessary match with your dive computer, but at least you would get a 
consistent application experience, regardless of the type of dive 
computer you have. Personally, I think this makes more sense for a 
general purpose logbook application, but not everyone may agree with 
that of course.

2. Which sample types are present?

With the current callback api, you just get all the sample types pushed 
to the application. With the new proposal the application needs to 
retrieve each sample value manually. Thus somehow we need a mechanism to 
query which sample types are available in the dc_sample_t object. 
Suggestions are welcome.

Also, how do we deal with sample types that can occur multiple times 
(e.g. vendor extensions, pressure values for multiple tanks, alarms, 
etc)?

3. Memory management

To be consistent with the dc_dive_t object, the dc_sample_t object 
should be allocated by the dc_dive_t object and freed by the 
application. However I'm not convinced that is a good idea. The number 
of samples is usually relative large (e.g. 3600 samples for a 1 hour 
dive at a 1 second sample rate) and in the typical scenario there is no 
reason to retain the sample object after having extracting the values 
(e.g. you call free right before leaving the callback function). Thus 
you end up with several hundreds or thousands of tiny objects that are 
allocated and immediately freed again. That's just very inefficient if 
you ask me!

A possible workaround would be to make the objects reference counted. 
Then, if the application doesn't keep a reference to the object, we can 
re-use the previous one, instead of creating a new one from scratch. But 
the drawback is that if we want to support passing objects between 
threads (see my previous email) the reference counting should be made 
thread-safe too.

Note that I'm not an export on multi-threading, so please correct me if 
I'm writing nonsense! Also everything I wrote so far is open for 
discussion. Feedback is highly appreciated!

Jef





More information about the Devel mailing list