Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
| 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> |
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
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