Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #6199

Re: Reference counting

From Shao Miller <sha0.miller@gmail.com>
Newsgroups comp.lang.c
Subject Re: Reference counting
Date 2011-06-16 18:39 -0500
Organization A noiseless patient Spider
Message-ID <ite48b$5h1$1@dont-email.me> (permalink)
References (7 earlier) <a290e025-ebf8-48cc-af63-55188e70d090@a10g2000vbz.googlegroups.com> <it5vnd$4qo$1@dont-email.me> <BraKp.8802$F25.5131@newsfe04.iad> <rzaKp.360$lv6.162@newsfe12.iad> <TXtKp.9064$xh5.8258@newsfe02.iad>

Show all headers | View raw


Some comments on your code, for whatever the comments are worth...

Over a couple of days, Chris M. Thomasson wrote:

> #include <stdio.h>
> #include <stdlib.h>
> #include <stddef.h>
> #include <assert.h>
>
> #if ! defined (ALIGN_UINTPTR_TYPE)
> #   define ALIGN_UINTPTR_TYPE size_t
> #endif
>

So it seems you allow for an override, above.  Whatever the choice, the 
result of casting a pointer to an integer type is 
implementation-defined[6.3.2.3p6].  The result needn't be particularly 
meaningful, though it'd probably be pretty sensible to convert to an 
integer representing a linear address for an environment with such an 
addressing model.  An implementation needn't support 'intptr_t' nor 
'uintptr_t', for example[7.18.1.4p1].

>
> typedef char ALIGN_STATIC_ASSERT
> [
>     sizeof(ALIGN_UINTPTR_TYPE) == sizeof(void*)
>     ? 1 : -1
> ];
>

Ok so whatever the choice of this special type, its size must be equal 
to 'sizeof (void *)'.  I guess the idea is that a 'void *' is an 
integer-in-disguise and casting to this integer type with the same size 
ought not to "involve much"?

>
> #define ALIGN_OF(mp_type)   \
>     offsetof(               \
>         struct              \
>         {                   \
>             char pad;       \
>             mp_type type;   \
>         },                  \
>         type                \
>     )
>

'mp' for "macro parameter"? :)

>
> #define ALIGN_UP(mp_ptr, mp_align)              \
>     ((void*)(                                   \
>         (((ALIGN_UINTPTR_TYPE)(mp_ptr)) +       \
>         ((mp_align) - 1)) & ~(((mp_align) - 1)) \
>     ))
>

Above, you cast a pointer to an integer type (presumably).  This assumes 
that the result can be manipulated arithmetically, then cast back to a 
pointer type[6.3.2.3p5], then the resulting pointer used.  That's 
probably true for several implementations, but a trap representation is 
also a possible result.

You might "statically" assert the presence of 'uintptr_t' and use it, 
since it has a few guarantees associated with it.  It's still not 
guaranteed (as far as I know) that manipulating the integer value 
arithmetically has any relationship to alignment or what the 
cast-to-pointer will point [in]to.

The bitwise operations are nice.

>
> void*
> xmalloc_aligned(
>     size_t header_size,
>     size_t object_size,
>     size_t align_size
> ){
>     size_t total_size;
>     unsigned char* tmp;
>     unsigned char* header;
>     unsigned char* header_ptr;
>     unsigned char* object;
>
>     align_size = align_size
>         ?   (size_t)ALIGN_UP(align_size, ALIGN_OF(void*))
>         :   ALIGN_OF(void*);
>

Aha.  Here you use 'ALIGN_UP' with an integer value as 'mp_ptr', so 
'ALIGN_UP' is designed for both pointer and integers.

If I read correctly, the 'ALIGN_UP' will yield a 'void *', which you 
cast to a 'size_t', above.  But earlier on you allowed for a user to 
specify a type other than the default 'size_t' as a preferred integer 
type for pointer conversion.  I see you have no choice here, since 
'align_size' is a 'size_t'.

If only this computation didn't have to invoke pointer conversions, 
since the macro arguments are integers and the result is an integer.  Oh 
well.

Each time you use 'ALIGN_OF', you have a "helper" struct without a tag. 
  Although it's probably pretty unlikely, it seems that an 
implementation could choose different padding each time, despite the 
same struct definition with the 'char' and the same 'mp_type' member.

>     total_size = (size_t)
>         ALIGN_UP(
>             header_size + sizeof(void*) +
>             object_size + ALIGN_OF(void*) + align_size,
>             ALIGN_OF(void*)
>         );
>

Hopefully the additions of these 'size_t' values don't wrap around.  The 
caller can always take the blame.

>     if (! (header = malloc(total_size))) return NULL;
>     tmp = ALIGN_UP(header + header_size, ALIGN_OF(void*));
>     object = ALIGN_UP(tmp + sizeof(void*), align_size);
>     header_ptr = object - sizeof(void*);
>     *((void**)header_ptr) = header;
>
>     return object;
> }
>

