glib dependency for the X Server
Carsten Haitzler (The Rasterman)
raster at rasterman.com
Thu Apr 6 20:01:20 PDT 2006
On Fri, 07 Apr 2006 04:35:39 +0200 Bernardo Innocenti <bernie at develer.com>
babbled:
> Carsten Haitzler (The Rasterman) wrote:
>
> > yeah- BUT for me - i tend to DESIGN my code where "0" is a plausible and
> > DESIREABLE "default starting" value OR an invalid value (eg a NULL pointer -
> > see above - i know about its caveats that it may NOT be 0) so i wont
> > de-reference a pointer if its null (ie the object hasn't been attached yet
> > for example or its in a "created but not initialised state -
>
> Such intermediate initialization states are a no-no since the RAII
> concept was invented. Forgetting to initialize stuff is one of the
> most common sources of problems that are difficult to reproduce and
> debug.
>
> Sane C++ libraries (this would rule out MFC and its two-stage construction)
> use constructors to make sure objects are either fully usable or don't
> exist at all.
but frankly that's a performance dog. it sucks. badly. example:
i create an image object. the image object contains the info:
width, height, colorspace (RGB or RGBA), pixel data
now - this image object is perfectly usable a lot of the time with NO PIXEL
DATA. i simply need to know its dimensions. so i can load just the header of
the file - and not decode a single pixel, allowing me to perform an ultra-fast
loads and queries and only decode pixel data on-demand (ie the first time the
pixels are actually needed for rendering or inspection). when the object has
all the meta-info but no pixels - it's in a "partly initialized" state. it
finishes its init when the first time pixels are needed. until then i KNOW the
the pixel pointer is NULL and that means "still need to fetch those". my code
would crawl a lot more slowly if i didn't do this. i can setup a massive array
of image objects (imagine a photo gallery) in a scrolled view - and just
blindly create, query dimensions and lay out based on that. the data is decoded
on-demand, deferring the work and saving ram for things you don't see.
> C programs can be designed to do the same by providing constructor
> functions that do both the allocation and the initialization of
> objects with a single call:
>
> foobar *fb = foobar_new();
> ...use fb...
> foobar_delete(fb);
>
> This suggestion may seem very trivial, but there are far too
> many APIs around that don't follow this simple pattern.
all my api's follow this. the problem is IN the foobar_new(). if i calloc() the
foobar struct - then i don't need to remember to set 80 or 100 struct members to
"sane states" - they are all already 0. i also GIVE the libc implementation the
chance to be optimal and if it's a fresh page - don't zero it out. if not - i
would be memset()ing it anyway - and now libc knows less and is not able to
make such an optimization - regardless if it does or not, i have removed the
ABILITY for it to do so (or well made it a lot trickier).
> When static allocation is also needed, a second function
> could do just the initialization step on an existing buffer:
>
> foobar fb;
> foobar_ctor(&fb);
> ...use fb...
> foobar_dtor(&fb);
>
> In C, one would still have to be careful about destroying all
> objects manually, but that's very difficult to do without C++.
>
>
> > eg an image object
> > would have a struct for its control info and properties but may not alloc
> > the pixel data until needed - i.e. i may load an image file header and get
> > its width, height, colorspace info etc., but not decode pixel data until
> > demanded, saving a fair bit of work when you just want to create objects
> > that don't become visible until later - or never)
>
> There is a GoF pattern for safe lazy initialzation, but I can't
> remember if it's called Proxy, Flyweight or something else.
>
> Basically, the object acts as if it was fully initialized, but
> the slow part of the initialization only happens the first time
> a method needs to access the data.
yup - thats exactly what i do in many places. it pays off very handsomely. but
i KNOW the pixel pointer is a known sane state and i can check for it and then
fill it in when needed. if i forget to set it up at the start and now its some
strange value - how do i know its valid or not? i need to add another flags
field for that then - another point of failure if i forget to set that up
too... some of my structs have more than 100 members. i would become homicidal
if i was manually setting everyone to some value on alloc.
> The basic idea for robust APIs is to try as much as possible
> to shield client code from implementation details such as these.
i do :) i do the callocs within the api - foobar_new() calls calloc when
allocating the object and returning it.
> --
> // Bernardo Innocenti - Develer S.r.l., R&D dept.
> \X/ http://www.develer.com/
>
--
------------- Codito, ergo sum - "I code, therefore I am" --------------
The Rasterman (Carsten Haitzler) raster at rasterman.com
裸好多
Tokyo, Japan (東京 日本)
More information about the xorg
mailing list