apr-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Yann ...@bee-ware.net>
Subject Re: Opaque structures in general (was Re: Opaque apr_pool_t structure)
Date Fri, 06 Jun 2008 11:24:48 GMT
Sorry I didn't explain myself very well.

I don't wan't to play with pointers, of course, a single sizeof won't allow me to do much
more then a memcpy().

For example ( innocently :p ) :

struct mystuct {
	apr_pool_t p;
} myvar;
apr_pool_t p;

apr_pool_create(&p, NULL);
memcpy(&myvar.p, p, apr_pool_sizeof());

That's all I can do, I can't access any apr_pool field ...


Ryan Bloom wrote:
> I don't think that there is any reason to not have a sizeof()
> function, other than any code that does "play" with the pointers will
> be non-portable code.  The reason that I originally went with opaque
> data structures (I did it before giving the code to the ASF), was that
> most of the structures are defined totally differently on each
> platform.  By making the structures opaque, it became much harder for
> a developer to write code with APR that worked on some APR platforms,
> but not others.  If you play with the pointers, your code is very
> likely to work only on the platforms that you code on.
> But, I would like to hear from some of the active developers about this as well.
> Ryan
> On Fri, Jun 6, 2008 at 5:02 AM, Yann <yl@bee-ware.net> wrote:
>> I'm sorry to insist on this point but, in general, maybe you should consider
>> having a function that provides the sizeof() each opaque structure/type of
>> the APR (maybe not all of them, but at least some).
>> That would let the user "play" with the opaque types without breaking the
>> interest (portability, evolution ...) of this ones.
>> As far as I know, the APR is a C programming API, so let us play with the
>> pointers if we find it usefull.
>> I could propose the patch(s) if you agree and/or are interested by that.
>> If not, maybe you could let me know why ?
>> Thanks for your answers,
>> Yann.
>>>> Sander Striker wrote:
>>>>> Hello,
>>>>> I'm making a piece of software that recycles apr_sockets in
>>>>> sockets-pools.
>>>> Have you looked at apr_reslist in apr-util?
>>> It looks very interesting, thank you for the hint, however it seems that I
>>> have to do the same trick to prevent a leak with my_socket (a stucture
>>> containing the apr_socket and other things associated with it).
>>> As the pool used to create the reslist is passed to the contructor for its
>>> own allocations (my_sockets here), I suppose I have to create a subpool in
>>> the constructor where my_socket will be allocated, and keep a reference to
>>> the subpool in my_socket to be able to release all that in the destructor.
>>> Without this, that is using the reslist pool directly, memory will leak as
>>> my_socket allocated fields or even the apr_socket internals (addr and like)
>>> will stay in the pool after destruction.
>>> Did I miss something ?
>>>>> Each socket is allocated and created on its own pool (not a subpool,
>>>>> exactly a subpool of the internal global pool only).
>>>>> I've read on svn programming pages that it is not recommanded to do
>>>>> this,
>>>>> but I find it very usefull, that's the power of pools, IMHO.
>>>> The problem is the memory footprint that this brings with it.  Each pool
>>>> will pre-allocate 8k of memory.
>>> Maybe a subpool doesn't pre-allocate memory, or the problem remain with
>>> reslists (and the method above).
>>>>> Anyway, to make the things clean, I need a way to attach/detach pools
>>>>> to/from others, whether the socket belongs to the socket-pool's pool
>>>>> to
>>>>> the user's one.
>>>>> As the apr_pool_join() function is a noop (and I don't knwow if that's
>>>>> its
>>>>> purpose anyway), I used the apr_pool_cleanup_register()ing /
>>>>> apr_pool_cleanup_kill()ing mechanism to attach / detach pools between
>>>>> them.
>>>>> I create a small new API with my pools based on the APR ones, where I
>>>>> can
>>>>> attach/detach pools, as I said, but also malloc() and realloc() memories
>>>>> attached to a pool (with the same registering mechanism).
>>>>> My pool struct is like :
>>>>> struct my_pool_t {
>>>>>  apr_pool_t pool;
>>>>>  apr_pool_t *owner;
>>>>> };
>>>>> And the functions :
>>>>> apr_status_t my_pool_create(my_pool_t **pool, void *owner);
>>>>> apr_status_t my_pool_attach(my_pool_t *pool, void *owner);
>>>>> apr_status_t my_pool_detach(my_pool_t *pool);
>>>>> apr_status_t my_pmalloc(void *pool, apr_size_t size);
>>>>> apr_status_t my_pzalloc(void *pool, apr_size_t size);
>>>>> apr_status_t my_prealloc(void *pool, void *ptr, apr_size_t size);
>>>>> void my_pfree(void *pool, void *ptr);
>>>>> As you can see with the first element of the struct which is an APR pool
>>>>> and
>>>>> 'void*' types used in functions, I expect the functions to be
>>>>> "compatible"
>>>>> with the APR ones, that is I can use my_pool_t and apr_pool_t pools
>>>>> indistinctly with them (where the type is void*) ...
>>>> That's not the case, see below.
>>> Hum, I see, the pool stands in an allocator node, see below.
>>>>> My problem is that I can't initialize my_pool because I haven't got the
>>>>> sizeof(apr_pool_t), an opaque structure ...
>>>>> I understand the advantages of opaque types, but is there a way an
>>>>> apr_pool_sizeof() function be added (and exported) in the APR, simply
>>>>> like :
>>>>> APR_DECLARE(apr_size_t) apr_pool_sizeof(void)
>>>>> {
>>>>>  /* maybe the aligned SIZEOF_POOL_T should be used */
>>>>>  return sizeof(apr_pool_t);
>>>>> }
>>>>> With it, I could at least do :
>>>>>  apr_pool_create(&p, NULL);
>>>>>  memcpy(my_pool->pool, p, apr_pool_sizeof())
>>>> This would be a bad idea, as you'd be copying pointers and the like,
>>>> which
>>>> would be off as soon as copied.  Even if that were not the case, the
>>>> apr_pool_t
>>>> struct instance lives in an allocated block of memory from which the pool
>>>> will hand out memory.  This block in turn is managed by an allocator.
>>> But the allocator node shouldn't be destroyed (or reused) while the pool
>>> isn't, so I don't see why a copy of the pool couldn't do the job as well.
>>> The copy of the pointers and the like still reference the allocator node,
>>> and it should work.
>>> However all this becomes cheat and I'd better look at apr_reslist.
>>>>> Or should I consider using my_p*() functions strictly with my_pools ?
>>>>> Thanks for your advices, answers.
>>>> Cheers,
>>>> Sander
>>> Cheers, and thanks for your answers,
>>> Yann.

View raw message