Does the resulting layout look like this?:

   [header_size] | padding | header_ptr | [object_size]

>
> #define xmalloc_aligned_get(mp_object)          \
>     ((mp_object)                                \
>     ?   (*((void**)(((unsigned char*)mp_object) \
>         - sizeof(void*))))                      \
>     :   NULL)
>

So one takes a pointer, back-tracks to an immediately preceding 'void 
*', then that pointer points to a header.  Aha.

>
> #define XMALLOC_ALIGNED(mp_header, mp_object)   \
>     xmalloc_aligned(                            \
>         sizeof(mp_header),                      \
>         sizeof(mp_object),                      \
>         ALIGN_OF(mp_object)                     \
>     )
>

So the macro user needs to understand that this convenience macro takes 
type-names.

>
> void
> xfree_aligned(
>     void* object
> ){
>     if (! object) return;
>     free(xmalloc_aligned_get(object));
> }
>
> typedef void (ref_count_func_dtor) (void*);
>

I'm not sure why function pointer 'typedef's are so popular when one can 
'typedef' functions, as you have above.  This 'typedef' can serve as a 
"safety measure" in that if you declare:

   ref_count_func_dtor some_func;

somewhere, the definition had better agree with the declared type.  I'm 
a bit confused by one of Microsoft's analysis tools which _appears_ (I 
could be wrong) to require functions to be declared with function 
pointer types prior to their definitions. *boggle*

I believe that parentheses are required in the 'typedef' for function 
_pointer_ types, of course.  (Heh.)

>
> struct ref_count
> {
>     unsigned count;
>     ref_count_func_dtor* fp_dtor;
> };
>
> void* ref_count_sys_create(
>     size_t object_size,
>     size_t align_size,
>     ref_count_func_dtor* fp_dtor
> ){
>     struct ref_count* self;
>     void* const object =
>         xmalloc_aligned(sizeof(*self), object_size, align_size);
>     if (! object) return NULL;
>     self = xmalloc_aligned_get(object);
>     self->count = 1;
>     self->fp_dtor = fp_dtor;
>     return object;
> }
>

Nice and simple.

>
> #define REF_COUNT_CREATE(mp_type, mp_fp_dtor)   \
>     ref_count_sys_create(                       \
>         sizeof(mp_type),                        \
>         ALIGN_OF(mp_type),                      \
>         (mp_fp_dtor)                            \
>     )
>
>
> #define ref_count_get(mp_object)    \
>     xmalloc_aligned_get(mp_object)
>
>
> void*
> ref_count_acquire(
>     void* state
> ){
>     struct ref_count* const self = ref_count_get(state);
>     if (! self) return NULL;
>     ++self->count;
>     return state;
> }
>

Hopefully the reference count doesn't wrap around.

>
> void
> ref_count_release(
>     void* state
> ){
>     struct ref_count* const self = ref_count_get(state);
>     if (! self) return;
>     if (--self->count) return;
>     if (self->fp_dtor) self->fp_dtor(state);
>     free(self);
> }
>

So simple, so nice.

>
> struct foo
> {
>     /*__declspec(align(128))*/ double state;
> };
>
>
> void
> foo_ref_count_dtor(
>     void* state
> ){
>     struct foo* const self = state;
>
>     printf("foo_ref_count_dtor::%p - %f\n",
>            (void*)self, self->state);
> }
>

Why not use 'state' instead of '(void*)self'?  (Not that it matters.)

>
> int main(void)
> {
>     struct foo* foo1 =
>         REF_COUNT_CREATE(struct foo, foo_ref_count_dtor);
>
>     struct foo* foo2;
>
>     if (! foo1) return EXIT_FAILURE;
>
>     foo1->state = -665;
>
>     foo2 = ref_count_acquire(foo1);
>
>     foo2->state -= 1;
>
>     ref_count_release(foo1);
>     ref_count_release(foo2);
>
>     return EXIT_SUCCESS;
> }

Pretty nifty. :)

Back to comp.lang.c | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread


Thread

