Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #5477 > unrolled thread
| Started by | daknok <radekslupik@gmail.com> |
|---|---|
| First post | 2011-06-05 12:52 +0200 |
| Last post | 2011-06-16 14:42 -0400 |
| Articles | 20 on this page of 78 — 21 participants |
Back to article view | Back to comp.lang.c
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
Page 2 of 4 — ← Prev page 1 [2] 3 4 Next page →
| From | luser- -droog <mijoryx@yahoo.com> |
|---|---|
| Date | 2011-06-12 15:15 -0700 |
| Message-ID | <d677e296-f284-4fef-9d3a-3a119da4ea7c@d1g2000yqe.googlegroups.com> |
| In reply to | #5860 |
On Jun 11, 5:23 pm, Shao Miller <sha0.mil...@gmail.com> wrote: > On 6/11/2011 2:36 PM, ImpalerCore wrote: > > > > > If I understand correctly, malloc should always return an aligned > > pointer, so by knowing ALIGN_MAX, the pointer at offset ALIGN_MAX > > should also be suitably aligned for any other object. I think this > > might work, but I hesitate as the nuances of alignment issues continue > > to elude my understanding. > > Or you can put your accounting object at/near the end of the allocated > memory, as mentioned else-thread. Would anyone else mind mentioning > this or does nobody really do that? I thought it was fairly common > practice for some I/O buffers. Filtering... *sigh* With a suitable convention established for finding the end, sure. But the simplest way to find the end is to put a size field or pointer at the beginning, and we're back to the same alignment question. So it's hard to explore that option without making the entire issue more complicated.
[toc] | [prev] | [next] | [standalone]
| From | Shao Miller <sha0.miller@gmail.com> |
|---|---|
| Date | 2011-06-12 21:13 -0500 |
| Message-ID | <it3roq$ear$1@dont-email.me> |
| In reply to | #5927 |
On 6/12/2011 5:15 PM, luser- -droog wrote:
> On Jun 11, 5:23 pm, Shao Miller<sha0.mil...@gmail.com> wrote:
>> On 6/11/2011 2:36 PM, ImpalerCore wrote:
>>
>>> If I understand correctly, malloc should always return an aligned
>>> pointer, so by knowing ALIGN_MAX, the pointer at offset ALIGN_MAX
>>> should also be suitably aligned for any other object. I think this
>>> might work, but I hesitate as the nuances of alignment issues continue
>>> to elude my understanding.
>>
>> Or you can put your accounting object at/near the end of the allocated
>> memory, as mentioned else-thread. Would anyone else mind mentioning
>> this or does nobody really do that? I thought it was fairly common
>> practice for some I/O buffers. Filtering... *sigh*
>
> With a suitable convention established for finding the end, sure.
> But the simplest way to find the end is to put a size field or
> pointer at the beginning, and we're back to the same alignment
> question. So it's hard to explore that option without making the
> entire issue more complicated.
I agree that a disadvantage to accounting at the end is the convention
for finding the end.
The example code offered elsethread has a function that takes a 'size_t'
which must match what was passed to the allocator, and passing this
around is certainly overhead.
For a simple string-accounting struct which keeps track of the size, one
can pass 'sizeof *my_string + my_string->max_length' (or whatever), but
you're right; that seems like an awkward thing to pass to a
reference-releasing function.
For statically-sized objects, a macro makes things a bit easier (note
that 'ptr' is only evaluated once, for whatever that's worth):
#define release(ptr) (release_((ptr), sizeof *(ptr)))
Here's a code example, below. It ought to compile as one file. If
anyone has time to review it, what're some advantages and disadvantages
for the approach?:
#define ALL_IN_ONE 1
/**** ref_cnt.h */
/* For 'size_t' */
#include <stddef.h>
/*** Macros */
#define GetRefForFixedSizeObj(obj) \
(GetRefFromPtrAndSize((obj), sizeof *(obj)))
/*** Object types */
typedef void ** ref_counted_obj;
/*** Function types */
typedef void f_ref_cnt_free(ref_counted_obj);
/*** Functions */
extern ref_counted_obj GetRefFromPtrAndSize(void *, size_t);
extern ref_counted_obj NewRefCountedObj(size_t, f_ref_cnt_free *);
extern ref_counted_obj GetRef(ref_counted_obj);
extern void PutRef(ref_counted_obj);
/**** ref_cnt.c */
#include <stdlib.h>
#if !ALL_IN_ONE
#include <stddef.h>
#include "ref_cnt.h"
#endif
/*** Types */
struct ref_counted_obj_ {
void * obj;
unsigned int ref_count;
f_ref_cnt_free * dealloc;
};
/*** Functions */
static ptrdiff_t ref_at(size_t size) {
size_t result;
result = size;
result += sizeof (struct ref_counted_obj_);
/* Check for wrap-around */
if (result < size)
return 0;
--result;
result /= sizeof (struct ref_counted_obj_);
return (ptrdiff_t) result;
}
ref_counted_obj GetRefFromPtrAndSize(
void * ptr,
size_t size
) {
ptrdiff_t ref_index;
struct ref_counted_obj_ * ref;
ref_index = ref_at(size);
if (!ptr || !ref_index)
return NULL;
/* Point to the accounting info */
ref = ptr;
ref += ref_index;
/* Increment ref count and check for wrap-around */
if (!++ref->ref_count) {
--ref->ref_count;
return NULL;
}
return &ref->obj;
}
ref_counted_obj NewRefCountedObj(
size_t size,
f_ref_cnt_free * dealloc
) {
ptrdiff_t ref_index;
size_t new_size;
struct ref_counted_obj_ * ref;
ref_index = ref_at(size);
if (!ref_index)
return NULL;
/* Calculate required size */
new_size = (ref_index + 1) * sizeof *ref;
/* Check for wrap-around */
if (new_size < size)
return NULL;
/* Allocate and check for failure */
ref = malloc(new_size);
if (!ref)
return NULL;
/* Populate accounting info */
ref[ref_index].obj = ref;
ref += ref_index;
ref->ref_count = 1;
ref->dealloc = dealloc;
return &ref->obj;
}
ref_counted_obj GetRef(ref_counted_obj ref) {
struct ref_counted_obj_ * ref_;
if (!ref)
return NULL;
ref_ = (void *) ref;
/* Increment ref count and check for wrap-around */
if (++ref_->ref_count) {
--ref_->ref_count;
return NULL;
}
return ref;
}
void PutRef(ref_counted_obj ref) {
struct ref_counted_obj_ * ref_;
if (!ref)
return;
ref_ = (void *) ref;
/* Decrement ref count and check for zero */
if (!--ref_->ref_count) {
ref_->dealloc(ref);
free(ref_->obj);
}
return;
}
/**** Test program */
#include <stdio.h>
#include <string.h>
#if !ALL_IN_ONE
#include <stdlib.h>
#include "ref_cnt.h"
#endif
/*** Macros */
#define GetFooRef(foo) \
(GetRefFromPtrAndSize((foo), sizeof *(foo) + (foo)->len))
/*** Types */
struct foo {
double bobble;
size_t len;
char bear[1];
};
/*** Functions */
f_ref_cnt_free foo_dealloc;
void foo_dealloc(ref_counted_obj ptr) {
struct foo * bar;
bar = *ptr;
printf(
"foo_dealloc(%p): {%f, %d, \"%s\"}\n",
*ptr,
bar->bobble,
(int)bar->len,
bar->bear
);
return;
}
int main(void) {
ref_counted_obj bar_ref;
struct foo * bar;
char laughsalot[] = "Laughs-a-lot";
bar_ref = NewRefCountedObj(
sizeof *bar + sizeof laughsalot,
foo_dealloc
);
if (!bar_ref) {
puts("NewRefCountedObj() failed!");
return EXIT_FAILURE;
}
bar = *bar_ref;
bar->bobble = 3.14159;
bar->len = sizeof laughsalot;
memcpy(bar->bear, laughsalot, sizeof laughsalot);
/* Test re-getting the accounting info */
bar_ref = NULL;
bar_ref = GetFooRef(bar);
if (!bar_ref) {
puts("GetRefFromPtrAndSize() failed!");
free(bar); /* Yeah */
return EXIT_FAILURE;
}
/* We have two references */
PutRef(bar_ref);
PutRef(bar_ref);
return EXIT_SUCCESS;
}
[toc] | [prev] | [next] | [standalone]
| From | "Chris M. Thomasson" <cristom@charter.net> |
|---|---|
| Date | 2011-06-13 12:37 -0700 |
| Message-ID | <yFtJp.6017$_I7.2098@newsfe08.iad> |
| In reply to | #5949 |
"Shao Miller" <sha0.miller@gmail.com> wrote in message
news:it3roq$ear$1@dont-email.me...
[...]
>
> /*** Macros */
> #define GetFooRef(foo) \
> (GetRefFromPtrAndSize((foo), sizeof *(foo) + (foo)->len))
[...]
Using macros... Humm, well how about something simple like this:
http://codepad.org/CzUX4xDB
_____________________________________________________
typedef void (ref_count_func_dtor) (void*);
struct ref_count
{
unsigned count;
ref_count_func_dtor* fp_dtor;
};
#define REF_COUNT_STRUCT(mp_type) \
struct \
{ \
struct ref_count rcount; \
mp_type type; \
}
void* ref_count_sys_create(
size_t size,
ref_count_func_dtor* fp_dtor
){
struct ref_count* const self = malloc(size);
if (! self) return NULL;
self->count = 1;
self->fp_dtor = fp_dtor;
return self + 1;
}
#define REF_COUNT_CREATE(mp_type, mp_fp_dtor) \
ref_count_sys_create( \
sizeof(REF_COUNT_STRUCT(mp_type)), \
(mp_fp_dtor) \
)
#define ref_count_get(mp_state) \
((mp_state) \
? (((struct ref_count*)(mp_state)) - 1) \
: (NULL))
void*
ref_count_acquire(
void* state
){
struct ref_count* const self = ref_count_get(state);
if (! self) return NULL;
++self->count;
return state;
}
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);
}
_____________________________________________________
[toc] | [prev] | [next] | [standalone]
| From | "Chris M. Thomasson" <cristom@charter.net> |
|---|---|
| Date | 2011-06-13 12:54 -0700 |
| Message-ID | <nVtJp.8759$5v5.1511@newsfe11.iad> |
| In reply to | #5986 |
"Chris M. Thomasson" <cristom@charter.net> wrote in message news:yFtJp.6017$_I7.2098@newsfe08.iad... > "Shao Miller" <sha0.miller@gmail.com> wrote in message > news:it3roq$ear$1@dont-email.me... > [...] > >> >> /*** Macros */ >> #define GetFooRef(foo) \ >> (GetRefFromPtrAndSize((foo), sizeof *(foo) + (foo)->len)) > > [...] > > Using macros... Humm, well how about something simple like this: > > http://codepad.org/CzUX4xDB [...] Umm, I don't think that is going to work! ;^o
[toc] | [prev] | [next] | [standalone]
| From | Shao Miller <sha0.miller@gmail.com> |
|---|---|
| Date | 2011-06-13 16:40 -0500 |
| Message-ID | <it5sk5$ep2$1@dont-email.me> |
| In reply to | #5986 |
On 6/13/2011 2:37 PM, Chris M. Thomasson wrote:
> "Shao Miller"<sha0.miller@gmail.com> wrote in message
> news:it3roq$ear$1@dont-email.me...
> [...]
>
>>
>> /*** Macros */
>> #define GetFooRef(foo) \
>> (GetRefFromPtrAndSize((foo), sizeof *(foo) + (foo)->len))
>
> [...]
>
> Using macros... Humm, well how about something simple like this:
>
> http://codepad.org/CzUX4xDB
>
Cool. :)
> _____________________________________________________
> typedef void (ref_count_func_dtor) (void*);
>
>
> struct ref_count
> {
> unsigned count;
> ref_count_func_dtor* fp_dtor;
> };
>
>
> #define REF_COUNT_STRUCT(mp_type) \
> struct \
> { \
> struct ref_count rcount; \
> mp_type type; \
> }
>
>
> void* ref_count_sys_create(
> size_t size,
> ref_count_func_dtor* fp_dtor
> ){
> struct ref_count* const self = malloc(size);
> if (! self) return NULL;
> self->count = 1;
> self->fp_dtor = fp_dtor;
> return self + 1;
> }
>
How do you know that '(self + 1) == ((char *) self +
offsetof(REF_COUNT_STRUCT(mp_type), type))'? It might be unlikely that
there is padding there, but is no padding guaranteed?
>
> #define REF_COUNT_CREATE(mp_type, mp_fp_dtor) \
> ref_count_sys_create( \
> sizeof(REF_COUNT_STRUCT(mp_type)), \
> (mp_fp_dtor) \
> )
>
This interface appears to restrict callers to types whose sizes are
known and are integer constant expressions... Not that there's anything
wrong with that. :)
>
> #define ref_count_get(mp_state) \
> ((mp_state) \
> ? (((struct ref_count*)(mp_state)) - 1) \
> : (NULL))
>
>
> void*
> ref_count_acquire(
> void* state
> ){
> struct ref_count* const self = ref_count_get(state);
> if (! self) return NULL;
> ++self->count;
> return state;
> }
>
>
> 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);
> }
> _____________________________________________________
>
[toc] | [prev] | [next] | [standalone]
| From | ImpalerCore <jadill33@gmail.com> |
|---|---|
| Date | 2011-06-13 07:34 -0700 |
| Message-ID | <d6d7b471-ee68-443e-8592-c56e3555bef9@e26g2000vbz.googlegroups.com> |
| In reply to | #5860 |
On Jun 11, 6:23 pm, Shao Miller <sha0.mil...@gmail.com> wrote: > On 6/11/2011 2:36 PM, ImpalerCore wrote: > > > > > If I understand correctly, malloc should always return an aligned > > pointer, so by knowing ALIGN_MAX, the pointer at offset ALIGN_MAX > > should also be suitably aligned for any other object. I think this > > might work, but I hesitate as the nuances of alignment issues continue > > to elude my understanding. > > Or you can put your accounting object at/near the end of the allocated > memory, as mentioned else-thread. Would anyone else mind mentioning > this or does nobody really do that? I thought it was fairly common > practice for some I/O buffers. Filtering... *sigh* I just find the interface with your footer method to be more verbose without any tangible benefit. You add these four functions, yet you haven't tried to use them to come up with the reference counted allocation, copy, and release functions. size_t footer_at(size_t size); size_t size_with_footer(size_t size); footer_t * get_footer(void * mem, size_t size); void * malloc_with_footer(size_t size); My opinion is that the interface is cluttered, and doesn't even do what was asked, to reference count. When you come to the release step, are you going to require everyone to pass in the size of the allocated object? void rc_release( void* p, size_t I_need_to_know_the_object_size_to_find_the_footer ); Raw pointers don't carry the size of the allocated memory with them. I don't have access to what malloc uses internally. If you have a malloced character string, are you going to require the user to pass in the original allocated size of each allocated string so you can find the footer when you go to decrement its reference count? Placing the bookkeeping before the object pointer allows one to know where the bookkeeping object is without knowing the size or contents of the allocated object. Write your version of rc_malloc, rc_copy, and rc_release in terms of your footer interface and make a pros vs cons list. I just see more cons to this technique without any perceived pros. Best regards, John D.
[toc] | [prev] | [next] | [standalone]
| From | Shao Miller <sha0.miller@gmail.com> |
|---|---|
| Date | 2011-06-13 14:26 -0500 |
| Message-ID | <it5kok$m5o$1@dont-email.me> |
| In reply to | #5974 |
On 6/13/2011 9:34 AM, ImpalerCore wrote: > On Jun 11, 6:23 pm, Shao Miller<sha0.mil...@gmail.com> wrote: >> On 6/11/2011 2:36 PM, ImpalerCore wrote: >> >> >> >>> If I understand correctly, malloc should always return an aligned >>> pointer, so by knowing ALIGN_MAX, the pointer at offset ALIGN_MAX >>> should also be suitably aligned for any other object. I think this >>> might work, but I hesitate as the nuances of alignment issues continue >>> to elude my understanding. >> >> Or you can put your accounting object at/near the end of the allocated >> memory, as mentioned else-thread. Would anyone else mind mentioning >> this or does nobody really do that? I thought it was fairly common >> practice for some I/O buffers. Filtering... *sigh* > > I just find the interface with your footer method to be more verbose > without any tangible benefit. You add these four functions, yet you > haven't tried to use them to come up with the reference counted > allocation, copy, and release functions. > > size_t footer_at(size_t size); > size_t size_with_footer(size_t size); > footer_t * get_footer(void * mem, size_t size); > void * malloc_with_footer(size_t size); > > My opinion is that the interface is cluttered, and doesn't even do > what was asked, to reference count. When you come to the release > step, are you going to require everyone to pass in the size of the > allocated object? > > void rc_release( void* p, size_t > I_need_to_know_the_object_size_to_find_the_footer ); > > Raw pointers don't carry the size of the allocated memory with them. > I don't have access to what malloc uses internally. If you have a > malloced character string, are you going to require the user to pass > in the original allocated size of each allocated string so you can > find the footer when you go to decrement its reference count? Placing > the bookkeeping before the object pointer allows one to know where the > bookkeeping object is without knowing the size or contents of the > allocated object. > > Write your version of rc_malloc, rc_copy, and rc_release in terms of > your footer interface and make a pros vs cons list. I just see more > cons to this technique without any perceived pros. Thanks. I posted more code and thoughts about half a day before your response. Perhaps your news-reader has filtered it? :) Is keeping the accounting info before the object and working out some way to get the alignment right really much more common than keeping it after the object? (Obviously this is only a poll of anyone here who responds.) Have a pleasant day.
[toc] | [prev] | [next] | [standalone]
| From | ImpalerCore <jadill33@gmail.com> |
|---|---|
| Date | 2011-06-13 12:47 -0700 |
| Message-ID | <a290e025-ebf8-48cc-af63-55188e70d090@a10g2000vbz.googlegroups.com> |
| In reply to | #5984 |
On Jun 13, 3:26 pm, Shao Miller <sha0.mil...@gmail.com> wrote: > On 6/13/2011 9:34 AM, ImpalerCore wrote: > > > > > On Jun 11, 6:23 pm, Shao Miller<sha0.mil...@gmail.com> wrote: > >> On 6/11/2011 2:36 PM, ImpalerCore wrote: > > >>> If I understand correctly, malloc should always return an aligned > >>> pointer, so by knowing ALIGN_MAX, the pointer at offset ALIGN_MAX > >>> should also be suitably aligned for any other object. I think this > >>> might work, but I hesitate as the nuances of alignment issues continue > >>> to elude my understanding. > > >> Or you can put your accounting object at/near the end of the allocated > >> memory, as mentioned else-thread. Would anyone else mind mentioning > >> this or does nobody really do that? I thought it was fairly common > >> practice for some I/O buffers. Filtering... *sigh* > > > I just find the interface with your footer method to be more verbose > > without any tangible benefit. You add these four functions, yet you > > haven't tried to use them to come up with the reference counted > > allocation, copy, and release functions. > > > size_t footer_at(size_t size); > > size_t size_with_footer(size_t size); > > footer_t * get_footer(void * mem, size_t size); > > void * malloc_with_footer(size_t size); > > > My opinion is that the interface is cluttered, and doesn't even do > > what was asked, to reference count. When you come to the release > > step, are you going to require everyone to pass in the size of the > > allocated object? > > > void rc_release( void* p, size_t > > I_need_to_know_the_object_size_to_find_the_footer ); > > > Raw pointers don't carry the size of the allocated memory with them. > > I don't have access to what malloc uses internally. If you have a > > malloced character string, are you going to require the user to pass > > in the original allocated size of each allocated string so you can > > find the footer when you go to decrement its reference count? Placing > > the bookkeeping before the object pointer allows one to know where the > > bookkeeping object is without knowing the size or contents of the > > allocated object. > > > Write your version of rc_malloc, rc_copy, and rc_release in terms of > > your footer interface and make a pros vs cons list. I just see more > > cons to this technique without any perceived pros. > > Thanks. I posted more code and thoughts about half a day before your > response. Perhaps your news-reader has filtered it? :) > > Is keeping the accounting info before the object and working out some > way to get the alignment right really much more common than keeping it > after the object? (Obviously this is only a poll of anyone here who > responds.) It depends, if you're a debugging allocator, you'll likely want to put markers at each end to detect buffer overruns and the like. The dmalloc and SQLite allocators are examples that place information at both sides. The dmalloc allocator simply guesses the alignment by defining '#define ALLOCATION_ALIGNMENT N' in a conf.h file that just guesses the alignment from 'ac_cv_sizeof_long'. I haven't investigated how SQLite goes about it. For myself, I've never implemented a reference counted pointer scheme, so what you saw is just conjecture about how I'd attempt it. > Have a pleasant day. Same to you. John D.
[toc] | [prev] | [next] | [standalone]
| From | Shao Miller <sha0.miller@gmail.com> |
|---|---|
| Date | 2011-06-13 17:33 -0500 |
| Message-ID | <it5vnd$4qo$1@dont-email.me> |
| In reply to | #5987 |
On 6/13/2011 2:47 PM, ImpalerCore wrote:
> On Jun 13, 3:26 pm, Shao Miller<sha0.mil...@gmail.com> wrote:
>> On 6/13/2011 9:34 AM, ImpalerCore wrote:
>>
>>
>>
>>> On Jun 11, 6:23 pm, Shao Miller<sha0.mil...@gmail.com> wrote:
>>>> On 6/11/2011 2:36 PM, ImpalerCore wrote:
>>
>>>>> If I understand correctly, malloc should always return an aligned
>>>>> pointer, so by knowing ALIGN_MAX, the pointer at offset ALIGN_MAX
>>>>> should also be suitably aligned for any other object. I think this
>>>>> might work, but I hesitate as the nuances of alignment issues continue
>>>>> to elude my understanding.
>>
>>>> Or you can put your accounting object at/near the end of the allocated
>>>> memory, as mentioned else-thread. Would anyone else mind mentioning
>>>> this or does nobody really do that? I thought it was fairly common
>>>> practice for some I/O buffers. Filtering... *sigh*
>>
>>> I just find the interface with your footer method to be more verbose
>>> without any tangible benefit. You add these four functions, yet you
>>> haven't tried to use them to come up with the reference counted
>>> allocation, copy, and release functions.
>>
>>> size_t footer_at(size_t size);
>>> size_t size_with_footer(size_t size);
>>> footer_t * get_footer(void * mem, size_t size);
>>> void * malloc_with_footer(size_t size);
>>
>>> My opinion is that the interface is cluttered, and doesn't even do
>>> what was asked, to reference count. When you come to the release
>>> step, are you going to require everyone to pass in the size of the
>>> allocated object?
>>
>>> void rc_release( void* p, size_t
>>> I_need_to_know_the_object_size_to_find_the_footer );
>>
>>> Raw pointers don't carry the size of the allocated memory with them.
>>> I don't have access to what malloc uses internally. If you have a
>>> malloced character string, are you going to require the user to pass
>>> in the original allocated size of each allocated string so you can
>>> find the footer when you go to decrement its reference count? Placing
>>> the bookkeeping before the object pointer allows one to know where the
>>> bookkeeping object is without knowing the size or contents of the
>>> allocated object.
>>
>>> Write your version of rc_malloc, rc_copy, and rc_release in terms of
>>> your footer interface and make a pros vs cons list. I just see more
>>> cons to this technique without any perceived pros.
>>
>> Thanks. I posted more code and thoughts about half a day before your
>> response. Perhaps your news-reader has filtered it? :)
>>
>> Is keeping the accounting info before the object and working out some
>> way to get the alignment right really much more common than keeping it
>> after the object? (Obviously this is only a poll of anyone here who
>> responds.)
>
> It depends, if you're a debugging allocator, you'll likely want to put
> markers at each end to detect buffer overruns and the like. The
> dmalloc and SQLite allocators are examples that place information at
> both sides.
>
> The dmalloc allocator simply guesses the alignment by defining
> '#define ALLOCATION_ALIGNMENT N' in a conf.h file that just guesses
> the alignment from 'ac_cv_sizeof_long'. I haven't investigated how
> SQLite goes about it.
>
> For myself, I've never implemented a reference counted pointer scheme,
> so what you saw is just conjecture about how I'd attempt it.
Well, two people in another C-devoted forum suggested another concern
with keeping the accounting information at/near the end of the allocated
storage: Someone sloppy can overwrite it. By accounting near the
beginning, that might be less likely.
I'm just not sure how one gets the alignment at the beginning to be
guaranteed as correct without making an extra burden to callers, for C
implementations conforming to < C1X.
Given an adaptation of Mr. Chris M. Thomasson's macro:
#define ALIGNOF(type) (offsetof(struct{char c; type t;}, t))
(which, by the way, I just noticed doesn't appear to be guaranteed as
giving the same result every time due to a lack of tag, though that
might be highly unlikely)
We could have a 'malloc' wrapper:
void * malloc_aligned(size_t size, size_t alignment);
But then callers would need to:
some * p = malloc_aligned(
sizeof *p + optional_variable_length,
ALIGNOF(some)
);
where we'd forfeit the convenience of having 'some' appear just once.
Any pad-to-nice-alignment-at-the-beginning strategy for < C1X is just
guessing, isn't it? And the more conservative we are, the greater the
risk of wasted space?
If one only requires a 'ptrdiff_t' or 'size_t' at the beginning, this
might be minimal and could specify where additional accounting info at
the end is, but that does seem complicated.
But even with the overhead of tracking the size of the allocated data
and of requiring that paired with the pointer in order to find the
accounting info, are there scenarios where a caller _shouldn't_ know the
apparent size of the allocated data? Isn't that asking for trouble?
Sentinels are great for unknown lengths, but a call to 'malloc' requires
a known length... Shouldn't this be tracked somewhere as a good
programming practice in order to avoid out-of-bounds accesses?
[toc] | [prev] | [next] | [standalone]
| From | ImpalerCore <jadill33@gmail.com> |
|---|---|
| Date | 2011-06-14 12:14 -0700 |
| Message-ID | <ef5a24b9-9442-456f-b46b-72fb072775f9@hg8g2000vbb.googlegroups.com> |
| In reply to | #5993 |
On Jun 13, 6:33 pm, Shao Miller <sha0.mil...@gmail.com> wrote:
> On 6/13/2011 2:47 PM, ImpalerCore wrote:
>
>
>
> > On Jun 13, 3:26 pm, Shao Miller<sha0.mil...@gmail.com> wrote:
> >> On 6/13/2011 9:34 AM, ImpalerCore wrote:
>
> >>> On Jun 11, 6:23 pm, Shao Miller<sha0.mil...@gmail.com> wrote:
> >>>> On 6/11/2011 2:36 PM, ImpalerCore wrote:
>
> >>>>> If I understand correctly, malloc should always return an aligned
> >>>>> pointer, so by knowing ALIGN_MAX, the pointer at offset ALIGN_MAX
> >>>>> should also be suitably aligned for any other object. I think this
> >>>>> might work, but I hesitate as the nuances of alignment issues continue
> >>>>> to elude my understanding.
>
> >>>> Or you can put your accounting object at/near the end of the allocated
> >>>> memory, as mentioned else-thread. Would anyone else mind mentioning
> >>>> this or does nobody really do that? I thought it was fairly common
> >>>> practice for some I/O buffers. Filtering... *sigh*
>
> >>> I just find the interface with your footer method to be more verbose
> >>> without any tangible benefit. You add these four functions, yet you
> >>> haven't tried to use them to come up with the reference counted
> >>> allocation, copy, and release functions.
>
> >>> size_t footer_at(size_t size);
> >>> size_t size_with_footer(size_t size);
> >>> footer_t * get_footer(void * mem, size_t size);
> >>> void * malloc_with_footer(size_t size);
>
> >>> My opinion is that the interface is cluttered, and doesn't even do
> >>> what was asked, to reference count. When you come to the release
> >>> step, are you going to require everyone to pass in the size of the
> >>> allocated object?
>
> >>> void rc_release( void* p, size_t
> >>> I_need_to_know_the_object_size_to_find_the_footer );
>
> >>> Raw pointers don't carry the size of the allocated memory with them.
> >>> I don't have access to what malloc uses internally. If you have a
> >>> malloced character string, are you going to require the user to pass
> >>> in the original allocated size of each allocated string so you can
> >>> find the footer when you go to decrement its reference count? Placing
> >>> the bookkeeping before the object pointer allows one to know where the
> >>> bookkeeping object is without knowing the size or contents of the
> >>> allocated object.
>
> >>> Write your version of rc_malloc, rc_copy, and rc_release in terms of
> >>> your footer interface and make a pros vs cons list. I just see more
> >>> cons to this technique without any perceived pros.
>
> >> Thanks. I posted more code and thoughts about half a day before your
> >> response. Perhaps your news-reader has filtered it? :)
>
> >> Is keeping the accounting info before the object and working out some
> >> way to get the alignment right really much more common than keeping it
> >> after the object? (Obviously this is only a poll of anyone here who
> >> responds.)
>
> > It depends, if you're a debugging allocator, you'll likely want to put
> > markers at each end to detect buffer overruns and the like. The
> > dmalloc and SQLite allocators are examples that place information at
> > both sides.
>
> > The dmalloc allocator simply guesses the alignment by defining
> > '#define ALLOCATION_ALIGNMENT N' in a conf.h file that just guesses
> > the alignment from 'ac_cv_sizeof_long'. I haven't investigated how
> > SQLite goes about it.
>
> > For myself, I've never implemented a reference counted pointer scheme,
> > so what you saw is just conjecture about how I'd attempt it.
>
> Well, two people in another C-devoted forum suggested another concern
> with keeping the accounting information at/near the end of the allocated
> storage: Someone sloppy can overwrite it. By accounting near the
> beginning, that might be less likely.
Seems reasonable. For example, how much do you trust users of
sprintf?
> I'm just not sure how one gets the alignment at the beginning to be
> guaranteed as correct without making an extra burden to callers, for C
> implementations conforming to < C1X.
>
> Given an adaptation of Mr. Chris M. Thomasson's macro:
>
> #define ALIGNOF(type) (offsetof(struct{char c; type t;}, t))
>
> (which, by the way, I just noticed doesn't appear to be guaranteed as
> giving the same result every time due to a lack of tag, though that
> might be highly unlikely)
Can you elaborate?
> We could have a 'malloc' wrapper:
>
> void * malloc_aligned(size_t size, size_t alignment);
>
> But then callers would need to:
>
> some * p = malloc_aligned(
> sizeof *p + optional_variable_length,
> ALIGNOF(some)
> );
>
> where we'd forfeit the convenience of having 'some' appear just once.
>
> Any pad-to-nice-alignment-at-the-beginning strategy for < C1X is just
> guessing, isn't it? And the more conservative we are, the greater the
> risk of wasted space?
It's a cost benefit analysis. We're not necessarily limited to using
one single method. A simpler interface can use a conservative
alignment valid for any type to make it easier for the user (assuming
one can determine ALIGN_MAX with enough confidence through platform
and compiler documentation, autoconf, or some C offsetof
incantation). If more performance needs to be squeaked out, a more
complex interface may be used. Personally, I just haven't been in a
situation that's motivated me to think of using reference counting.
> If one only requires a 'ptrdiff_t' or 'size_t' at the beginning, this
> might be minimal and could specify where additional accounting info at
> the end is, but that does seem complicated.
>
> But even with the overhead of tracking the size of the allocated data
> and of requiring that paired with the pointer in order to find the
> accounting info, are there scenarios where a caller _shouldn't_ know the
> apparent size of the allocated data?
The design of malloc is predicated on the user not needing to track
the size of the allocation. Otherwise C would be designed with
'free( void* p, size_t sz )'. Of course, malloc is responsible to
track allocation size internally, but it's in the implementation
space, not user space. For better or worse, there is no standard
method to take a raw pointer and obtain its allocation size. There
are times when knowing the allocation space is desirable: designing a
custom allocator, managing an auto-resizing container like a string or
array, when its the destination buffer of a snprintf function, etc,
but certainly not universal.
> Isn't that asking for trouble?
> Sentinels are great for unknown lengths, but a call to 'malloc' requires
> a known length... Shouldn't this be tracked somewhere as a good
> programming practice in order to avoid out-of-bounds accesses?
That is in the realm of debugging allocators, which is good practice
to use. Delegating this responsibility directly to users is in my
opinion a bad idea.
Most debugging allocators use the preprocessor to replace instances of
'malloc' with their own special call to allocator. By providing your
own malloc wrapper, one can create an interface to allocate a
reference counted pointer through something like 'rc_malloc', but
still tap into dmalloc or valgrind to verify that your implementation
doesn't trash the address space, i.e.
---dmalloc.h---
#define malloc(size) \
dmalloc_malloc(__FILE__, __LINE__, (size), DMALLOC_FUNC_MALLOC, 0,
0)
Again, this is just one path from several viable methods to implement
reference counting. I'm not arguing for superiority of one method
over another simply because I have no real-use experience with
reference counting, just curiosity.
Best regards,
John D.
[toc] | [prev] | [next] | [standalone]
| From | Shao Miller <sha0.miller@gmail.com> |
|---|---|
| Date | 2011-06-15 02:16 -0500 |
| Message-ID | <it9io3$jsv$1@dont-email.me> |
| In reply to | #6075 |
On 6/14/2011 2:14 PM, ImpalerCore wrote:
> On Jun 13, 6:33 pm, Shao Miller<sha0.mil...@gmail.com> wrote:
>>
>> Well, two people in another C-devoted forum suggested another concern
>> with keeping the accounting information at/near the end of the allocated
>> storage: Someone sloppy can overwrite it. By accounting near the
>> beginning, that might be less likely.
>
> Seems reasonable. For example, how much do you trust users of
> sprintf?
>
Indeed.
>> I'm just not sure how one gets the alignment at the beginning to be
>> guaranteed as correct without making an extra burden to callers, for C
>> implementations conforming to< C1X.
>>
>> Given an adaptation of Mr. Chris M. Thomasson's macro:
>>
>> #define ALIGNOF(type) (offsetof(struct{char c; type t;}, t))
>>
>> (which, by the way, I just noticed doesn't appear to be guaranteed as
>> giving the same result every time due to a lack of tag, though that
>> might be highly unlikely)
>
> Can you elaborate?
>
If you have:
struct {
int x;
} foo;
struct {
int x;
} bar;
I believe that you are not guaranteed that 'sizeof foo == sizeof bar',
as they have different types... Though I find it highly unlikely.
Similarly, the 'ALIGNOF' macro above could yield different results upon
invocations with the same 'type' because the implementation could have
generated different padding for the different types of "helper" structs.
>> We could have a 'malloc' wrapper:
>>
>> void * malloc_aligned(size_t size, size_t alignment);
>>
>> But then callers would need to:
>>
>> some * p = malloc_aligned(
>> sizeof *p + optional_variable_length,
>> ALIGNOF(some)
>> );
>>
>> where we'd forfeit the convenience of having 'some' appear just once.
>>
>> Any pad-to-nice-alignment-at-the-beginning strategy for< C1X is just
>> guessing, isn't it? And the more conservative we are, the greater the
>> risk of wasted space?
>
> It's a cost benefit analysis. We're not necessarily limited to using
> one single method. A simpler interface can use a conservative
> alignment valid for any type to make it easier for the user (assuming
> one can determine ALIGN_MAX with enough confidence through platform
> and compiler documentation, autoconf, or some C offsetof
> incantation). If more performance needs to be squeaked out, a more
> complex interface may be used. Personally, I just haven't been in a
> situation that's motivated me to think of using reference counting.
>
Well, assuming the 'ALIGNOF' above is a pretty good alignment guess, the
code example below makes use of it to allocate an object with a
reference-counting prefix object. It doesn't have:
- 'sprintf' user concerns ;)
- the overhead of tracking an object's originally-allocated size
I'm not sure what disadvantages there are to the approach in the code
below. Any ideas? (Or anyone else?)
>> If one only requires a 'ptrdiff_t' or 'size_t' at the beginning, this
>> might be minimal and could specify where additional accounting info at
>> the end is, but that does seem complicated.
>>
>> But even with the overhead of tracking the size of the allocated data
>> and of requiring that paired with the pointer in order to find the
>> accounting info, are there scenarios where a caller _shouldn't_ know the
>> apparent size of the allocated data?
>
> The design of malloc is predicated on the user not needing to track
> the size of the allocation. Otherwise C would be designed with
> 'free( void* p, size_t sz )'. Of course, malloc is responsible to
> track allocation size internally, but it's in the implementation
> space, not user space. For better or worse, there is no standard
> method to take a raw pointer and obtain its allocation size. There
> are times when knowing the allocation space is desirable: designing a
> custom allocator, managing an auto-resizing container like a string or
> array, when its the destination buffer of a snprintf function, etc,
> but certainly not universal.
>
I agree that it's a burden to pass around a size, but was just
commenting on the sanity of having it handy.
>> Isn't that asking for trouble?
>> Sentinels are great for unknown lengths, but a call to 'malloc' requires
>> a known length... Shouldn't this be tracked somewhere as a good
>> programming practice in order to avoid out-of-bounds accesses?
>
> That is in the realm of debugging allocators, which is good practice
> to use. Delegating this responsibility directly to users is in my
> opinion a bad idea.
>
Hmmm... Yes I guess it's automation and burden-relief versus
encouraging awareness of every detail.
> Most debugging allocators use the preprocessor to replace instances of
> 'malloc' with their own special call to allocator. By providing your
> own malloc wrapper, one can create an interface to allocate a
> reference counted pointer through something like 'rc_malloc', but
> still tap into dmalloc or valgrind to verify that your implementation
> doesn't trash the address space, i.e.
>
> ---dmalloc.h---
>
> #define malloc(size) \
> dmalloc_malloc(__FILE__, __LINE__, (size), DMALLOC_FUNC_MALLOC, 0,
> 0)
>
> Again, this is just one path from several viable methods to implement
> reference counting. I'm not arguing for superiority of one method
> over another simply because I have no real-use experience with
> reference counting, just curiosity.
Well unfortunately, the 'pfxalloc' function below is not a drop-in
replacement for 'malloc', but a wrapper function or macro or both could
potentially produce a drop-in replacement.
Here's the code, which ought to compile as a single file, or one can
split it up into multiple files. Also available, with nice colours, at:
http://codepad.org/0R6QzND9
-----
/**
* Delete all lines containing
* 'ALL_IN_ONE' if you split this example
* into separate files.
*/
#define ALL_IN_ONE 1
/****
* pfxalloc.h
*
* Shao Miller, 2011
* It took several minutes to find
* a free *alloc. (No pun intended.)
*/
#ifndef PFXALLOC_H_
/* For 'offsetof' and 'size_t' */
#include <stddef.h>
/*** Macros */
#define PFXALLOC_H_
#ifndef alignof
/* Derived from Mr. Chris M. Thomasson */
#define alignof(type) \
(offsetof(struct {char c; type t;}, t))
#ifdef __alignof_is_defined
#undef __alignof_is_defined
#endif /* __alignof_is_defined */
#define __alignof_is_defined 1
#endif /* alignof */
/*** Functions */
/**
* Allocate memory for an object and an
* associated "prefix" object.
*
* @v pfx_size The "prefix" size.
* @v obj_alignment The object's alignment
* requirement.
* @v obj_size The object's size.
* @ret void * Points to the object,
* or is NULL for failure.
*/
extern void * pfxalloc(size_t, size_t, size_t);
/**
* Get an object's associated "prefix" object.
*
* @v obj The object to fetch the
* associated "prefix" for.
* @ret void * Points to the "prefix",
* or is NULL for failure.
*/
extern void * pfxget(void *);
#endif /* PFXALLOC_H_ */
/**** pfxalloc.c */
/* Shao Miller, 2011 */
/* For 'malloc' */
#include <stdlib.h>
#if !ALL_IN_ONE
/* For 'size_t', 'ptrdiff_t' and 'NULL' */
#include <stddef.h>
/* For 'alignof' */
#include "pfxalloc.h"
#endif /* !ALL_IN_ONE */
/*** Constants */
enum cv {
cv_ptrdiff_alignment =
alignof(ptrdiff_t),
cv_zero = 0
};
/*** Functions */
/**
* The layout looks like:
* +-----+-------------+--------+--------+
* | pfx | opt_padding | offset | |
* +- -+- -+- -+ object |
* | header | |
* +----------------------------+--------+
*/
void * pfxalloc(
size_t pfx_size,
size_t obj_alignment,
size_t obj_size
) {
size_t offset_at;
ptrdiff_t * offset;
size_t header_size;
size_t total_size;
unsigned char * mem;
unsigned char * obj;
/* Sanity-check alignment value */
if (obj_alignment & (obj_alignment - 1))
return NULL;
/* Calculate the offset position */
offset_at = pfx_size;
offset_at += sizeof *offset;
/* Check for wrap-around */
if (offset_at < pfx_size)
return NULL;
--offset_at;
offset_at /= sizeof *offset;
/* Calculate the header size */
header_size = (offset_at + 1) * sizeof *offset;
/* Check for wrap-around */
if (header_size < pfx_size)
return NULL;
/* Calculate padding */
if (obj_alignment > cv_ptrdiff_alignment) {
size_t new_hdr_size = header_size;
new_hdr_size += obj_alignment;
/* Check for wrap-around */
if (new_hdr_size < header_size)
return NULL;
--new_hdr_size;
new_hdr_size /= obj_alignment;
new_hdr_size *= obj_alignment;
header_size = new_hdr_size;
}
/* Allocate storage */
total_size = header_size + obj_size;
/* Check for wrap-around */
if (total_size < pfx_size || total_size < obj_size)
return NULL;
mem = malloc(total_size);
if (!mem)
return mem;
/* Point to the object */
obj = mem + header_size;
/* Note the offset to the prefix */
offset = (ptrdiff_t *) obj - 1;
*offset = obj - mem;
return obj;
}
/* Fetch an asociated prefix for an object */
void * pfxget(void * obj) {
ptrdiff_t * offset;
unsigned char * prefix;
if (!obj)
return obj;
offset = obj;
--offset;
prefix = obj;
prefix -= *offset;
return prefix;
}
/**** ref_cnt.h */
/* Shao Miller, 2011 */
#ifndef REF_CNT_H_
#if !ALL_IN_ONE
/* For 'size_t' */
#include <stddef.h>
#include "align.h"
#endif /* !ALL_IN_ONE */
/*** Macros */
#define REF_CNT_H_
/*** Function types */
typedef void f_ref_cnt_free(void *);
/*** Functions */
/**
* Create a new, reference-counted object
*
* @v size The size of the object
* to allocate, in bytes.
* @v alignment The alignment requirement
* for the object.
* @v dealloc The de-allocation function
* to call, when refs == 0.
* @ret void * Points to the newly-
* allocated object, or is
* NULL, upon failure.
*/
extern void * NewRefCountedObj(
size_t,
size_t,
f_ref_cnt_free *
);
/**
* Increment the reference count for an object.
*
* @v obj The object to reference.
* @ret void * Points to the object, or is
* NULL if too many references.
*/
extern void * GetRef(void *);
/**
* Decrement the reference count for an object.
*
* @v obj The object to dereference.
*/
extern void PutRef(void *);
#endif /* REF_CNT_H_ */
/**** ref_cnt.c */
/* Shao Miller, 2011 */
#if !ALL_IN_ONE
/* For 'size_t' */
#include <stddef.h>
#include "pfxalloc.h"
#include "ref_cnt.h"
#endif /* !ALL_IN_ONE */
/*** Types */
struct ref_counted_obj {
unsigned int ref_count;
f_ref_cnt_free * dealloc;
};
/*** Functions */
void * NewRefCountedObj(
size_t size,
size_t alignment,
f_ref_cnt_free * dealloc
) {
void * result;
struct ref_counted_obj * ref;
/* Allocate the object */
result = pfxalloc(
sizeof *ref,
alignment,
size
);
if (!result)
return result;
ref = pfxget(result);
if (!ref) {
/* Uh oh; this is unexpected! */
return ref;
}
/* Populate accounting info */
ref->ref_count = 1;
ref->dealloc = dealloc;
return result;
}
void * GetRef(void * obj) {
struct ref_counted_obj * ref;
ref = pfxget(obj);
if (!ref)
return ref;
/* Increment ref count and check for wrap-around */
if (!++ref->ref_count) {
--ref->ref_count;
return NULL;
}
return obj;
}
void PutRef(void * obj) {
struct ref_counted_obj * ref;
ref = pfxget(obj);
if (!ref)
return;
/* Decrement ref count and check for zero */
if (!--ref->ref_count) {
ref->dealloc(obj);
free(ref);
}
return;
}
/**** Test program */
/* Shao Miller, 2011 */
#include <stdio.h>
#include <string.h>
#if !ALL_IN_ONE
#include <stdlib.h>
#include "pfxalloc.h"
#include "ref_cnt.h"
#endif /* !ALL_IN_ONE */
/*** Types */
struct foo {
double bobble;
size_t len;
char bear[1];
};
/*** Functions */
f_ref_cnt_free foo_dealloc;
void foo_dealloc(void * ptr) {
struct foo * bar;
bar = ptr;
printf(
"foo_dealloc(%p): {%f, %d, \"%s\"}\n",
ptr,
bar->bobble,
(int)bar->len,
bar->bear
);
return;
}
int main(void) {
struct foo * bar;
char laughsalot[] = "Laughs-a-lot";
bar = NewRefCountedObj(
sizeof *bar + sizeof laughsalot,
alignof (struct foo),
foo_dealloc
);
if (!bar) {
puts("NewRefCountedObj() failed!");
return EXIT_FAILURE;
}
bar->bobble = 3.14159;
bar->len = sizeof laughsalot;
memcpy(bar->bear, laughsalot, sizeof laughsalot);
/* Test getting a reference */
bar = GetRef(bar);
if (!bar) {
puts("GetRef() failed!");
PutRef(bar);
return EXIT_FAILURE;
}
/* We have two references */
PutRef(bar);
PutRef(bar);
return EXIT_SUCCESS;
}
[toc] | [prev] | [next] | [standalone]
| From | "Chris M. Thomasson" <cristom@charter.net> |
|---|---|
| Date | 2011-06-15 15:34 -0700 |
| Message-ID | <BraKp.8802$F25.5131@newsfe04.iad> |
| In reply to | #5993 |
"Shao Miller" <sha0.miller@gmail.com> wrote in message
news:it5vnd$4qo$1@dont-email.me...
[...]
> Given an adaptation of Mr. Chris M. Thomasson's macro:
>
> #define ALIGNOF(type) (offsetof(struct{char c; type t;}, t))
>
> (which, by the way, I just noticed doesn't appear to be guaranteed as
> giving the same result every time due to a lack of tag, though that might
> be highly unlikely)
>
> We could have a 'malloc' wrapper:
>
> void * malloc_aligned(size_t size, size_t alignment);
>
> But then callers would need to:
>
> some * p = malloc_aligned(
> sizeof *p + optional_variable_length,
> ALIGNOF(some)
> );
>
> where we'd forfeit the convenience of having 'some' appear just once.
You mean something like this crazy shi%:
http://codepad.org/Ot7HL6Te
? ;^o
[...]
[toc] | [prev] | [next] | [standalone]
| From | "Chris M. Thomasson" <cristom@charter.net> |
|---|---|
| Date | 2011-06-15 15:42 -0700 |
| Message-ID | <rzaKp.360$lv6.162@newsfe12.iad> |
| In reply to | #6122 |
"Chris M. Thomasson" <cristom@charter.net> wrote in message news:BraKp.8802$F25.5131@newsfe04.iad... > "Shao Miller" <sha0.miller@gmail.com> wrote in message > news:it5vnd$4qo$1@dont-email.me... [...] >> We could have a 'malloc' wrapper: >> >> void * malloc_aligned(size_t size, size_t alignment); [...] >> where we'd forfeit the convenience of having 'some' appear just once. > > You mean something like this crazy shi%: > > http://codepad.org/Ot7HL6Te I was allocating too much space in the code above. Here is an "improved" version: http://codepad.org/fOAFnYCZ Sorry about that.
[toc] | [prev] | [next] | [standalone]
| From | "Chris M. Thomasson" <cristom@charter.net> |
|---|---|
| Date | 2011-06-16 13:45 -0700 |
| Message-ID | <TXtKp.9064$xh5.8258@newsfe02.iad> |
| In reply to | #6124 |
"Chris M. Thomasson" <cristom@charter.net> wrote in message
news:rzaKp.360$lv6.162@newsfe12.iad...
> "Chris M. Thomasson" <cristom@charter.net> wrote in message
> news:BraKp.8802$F25.5131@newsfe04.iad...
>> "Shao Miller" <sha0.miller@gmail.com> wrote in message
>> news:it5vnd$4qo$1@dont-email.me...
> [...]
>>> We could have a 'malloc' wrapper:
>>>
>>> void * malloc_aligned(size_t size, size_t alignment);
> [...]
>>> where we'd forfeit the convenience of having 'some' appear just once.
>>
>> You mean something like this crazy shi%:
>>
>> http://codepad.org/Ot7HL6Te
>
> I was allocating too much space in the code above. Here is an "improved"
> version:
>
> http://codepad.org/fOAFnYCZ
>
> Sorry about that.
I think there is an error in `xmalloc_aligned()' because I subtract
`sizeof(void*)' from the aligned user object base address! This might not be
correct because `sizeof(void*)' could be `4' and `ALIGN_OF(void*)' (assume
100% correct result for a moment) just might be 128!
Therefore, I need to use something like:
___________________________________________
#define ALIGN_PTR_SZ \
(ALIGN_OF(void*) > sizeof(void*) \
? ALIGN_OF(void*) \
: sizeof(void*))
___________________________________________
as an offset wrt the aligned "user object" portion of the allocated
memory...
;^/
[toc] | [prev] | [next] | [standalone]
| From | Shao Miller <sha0.miller@gmail.com> |
|---|---|
| Date | 2011-06-16 17:02 -0500 |
| Message-ID | <itduhi$qem$1@dont-email.me> |
| In reply to | #6184 |
On 6/16/2011 3:45 PM, Chris M. Thomasson wrote: > "Chris M. Thomasson"<cristom@charter.net> wrote in message > news:rzaKp.360$lv6.162@newsfe12.iad... >> "Chris M. Thomasson"<cristom@charter.net> wrote in message >> news:BraKp.8802$F25.5131@newsfe04.iad... >>> "Shao Miller"<sha0.miller@gmail.com> wrote in message >>> news:it5vnd$4qo$1@dont-email.me... >> [...] >>>> We could have a 'malloc' wrapper: >>>> >>>> void * malloc_aligned(size_t size, size_t alignment); >> [...] >>>> where we'd forfeit the convenience of having 'some' appear just once. >>> >>> You mean something like this crazy shi%: >>> >>> http://codepad.org/Ot7HL6Te >> >> I was allocating too much space in the code above. Here is an "improved" >> version: >> >> http://codepad.org/fOAFnYCZ >> >> Sorry about that. > > I think there is an error in `xmalloc_aligned()' because I subtract > `sizeof(void*)' from the aligned user object base address! This might not be > correct because `sizeof(void*)' could be `4' and `ALIGN_OF(void*)' (assume > 100% correct result for a moment) just might be 128! > I think you mean "assume 100% incorrect result for a moment," right? If it was a correct result, the alignment couldn't be greater than the 'sizeof'... The 'sizeof' must be an integer multiple of the alignment requirement, else arrays wouldn't work. I might have misunderstood you. :) > > Therefore, I need to use something like: > ___________________________________________ > #define ALIGN_PTR_SZ \ > (ALIGN_OF(void*)> sizeof(void*) \ > ? ALIGN_OF(void*) \ > : sizeof(void*)) > ___________________________________________ > > > as an offset wrt the aligned "user object" portion of the allocated > memory... > > ;^/ > Interesting code, by the way.
[toc] | [prev] | [next] | [standalone]
| From | "Chris M. Thomasson" <cristom@charter.net> |
|---|---|
| Date | 2011-06-16 15:18 -0700 |
| Message-ID | <RivKp.7992$_I7.2325@newsfe08.iad> |
| In reply to | #6191 |
"Shao Miller" <sha0.miller@gmail.com> wrote in message news:itduhi$qem$1@dont-email.me... > On 6/16/2011 3:45 PM, Chris M. Thomasson wrote: >> "Chris M. Thomasson"<cristom@charter.net> wrote in message >> news:rzaKp.360$lv6.162@newsfe12.iad... >>> "Chris M. Thomasson"<cristom@charter.net> wrote in message >>> news:BraKp.8802$F25.5131@newsfe04.iad... >>>> "Shao Miller"<sha0.miller@gmail.com> wrote in message >>>> news:it5vnd$4qo$1@dont-email.me... >>> [...] >>>>> We could have a 'malloc' wrapper: >>>>> >>>>> void * malloc_aligned(size_t size, size_t alignment); >>> [...] >>>>> where we'd forfeit the convenience of having 'some' appear just once. >>>> >>>> You mean something like this crazy shi%: >>>> >>>> http://codepad.org/Ot7HL6Te >>> >>> I was allocating too much space in the code above. Here is an "improved" >>> version: >>> >>> http://codepad.org/fOAFnYCZ >>> >>> Sorry about that. >> >> I think there is an error in `xmalloc_aligned()' because I subtract >> `sizeof(void*)' from the aligned user object base address! This might not >> be >> correct because `sizeof(void*)' could be `4' and `ALIGN_OF(void*)' >> (assume >> 100% correct result for a moment) just might be 128! >> > > I think you mean "assume 100% incorrect result for a moment," right? If > it was a correct result, the alignment couldn't be greater than the > 'sizeof'... The 'sizeof' must be an integer multiple of the alignment > requirement, else arrays wouldn't work. I might have misunderstood you. > :) Sorry; I was _really_ decoupling `ALIGN_OF()' with `sizeof()'!
[toc] | [prev] | [next] | [standalone]
| From | "Chris M. Thomasson" <cristom@charter.net> |
|---|---|
| Date | 2011-06-16 16:01 -0700 |
| Message-ID | <aXvKp.15287$8G4.11353@newsfe17.iad> |
| In reply to | #6192 |
"Chris M. Thomasson" <cristom@charter.net> wrote in message news:RivKp.7992$_I7.2325@newsfe08.iad... >> "Shao Miller" <sha0.miller@gmail.com> wrote in message [...] >>> I think there is an error in `xmalloc_aligned()' because I subtract >>> `sizeof(void*)' from the aligned user object base address! This might >>> not be >>> correct because `sizeof(void*)' could be `4' and `ALIGN_OF(void*)' >>> (assume >>> 100% correct result for a moment) just might be 128! >>> >> >> I think you mean "assume 100% incorrect result for a moment," right? If >> it was a correct result, the alignment couldn't be greater than the >> 'sizeof'... The 'sizeof' must be an integer multiple of the alignment >> requirement, else arrays wouldn't work. I might have misunderstood you. >> :) > > Sorry; I was _really_ decoupling `ALIGN_OF()' with `sizeof()'! think in terms of `sizeof(data-structure-A)' is less than alignment for said `(data-structure-A)'. This can be fairly common. sizeof(foo) can be 4 alignof(foo) might be 1024 Who knows right?
[toc] | [prev] | [next] | [standalone]
| From | Shao Miller <sha0.miller@gmail.com> |
|---|---|
| Date | 2011-06-16 18:44 -0500 |
| Message-ID | <ite4ga$6ud$1@dont-email.me> |
| In reply to | #6198 |
On 6/16/2011 6:01 PM, Chris M. Thomasson wrote: > "Chris M. Thomasson"<cristom@charter.net> wrote in message > news:RivKp.7992$_I7.2325@newsfe08.iad... >>> "Shao Miller"<sha0.miller@gmail.com> wrote in message > [...] >>>> I think there is an error in `xmalloc_aligned()' because I subtract >>>> `sizeof(void*)' from the aligned user object base address! This might >>>> not be >>>> correct because `sizeof(void*)' could be `4' and `ALIGN_OF(void*)' >>>> (assume >>>> 100% correct result for a moment) just might be 128! >>>> >>> >>> I think you mean "assume 100% incorrect result for a moment," right? If >>> it was a correct result, the alignment couldn't be greater than the >>> 'sizeof'... The 'sizeof' must be an integer multiple of the alignment >>> requirement, else arrays wouldn't work. I might have misunderstood you. >>> :) >> >> Sorry; I was _really_ decoupling `ALIGN_OF()' with `sizeof()'! > > think in terms of `sizeof(data-structure-A)' is less than alignment for said > `(data-structure-A)'. This can be fairly common. > > sizeof(foo) can be 4 > alignof(foo) might be 1024 > > Who knows right? > Nope; you've lost me. If we take your 'foo' example and do: foo array[2]; The first element will presumably be properly aligned at some multiple of 1024, then the next element will start 4 bytes later, which will be improperly aligned at ((some multiple of 1024) plus 4).
[toc] | [prev] | [next] | [standalone]
| From | "Chris M. Thomasson" <cristom@charter.net> |
|---|---|
| Date | 2011-06-16 17:11 -0700 |
| Message-ID | <bYwKp.15292$8G4.14906@newsfe17.iad> |
| In reply to | #6200 |
"Shao Miller" <sha0.miller@gmail.com> wrote in message news:ite4ga$6ud$1@dont-email.me... > On 6/16/2011 6:01 PM, Chris M. Thomasson wrote: >> "Chris M. Thomasson"<cristom@charter.net> wrote in message >> news:RivKp.7992$_I7.2325@newsfe08.iad... >>>> "Shao Miller"<sha0.miller@gmail.com> wrote in message >> [...] >>>>> I think there is an error in `xmalloc_aligned()' because I subtract >>>>> `sizeof(void*)' from the aligned user object base address! This might >>>>> not be >>>>> correct because `sizeof(void*)' could be `4' and `ALIGN_OF(void*)' >>>>> (assume >>>>> 100% correct result for a moment) just might be 128! >>>>> >>>> >>>> I think you mean "assume 100% incorrect result for a moment," right? >>>> If >>>> it was a correct result, the alignment couldn't be greater than the >>>> 'sizeof'... The 'sizeof' must be an integer multiple of the alignment >>>> requirement, else arrays wouldn't work. I might have misunderstood >>>> you. >>>> :) >>> >>> Sorry; I was _really_ decoupling `ALIGN_OF()' with `sizeof()'! >> >> think in terms of `sizeof(data-structure-A)' is less than alignment for >> said >> `(data-structure-A)'. This can be fairly common. >> >> sizeof(foo) can be 4 >> alignof(foo) might be 1024 >> >> Who knows right? >> > > Nope; you've lost me. [...] Yikes! Let me try to clarify: I was thinking in terms of an array of `struct object' in which the beginning of said array is aligned on a boundary that is greater than `sizeof(struct object)'. Imagine an array of N 128-byte objects that simply has to be aligned on a 4096-byte boundary. Please excuse any confusions I have caused! ;^(...
[toc] | [prev] | [next] | [standalone]
| From | Shao Miller <sha0.miller@gmail.com> |
|---|---|
| Date | 2011-06-16 18:39 -0500 |
| Message-ID | <ite48b$5h1$1@dont-email.me> |
| In reply to | #6184 |
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. :)
[toc] | [prev] | [next] | [standalone]
Page 2 of 4 — ← Prev page 1 [2] 3 4 Next page →
Back to top | Article view | comp.lang.c
csiph-web