* final (?) word on constness and containers
@ 2014-11-05 22:08 Gerard Jungman
0 siblings, 0 replies; only message in thread
From: Gerard Jungman @ 2014-11-05 22:08 UTC (permalink / raw)
Once more on the container constness problem and
container design, to express my final understanding
of the problems and suggest a path forward.
I have concluded that the design of the vector and
matrix view types is completely brain-damaged. The
two distinct types (non-const and const) are useless,
because they cannot enforce their implied contract.
Any client who uses the const-ified view type is forced
to cast away the constness before using any GSL interface.
So the const types are actually just an annoying trap.
The full vector and matrix types are slightly less
brain-damaged. They also do not enforce any implied
contract, but they do not really claim to do so,
since there is no const-ified type. There is
only the current illusion of const-correctness.
I have spent some effort trying to understand the
state of the art for containers in C. The conclusion
seems to be that const-correctness is essentially
impossible in practical C code of this type. This
is quite sad, when you think about it. But that's
the way it is.
On the bright side, you could argue that this situation
is inevitable in an inter-language environment, where GSL
might be wrapped in python, etc. The notion of constness
is C-language-family specific and does not translate
well to dynamic inter-language contexts.
So here are my recommendations:
R1) Introduce a set of "view constructors" which
build gsl_vector objects (not views) that
wrap existing memory. Objects are built
on the stack.
gsl_vector gsl_vector_as_view(double * x, size_t size, int stride);
gsl_vector gsl_vector_as_subvector(const gsl_vector * v, size_t
i, int stride, size_t n);
The notion of "view" shifts from a distinct type
to flexible methods of construction for the
single main type.
For parallelism, introduce stack constructors for
heap-allocated data as well:
gsl_vector gsl_vector_as_heap_data(size_t size);
This is important, to encourage a more value-centric
philosophy (rather than pointer-centric), which makes
client code more flexible and probably more maintainable.
The pointer-based idioms are retained, since they
are also useful, especially in more dynamic contexts.
Also, current client code depends on them.
R2) Expand the semantics of the 'owner' member in the vector
and matrix structs to be flags that delineate the supported
actions in gsl_XXX_free(). Currently, the value is either 0 or 1,
where 0 instructs gsl_vector_free() to not attempt to free the
data segment. The new values and their semantics would be as follows:
GSL_OWNER_EXTERN = 0 /* wrapper and data externally managed */
GSL_OWNER_MALLOC_DATA = 1 /* data is heap allocated */
GSL_OWNER_MALLOC_WRAP = 2 /* wrapper is heap allocated */
GSL_OWNER_MALLOC_BOTH = 3 /* (1 & 2) */
gsl_XXX_free will test these flags and act accordingly.
The values are not quite binary compatible with the
current design, because the current constants were
R3) Deprecate the current view functionality. There is
no reason to eliminate it, since it is orthogonal
to everything, and some clients may be burdened
if we removed it immediately.
C1) The constness problem is not solved. This is the only
way forward that does not change everything. The
library can handle the casting away of constness
at construction time, continuing to propagate the
current fiction that the design is const correct.
C2) Clients gain more flexibility in managing their own
memory and creating their own allocation strategies.
This design is the most flexible and avoids alloc/free
function wrappers and related "factory" style frameworks,
which are just too rigid to be contemplated.
C3) No changes are required in existing client code,
unless they choose to use the new interfaces.
C4) Uses of the current "view" types in GSL library code
should be replaced with new-style constructs. This
would not be difficult; these internal uses are
well-delineated and easy to replace. There are,
however, dozens of them.
C5) Add the new constructor interfaces and make the
small needed change to the gsl_XXX_alloc() and
gsl_XXX_free() impls, to support the new 'owner'
Overall, this seems like a simple and controlled plan.
It's the kind of thing I could bang out in a few
afternoons. And the consequences seem palatable.
Please think hard about how this might impact
future progress. That is the hard problem.
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2014-11-05 22:08 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-11-05 22:08 final (?) word on constness and containers Gerard Jungman
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).