Reference counting daknok <radekslupik@gmail.com> - 2011-06-05 12:52 +0200
  Re: Reference counting Angel <angel+news@spamcop.net> - 2011-06-05 11:17 +0000
    Re: Reference counting Gene <gene.ressler@gmail.com> - 2011-06-06 20:07 -0700
      Multiple Inheritance (Was Re: Reference counting) Shao Miller <sha0.miller@gmail.com> - 2011-06-11 03:57 -0500
        Re: Multiple Inheritance (Was Re: Reference counting) Dr Nick <3-nospam@temporary-address.org.uk> - 2011-06-12 07:22 +0100
  Re: Reference counting China Blue Angels <chine.bleu@yahoo.com> - 2011-06-05 05:07 -0700
  Re: Reference counting "BartC" <bc@freeuk.com> - 2011-06-05 13:14 +0100
    Re: Reference counting daknok <daknok@example.com> - 2011-06-05 14:22 +0200
      Re: Reference counting "BartC" <bc@freeuk.com> - 2011-06-05 14:45 +0100
        Re: Reference counting daknok <daknok@example.com> - 2011-06-05 17:01 +0200
          Re: Reference counting Eric Sosman <esosman@ieee-dot-org.invalid> - 2011-06-05 18:06 -0400
          Re: Reference counting Dr Nick <3-nospam@temporary-address.org.uk> - 2011-06-12 07:25 +0100
  Re: Reference counting daknok <daknok@example.com> - 2011-06-05 15:29 +0200
  Re: Reference counting Shao Miller <sha0.miller@gmail.com> - 2011-06-05 12:17 -0500
  Re: Reference counting cri@tiac.net (Richard Harter) - 2011-06-05 17:11 +0000
  Re: Reference counting ImpalerCore <jadill33@gmail.com> - 2011-06-10 11:30 -0700
    Re: Reference counting Shao Miller <sha0.miller@gmail.com> - 2011-06-10 16:04 -0400
    Re: Reference counting James Kuyper <jameskuyper@verizon.net> - 2011-06-10 22:56 -0400
      Re: Reference counting ImpalerCore <jadill33@gmail.com> - 2011-06-11 12:36 -0700
        Re: Reference counting Shao Miller <sha0.miller@gmail.com> - 2011-06-11 17:23 -0500
          Re: Reference counting luser- -droog <mijoryx@yahoo.com> - 2011-06-12 15:15 -0700
            Re: Reference counting Shao Miller <sha0.miller@gmail.com> - 2011-06-12 21:13 -0500
              Re: Reference counting "Chris M. Thomasson" <cristom@charter.net> - 2011-06-13 12:37 -0700
                Re: Reference counting "Chris M. Thomasson" <cristom@charter.net> - 2011-06-13 12:54 -0700
                Re: Reference counting Shao Miller <sha0.miller@gmail.com> - 2011-06-13 16:40 -0500
          Re: Reference counting ImpalerCore <jadill33@gmail.com> - 2011-06-13 07:34 -0700
            Re: Reference counting Shao Miller <sha0.miller@gmail.com> - 2011-06-13 14:26 -0500
              Re: Reference counting ImpalerCore <jadill33@gmail.com> - 2011-06-13 12:47 -0700
                Re: Reference counting Shao Miller <sha0.miller@gmail.com> - 2011-06-13 17:33 -0500
                Re: Reference counting ImpalerCore <jadill33@gmail.com> - 2011-06-14 12:14 -0700
                Re: Reference counting Shao Miller <sha0.miller@gmail.com> - 2011-06-15 02:16 -0500
                Re: Reference counting "Chris M. Thomasson" <cristom@charter.net> - 2011-06-15 15:34 -0700
                Re: Reference counting "Chris M. Thomasson" <cristom@charter.net> - 2011-06-15 15:42 -0700
                Re: Reference counting "Chris M. Thomasson" <cristom@charter.net> - 2011-06-16 13:45 -0700
                Re: Reference counting Shao Miller <sha0.miller@gmail.com> - 2011-06-16 17:02 -0500
                Re: Reference counting "Chris M. Thomasson" <cristom@charter.net> - 2011-06-16 15:18 -0700
                Re: Reference counting "Chris M. Thomasson" <cristom@charter.net> - 2011-06-16 16:01 -0700
                Re: Reference counting Shao Miller <sha0.miller@gmail.com> - 2011-06-16 18:44 -0500
                Re: Reference counting "Chris M. Thomasson" <cristom@charter.net> - 2011-06-16 17:11 -0700
                Re: Reference counting Shao Miller <sha0.miller@gmail.com> - 2011-06-16 18:39 -0500
        Re: Reference counting "Chris M. Thomasson" <cristom@charter.net> - 2011-06-11 16:51 -0700
          Re: Reference counting "Chris M. Thomasson" <cristom@charter.net> - 2011-06-11 18:28 -0700
            Re: Reference counting Shao Miller <sha0.miller@gmail.com> - 2011-06-12 16:10 -0500
            Re: Reference counting ImpalerCore <jadill33@gmail.com> - 2011-06-13 07:36 -0700
      Re: Reference counting Tim Rentsch <txr@alumni.caltech.edu> - 2011-06-14 15:00 -0700
  Re: Reference counting luser- -droog <mijoryx@yahoo.com> - 2011-06-13 21:46 -0700
    Re: Reference counting Shao Miller <sha0.miller@gmail.com> - 2011-06-14 03:19 -0500
      Re: Reference counting Angel <angel+news@spamcop.net> - 2011-06-14 07:31 +0000
        Re: Reference counting Shao Miller <sha0.miller@gmail.com> - 2011-06-14 05:02 -0500
        Re: Reference counting Keith Thompson <kst-u@mib.org> - 2011-06-14 09:03 -0700
          Re: Reference counting luser- -droog <mijoryx@yahoo.com> - 2011-06-14 10:23 -0700
            Re: Reference counting Shao Miller <sha0.miller@gmail.com> - 2011-06-14 13:46 -0500
          Re: Reference counting Tim Rentsch <txr@alumni.caltech.edu> - 2011-06-14 15:05 -0700
            Re: Reference counting Keith Thompson <kst-u@mib.org> - 2011-06-14 16:44 -0700
              Re: Reference counting Tim Rentsch <txr@alumni.caltech.edu> - 2011-06-15 06:54 -0700
                Re: Reference counting Keith Thompson <kst-u@mib.org> - 2011-06-15 08:46 -0700
                Re: Reference counting pete <pfiland@mindspring.com> - 2011-06-15 22:19 -0400
                Re: Reference counting James Kuyper <jameskuyper@verizon.net> - 2011-06-15 23:03 -0400
                Re: Reference counting Tim Rentsch <txr@alumni.caltech.edu> - 2011-06-19 14:48 -0700
        Re: Reference counting Seebs <usenet-nospam@seebs.net> - 2011-06-14 17:16 +0000
    Re: Reference counting luser- -droog <mijoryx@yahoo.com> - 2011-06-14 20:53 -0700
      Re: Reference counting Shao Miller <sha0.miller@gmail.com> - 2011-06-16 18:49 -0500
  Re: Reference counting "io_x" <a@b.c.invalid> - 2011-06-14 08:30 +0200
    Re: Reference counting "io_x" <a@b.c.invalid> - 2011-06-14 09:15 +0200
      Re: Reference counting Shao Miller <sha0.miller@gmail.com> - 2011-06-14 04:21 -0500
      Re: Reference counting "io_x" <a@b.c.invalid> - 2011-06-16 10:35 +0200
        Re: Reference counting Ian Collins <ian-news@hotmail.com> - 2011-06-16 20:36 +1200
        Re: Reference counting "io_x" <a@b.c.invalid> - 2011-06-16 11:21 +0200
          Re: Reference counting "io_x" <a@b.c.invalid> - 2011-06-19 17:57 +0200
          Re: Reference counting "io_x" <a@b.c.invalid> - 2011-06-19 20:01 +0200
            Re: Reference counting Keith Thompson <kst-u@mib.org> - 2011-06-19 11:07 -0700
            Re: Reference counting Shao Miller <sha0.miller@gmail.com> - 2011-06-19 23:15 -0500
              Re: Reference counting "io_x" <a@b.c.invalid> - 2011-06-20 08:21 +0200
        Re: Reference counting Shao Miller <sha0.miller@gmail.com> - 2011-06-16 19:05 -0500
          Re: Reference counting Ian Collins <ian-news@hotmail.com> - 2011-06-17 12:09 +1200
  Re: Reference counting luser- -droog <mijoryx@yahoo.com> - 2011-06-15 08:40 -0700
  Re: Reference counting "christian.bau" <christian.bau@cbau.wanadoo.co.uk> - 2011-06-16 11:08 -0700
    Re: Reference counting Shao Miller <sha0.miller@gmail.com> - 2011-06-16 14:42 -0400

csiph-web