[Openal-devel] FreeALUT stream proof-of-concept

Chris Robinson chris.kcat at gmail.com
Sun Jun 8 19:25:11 PDT 2008


On Sunday 08 June 2008 06:11:02 pm Sherief N. Farouk wrote:
> A part has to be exposed to the user. Exposing stream::stream() is no
> different than exposing CreateStreamFromFile for this case.

True enough, but whatever is exposed needs to remain exposed (and in the same 
order). Adding stuff is fine, but it has to be added to the end. I'd also say 
that anything exposed is fair game to the app. If the struct has a variable, 
the variable needs to continue to be used the same way by the implementation 
or else it can break apps. If something isn't for the app to touch, it 
shouldn't be exposed for the app to touch.

> > Unless you're talking about something like this:
> >
> > struct ALUTstream {
> >     virtual ALboolean ALUT_APIENTRY IsPlaying ()
> >     { return This->IsPlaying(); }
> >     virtual ALboolean ALUT_APIENTRY Poll ()
> >     { return This->Poll(); }
> >     virtual ALboolean ALUT_APIENTRY PlayOnSource (ALuint sourceID)
> >     { return This->PlayOnSource(sourceID); }
> >     virtual ALboolean ALUT_APIENTRY Stop ()
> >     { return This->Stop(); }
> >
> >     ALUTstream(a,b,c) : This(alutCreateStreamFromFile(a,b,c))
> >     { }
> >     virtual ~ALUTstream()
> >     { delete This; };
> >
> > private:
> >     ALUTstream *This;
> > };
>
> [Sherief N. Farouk]
> No. And there's something fundamentally wrong with that sample. If
> ALUTstream is the C object, how can a call like
> This->PlayOnSource(sourceID) work?

Because in C you call alutStreamPlayOnSource, which is implemented using C++ 
(but with C linkage), which can make calls like that just fine. In C, the 
struct isn't exposed at all (it's completely opaque). It's evil, though, 
because essentially this is what happens for new'd/stack objects:
alutStreamPlayOnSource(stream, x); // if used like C
  stream->PlayOnSource(x);
    stream->This->PlayOnSource(x);
      ...implementation here...
Plus the aforementioned leak potential for stack objects.

> There's no "this" parameter in C

There's no virtual or member functions in C, either (at most there's function 
pointers, but as you say the 'this' pointer isn't implicit). Which is why in 
C, the struct is opaque and used via the alutStream* functions, while in C++, 
the struct is defined to have a set of pure virtual functions and can be used 
either way.

The only "ugliness" is having to call an alutCreateStreamFrom* function to get 
an object in C++ instead of new'ing it. A fair trade-off, IMO, considering it 
can be used C++-ish otherwise (derive from it and make your own 
implementation, use auto_ptr or boost's shared pointer, whatever).

> If you have live objects after you call alcMakeContextCurrent(NULL), You're
> beyond help anyway, and you totally and absolutely deserve what's coming to
> you. This is the C++ equivalent of someone calling AL functions after a
> MakeContextCurrent(NULL) call - they had it coming! :)

Perhaps, but even calling AL functions with no context doesn't irreversably 
leak objects. You get an error and a chance to correct it. (and I used NULL 
as a simple example; It could just as easilly happen with another real 
context since sources are bound to the context they're created in).

I agree we don't need to be hand-holding (if they do something dumb, bad 
things will happen), but leaks caused by the lib, even if by proxy, are bad 
and should be avoided whenever possible. If the user wants to then ignore the 
error, there's nothing we can do about that. They at least had the 
opportunity to see "hey, something's wrong here..".

Of course it doesn't help that contexts aren't per thread, otherwise I'd be 
able to store the context the source uses, and set it when deleting (and 
reset it back after). But because another thread may be using the context, 
there's no way to syncronize for the temporary switch..


More information about the Openal-devel mailing list