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


Groups > comp.lang.c > #5477 > unrolled thread

Reference counting

Started bydaknok <radekslupik@gmail.com>
First post2011-06-05 12:52 +0200
Last post2011-06-16 14:42 -0400
Articles 20 on this page of 78 — 21 participants

Back to article view | Back to comp.lang.c


Contents

  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 1 of 4  [1] 2 3 4  Next page →


#5477 — Reference counting

Fromdaknok <radekslupik@gmail.com>
Date2011-06-05 12:52 +0200
SubjectReference counting
Message-ID<4deb6008$0$28457$703f8584@textnews.kpn.nl>
Hi,

If I want to do simple reference counting for different structures I 
would go like this:

struct String {
    unsigned references;
    char *cString;
    size_t length;
};

void StringRelease(struct String *str) {
    str->references--;
    if (str->references == 0) {
        free(str->cString);
        free(str);
    }
}

struct String *StringRetain(struct String *str) {
    str->references++;
    return str;
}

Though if I have about ten structs, I have ten different functions to 
increase and decrease the reference count. Is it, in some way, possible 
to just provide one function for increasing and one function for 
decreasing the reference count which can be used for all structs with a 
reference count?

[toc] | [next] | [standalone]


#5479

FromAngel <angel+news@spamcop.net>
Date2011-06-05 11:17 +0000
Message-ID<slrniumpdo.bkn.angel+news@pearlgates.net>
In reply to#5477
On 2011-06-05, daknok <radekslupik@gmail.com> wrote:
> Hi,
>
> If I want to do simple reference counting for different structures I 
> would go like this:
>
> struct String {
>     unsigned references;
>     char *cString;
>     size_t length;
> };
>
> void StringRelease(struct String *str) {
>     str->references--;
>     if (str->references == 0) {
>         free(str->cString);
>         free(str);
>     }
> }
>
> struct String *StringRetain(struct String *str) {
>     str->references++;
>     return str;
> }
>
> Though if I have about ten structs, I have ten different functions to 
> increase and decrease the reference count. Is it, in some way, possible 
> to just provide one function for increasing and one function for 
> decreasing the reference count which can be used for all structs with a 
> reference count?

There are number of ways to do this. One of the easiest (but least
flexible) is to start all your structures with the same reference
variable, of the same type, like this:

struct a
{
	int ref_count;
	char *data;
	char *more_data;
};

struct b
{
	int ref_count;
	int number;
	int another_number;
};

Now you can safely read the ref_count from any of these structures, for
example like this:

struct ref_count
{
	int ref_count;
};

void increase_refcount(void *data)
{
	((struct refcount *) data)->refcount++;
}

You can safely pass either pointers to struct a or struct b to this
function, and it will work as expected. The standard guarantees that
shared fields at the beginning of structures are compatible. In a way,
this is a primitive C implementation of inheritance.

The other way I used this same principle to create a generic linked
list. Similar tricks are also used in the Linux kernel, and in the
network parts of glibc.


-- 
"C provides a programmer with more than enough rope to hang himself.
C++ provides a firing squad, blindfold and last cigarette."
- seen in comp.lang.c

[toc] | [prev] | [next] | [standalone]


#5595

FromGene <gene.ressler@gmail.com>
Date2011-06-06 20:07 -0700
Message-ID<2117f4ec-91e1-45ae-a7cc-4ae7c85603d6@bl1g2000vbb.googlegroups.com>
In reply to#5479
On Jun 5, 7:17 am, Angel <angel+n...@spamcop.net> wrote:
> On 2011-06-05, daknok <radekslu...@gmail.com> wrote:
>
>
>
>
>
> > Hi,
>
> > If I want to do simple reference counting for different structures I
> > would go like this:
>
> > struct String {
> >     unsigned references;
> >     char *cString;
> >     size_t length;
> > };
>
> > void StringRelease(struct String *str) {
> >     str->references--;
> >     if (str->references == 0) {
> >         free(str->cString);
> >         free(str);
> >     }
> > }
>
> > struct String *StringRetain(struct String *str) {
> >     str->references++;
> >     return str;
> > }
>
> > Though if I have about ten structs, I have ten different functions to
> > increase and decrease the reference count. Is it, in some way, possible
> > to just provide one function for increasing and one function for
> > decreasing the reference count which can be used for all structs with a
> > reference count?
>
> There are number of ways to do this. One of the easiest (but least
> flexible) is to start all your structures with the same reference
> variable, of the same type, like this:
>
> struct a
> {
>         int ref_count;
>         char *data;
>         char *more_data;
>
> };
>
> struct b
> {
>         int ref_count;
>         int number;
>         int another_number;
>
> };
>
> Now you can safely read the ref_count from any of these structures, for
> example like this:
>
> struct ref_count
> {
>         int ref_count;
>
> };
>
> void increase_refcount(void *data)
> {
>         ((struct refcount *) data)->refcount++;
>
> }
>
> You can safely pass either pointers to struct a or struct b to this
> function, and it will work as expected. The standard guarantees that
> shared fields at the beginning of structures are compatible. In a way,
> this is a primitive C implementation of inheritance.

I asked about this here some time back.  The folks who know the
Standard well denied that this is portable.  The standard gives you
now way to rely on common prefixes of fields to be laid out the same
way in memory.  But you _can_ rely on casts between the first field
and an enclosing struct type to work correctly. So the fully portable
way is this:

typedef enum { StringTag, URLTag, ... } TAG;
typedef unsigned REF_COUNT;

typedef struct {
  TAG tag;
  REF_COUNT ref_count;
} HEADER, *REF_COUNTED_OBJECT_PTR;

// every kind object needs the same initial header field.
typedef struct string_s {
  HEADER hdr[1];
  char *text;
  unsigned length;
} STRING;

REF_COUNTED_OBJECT_PTR make_string(void)
{
  STRING *s = safe_malloc(sizeof(STRING));
  s->hdr->tag = StringTag;
  s->hdr->ref_count = 0;
  s->text = NULL;
  s->length = 0;
  return (REF_COUNTED_OJBECT_PTR)s;
}

REF_COUNTED_OBJECT_PTR ref (REF_COUNTED_OBJECT_PTR p)
{
  p->ref_count++;
  return p;
}

void deref (REF_COUNTED_OBJECT_PTR p)
{
  if (--p->ref_count == 0)
    switch (p->tag) {
    case StringTag:
      safe_free((STRING*)p);
      break;
    case ...
    }
  return p;
}

... now for example
{
  REF_COUNTED_OJBECT_PTR x, s = ref(make_string());
  ... use s
  x = ref(s);
  ... use x
  deref(s);
  ... yada yada
  deref(x); // causes deallocation.
}

[toc] | [prev] | [next] | [standalone]


#5838 — Multiple Inheritance (Was Re: Reference counting)

FromShao Miller <sha0.miller@gmail.com>
Date2011-06-11 03:57 -0500
SubjectMultiple Inheritance (Was Re: Reference counting)
Message-ID<isv74r$s8b$1@dont-email.me>
In reply to#5595
On 6/6/2011 10:07 PM, Gene wrote:
> On Jun 5, 7:17 am, Angel<angel+n...@spamcop.net>  wrote:
>> On 2011-06-05, daknok<radekslu...@gmail.com>  wrote:
>>
>>> ...
>>> If I want to do simple reference counting for different structures I
>>> would go like this:
>>> ...
>>> Though if I have about ten structs, I have ten different functions to
>>> increase and decrease the reference count. Is it, in some way, possible
>>> to just provide one function for increasing and one function for
>>> decreasing the reference count which can be used for all structs with a
>>> reference count?
>>
>> There are number of ways to do this. One of the easiest (but least
>> flexible) is to start all your structures with the same reference
>> variable, of the same type, like this:
>>
>> struct a
>> {
>>          int ref_count;
>>          char *data;
>>          char *more_data;
>>
>> };
>>
>> struct b
>> {
>>          int ref_count;
>>          int number;
>>          int another_number;
>>
>> };
>>
>> Now you can safely read the ref_count from any of these structures, for
>> example like this:
>>
>> struct ref_count
>> {
>>          int ref_count;
>>
>> };
>>
>> void increase_refcount(void *data)
>> {
>>          ((struct refcount *) data)->refcount++;
>>
>> }
>>
>> You can safely pass either pointers to struct a or struct b to this
>> function, and it will work as expected. The standard guarantees that
>> shared fields at the beginning of structures are compatible. In a way,
>> this is a primitive C implementation of inheritance.
>
> I asked about this here some time back.  The folks who know the
> Standard well denied that this is portable.  The standard gives you
> now way to rely on common prefixes of fields to be laid out the same
> way in memory.  But you _can_ rely on casts between the first field
> and an enclosing struct type to work correctly. So the fully portable
> way is this:
>

Does anyone recall which thread this was asked about in?  I'm curious as 
to whether or not "the folks who know the Standard well" had offered 
concerns beyond alignment.

If 'struct refcount' (above) has an alignment requirement that is not 
met by where 'data' in 'increase_refcount' (above) points to, then the 
behaviour appears to be undefined[6.3.2.3p7].  But as alluded to above, 
my impressions is that the alignment requirement of a struct or union 
must satisfy the alignment requirement(s) of its member(s), so a pointer 
to the first member (or element) can be cast to a pointer to the 
surrounding struct or union (or array).

> typedef enum { StringTag, URLTag, ... } TAG;
> typedef unsigned REF_COUNT;
>
> typedef struct {
>    TAG tag;
>    REF_COUNT ref_count;
> } HEADER, *REF_COUNTED_OBJECT_PTR;
>
> // every kind object needs the same initial header field.
> typedef struct string_s {
>    HEADER hdr[1];
>    char *text;
>    unsigned length;
> } STRING;
>
> REF_COUNTED_OBJECT_PTR make_string(void)
> {
>    STRING *s = safe_malloc(sizeof(STRING));
>    s->hdr->tag = StringTag;
>    s->hdr->ref_count = 0;
>    s->text = NULL;
>    s->length = 0;
>    return (REF_COUNTED_OJBECT_PTR)s;
> }
>

Which you suggested might've been better as:

   return s->hdr;

(I hope you don't mind my including that from our brief, private 
discussion.)

> REF_COUNTED_OBJECT_PTR ref (REF_COUNTED_OBJECT_PTR p)
> {
>    p->ref_count++;
>    return p;
> }
>
> void deref (REF_COUNTED_OBJECT_PTR p)
> {
>    if (--p->ref_count == 0)
>      switch (p->tag) {
>      case StringTag:
>        safe_free((STRING*)p);
>        break;
>      case ...
>      }
>    return p;
> }
>
> ... now for example
> {
>    REF_COUNTED_OJBECT_PTR x, s = ref(make_string());
>    ... use s
>    x = ref(s);
>    ... use x
>    deref(s);
>    ... yada yada
>    deref(x); // causes deallocation.
> }

The only "problem" I have with the "first member" strategy 
('container_of', 'CONTAINING_RECORD', etc.) is in regards to 
extensibility...

So all of the structs that you define 'HEADER' as the first member for 
are all effectively reference-countable using the above strategy. 
That's fine.

Then perhaps a day comes when you might like to actually track some 
reference-countable objects in linked lists, but maybe not others.  So 
maybe you do:

   struct ref_countable_and_linked_list_trackable {
       HEADER hdr[1];
       LIST_ENTRY link[1];
     };

And then you revisit the code and change, let's say, 'struct string_s' to:

   typedef struct string_s {
       struct ref_countable_and_linked_list_trackable hdr[1];
       char *text;
       unsigned length;
     } STRING;

There might be several struct definitions to change, too.

Then perhaps a day comes when you might like to actually allow for some 
object types to include an "extension" pointer because you'd like to use 
an interface where these objects might optionally be associated with 
additional data.  Do you put the extension pointer inside the definition 
of 'HEADER'?  Could it go unused and waste space?  Do you put it inside 
'struct ref_countable_and_linked_list_trackable'?  Could it go unused 
and waste space?  Does it apply to all reference-countable object types? 
  Does it apply to all linked-list-trackable object types?  Does it 
apply to object types which are not reference-countable?  It's 
essentially a "multiple-inheritance" challenge, if I understand it 
correctly.

One strategy might be to have object type "operations:"

   typedef void f_deref(void *);
   typedef void f_unlink(void *);
   typedef void f_free_extension(void *);

   struct object_operations {
       f_deref * deref;
       f_unlink * unlink;
       f_free_extension * free_extension;
     };

then for a particular object type, you could have (at file scope):

   struct object_operations string_operations = {
       string_deref,
       0,
       0,
     };
   struct object_operations node_operations = {
       node_deref,
       node_unlink,
       0,
     };

etc.  Then your "header" might simply be like 'ops' below:

   struct foo {
       struct object_operations * ops;
       /* Other members */
     };

and every object would need to have this header initialized to point to 
the operations appropriate for its type.  This strategy can also 
eliminate the 'tag' requirement, since an object's supported operations 
define the use of the object.

   void deref(void * object) {
       /* ...Maybe check for null pointer... */
       /* ...Maybe yield debug messages... */
       /* ...Maybe adjust debugging counters... */
       ((struct object_operations *) object)->deref(object);
       return;
     }

However, this strategy trades the size of objects for the speed required 
to initialize the 'ops' member and to call the functions instead of 
making the simpler casts and offset computations for the inherited 
properties (like 'ref_count').

Also, there is still wasted space for any object types with unsupported 
operations, in such a type's 'xxx_operations' instance.  So if one had 
hundreds of operations, one might further wish to squeeze space and 
forfeit time by using a single "operations function" that returns the 
supported operations:

   enum object_operation_type {
       obj_op_deref,
       obj_op_unlink,
       obj_op_free_extension,
       obj_ops
     };

   union object_operations {
       f_deref * deref;
       f_unlink * unlink;
       f_free_extension * free_extension;
     };

   typedef union object_operations f_object_operations(
       enum object_operation_type
     );

Then your header might simply be like 'ops' below:

   struct foo {
       f_object_operations * ops;
       /* Other members */
     };

And each object type would have a handler:

   f_object_operations string_operations;
   union object_operations string_operations(
       enum object_operation_type type
     ) {
       union object_operations result;
       switch (type) {
           case obj_op_deref:
             result.deref = string_deref;
             return result;
         }
       /* Problem */
     }

And the general interface would call the specific one:

   void deref(void * object) {
       f_object_operations ** ops;
       /* ...Maybe check for null pointer... */
       /* ...Maybe yield debug messages... */
       /* ...Maybe adjust debugging counters... */
       ops = object;
       (*ops)(obj_op_deref).deref(object);
       return;
     }

Then perhaps a day comes when you'd like to be able to support 
additional operations at execution-time.  One could "hook" an object's 
"handler" with a new handler that optionally invokes the old handler, if 
needed.  That's pretty easy; just set the 'ops' member.

Then perhaps a day comes when your additional operations need some kind 
of context whose storage is not accomodated by the object being hooked. 
  One could have a "stack" of handlers and context, but then it seems to 
me that the minimal size for a meaningful "header" would be:

   struct header {
       f_object_operations * ops;
       void * context;
     };

where both of these header members could be hooked for any object, and 
where the 'context' member could point to context which itself includes 
the same header for the previous[ly hooked] context, etc.

What approach(es) to a "multiple inheritance" challenge do you other 
folks in comp.lang.c enjoy? :)

[toc] | [prev] | [next] | [standalone]


#5882 — Re: Multiple Inheritance (Was Re: Reference counting)

FromDr Nick <3-nospam@temporary-address.org.uk>
Date2011-06-12 07:22 +0100
SubjectRe: Multiple Inheritance (Was Re: Reference counting)
Message-ID<87hb7vsh51.fsf@temporary-address.org.uk>
In reply to#5838
Shao Miller <sha0.miller@gmail.com> writes:

> On 6/6/2011 10:07 PM, Gene wrote:
>> On Jun 5, 7:17 am, Angel<angel+n...@spamcop.net>  wrote:
>>> On 2011-06-05, daknok<radekslu...@gmail.com>  wrote:
>>>
>>>> ...
>>>> If I want to do simple reference counting for different structures I
>>>> would go like this:
>>>> ...
>>>> Though if I have about ten structs, I have ten different functions to
>>>> increase and decrease the reference count. Is it, in some way, possible
>>>> to just provide one function for increasing and one function for
>>>> decreasing the reference count which can be used for all structs with a
>>>> reference count?
>>>
>>> There are number of ways to do this. One of the easiest (but least
>>> flexible) is to start all your structures with the same reference
>>> variable, of the same type, like this:
>>>
>>> struct a
>>> {
>>>          int ref_count;
>>>          char *data;
>>>          char *more_data;
>>>
>>> };
>>>
>>> struct b
>>> {
>>>          int ref_count;
>>>          int number;
>>>          int another_number;
>>>
>>> };
>>>
>>> Now you can safely read the ref_count from any of these structures, for
>>> example like this:
>>>
>>> struct ref_count
>>> {
>>>          int ref_count;
>>>
>>> };
>>>
>>> void increase_refcount(void *data)
>>> {
>>>          ((struct refcount *) data)->refcount++;
>>>
>>> }
>>>
>>> You can safely pass either pointers to struct a or struct b to this
>>> function, and it will work as expected. The standard guarantees that
>>> shared fields at the beginning of structures are compatible. In a way,
>>> this is a primitive C implementation of inheritance.
>>
>> I asked about this here some time back.  The folks who know the
>> Standard well denied that this is portable.  The standard gives you
>> now way to rely on common prefixes of fields to be laid out the same
>> way in memory.  But you _can_ rely on casts between the first field
>> and an enclosing struct type to work correctly. So the fully portable
>> way is this:
>>
>
> Does anyone recall which thread this was asked about in?  I'm curious
> as to whether or not "the folks who know the Standard well" had
> offered concerns beyond alignment.

I asked about it as well when discussing a generic merge-sort that
relied on each structure starting with it's "struct this *next" pointer
(rather than ending as is traditional).  My sort function had a generic
struct of that sort that it cast all incoming structures to.

The consensus was not concerns about alignment - indeed, everybody felt
it would be almost impossible to find a system that it broke on - but
that it was *not* guaranteed by the standard.

IIRC (and I may well not do), if all of them went into a union somewhere
then it would have to work, and if you have multiple compilation units
nothing is going to know that there isn't such a union somewhere, but
nevertheless...
-- 
Online waterways route planner            | http://canalplan.eu
Plan trips, see photos, check facilities  | http://canalplan.org.uk

[toc] | [prev] | [next] | [standalone]


#5484

FromChina Blue Angels <chine.bleu@yahoo.com>
Date2011-06-05 05:07 -0700
Message-ID<chine.bleu-3AAAEF.05070405062011@news.eternal-september.org>
In reply to#5477
In article <4deb6008$0$28457$703f8584@textnews.kpn.nl>,
 daknok <radekslupik@gmail.com> wrote:

> Hi,
> 
> If I want to do simple reference counting for different structures I 
> would go like this:

You can use
    typedef struct RefCount RefCount;
    typedef void (*LocalRelease)(struct RefCount*);
    typedef struct RefCount {
        int count;
        LocalRelease localrelease;
    };
    #define initialise(pointer) initialise1((RefCount*)(pointer))
    #define retain(pointer) retain1((RefCount*)(pointer))
    #define release(pointer) release1((RefCount*)(pointer))
    static inline RefCount *initialise1(RefCount *r, LocalRelease localrelease) {
        r->count = 1; r->localrelease = localrelease;
    }
    static inline RefCount *retain1(RefCount *r) {
        if (r) r->count += 1; return r;
    }
    static inline RefCount *release1(RefCount *r) {
        if (r && r->count<=1) {
            if (r->localrelease) r->localrelease(r);
            free(r); return 0;
        }else {
            r->count -= 1; return r;
        }
    }

> struct String {
>     unsigned references;
>     char *cString;
>     size_t length;
> };
> 
> void StringRelease(struct String *str) {
>     str->references--;
>     if (str->references == 0) {
>         free(str->cString);
>         free(str);
>     }
> }

struct String {
    RefCount ref; char *cString; size_t length;
};
void StringRelease(struct String *r) {
    free(str->cString);
}
struct String *newstring(void) {
    struct String *str = malloc(sizeof(struct String));
    initialise(str, (LocalRelease)StringRelease);
    str->cString = 0; str->length = 0;
    return str;
}

retain(str);
release(str);

-- 
I remember finding out about you,  |              I survived XYZZY-Day.
Everyday my mind is all around you,|     I'm whoever you want me to be.
Looking out from my lonely room    |Annoying Usenet one post at a time.
Day after day.                     |  At least I can stay in character.

[toc] | [prev] | [next] | [standalone]


#5485

From"BartC" <bc@freeuk.com>
Date2011-06-05 13:14 +0100
Message-ID<isfs08$42s$1@dont-email.me>
In reply to#5477

"daknok" <radekslupik@gmail.com> wrote in message 
news:4deb6008$0$28457$703f8584@textnews.kpn.nl...
> Hi,
>
> If I want to do simple reference counting for different structures I would 
> go like this:
>
> struct String {
>    unsigned references;
>    char *cString;
>    size_t length;
> };
>
> void StringRelease(struct String *str) {
>    str->references--;
>    if (str->references == 0) {
>        free(str->cString);
>        free(str);
>    }
> }
>
> struct String *StringRetain(struct String *str) {
>    str->references++;
>    return str;
> }
>
> Though if I have about ten structs, I have ten different functions to 
> increase and decrease the reference count. Is it, in some way, possible to 
> just provide one function for increasing and one function for decreasing 
> the reference count which can be used for all structs with a reference 
> count?

How different are these structs? It looks like each struct needs other 
things doing to it apart from the reference count.

I might go for a single, more elaborate struct that does everything, with 
perhaps a tag in it saying what kind of struct it is. Then you need one set 
of functions, although they will be more complex (and might still delegate 
the work to multiple functions).

>    str->references--;
>    if (str->references == 0) {
>        free(str->cString);
>        free(str);

Could this be called when ->references is already zero? I might check for 
this.

-- 
Bartc
 

[toc] | [prev] | [next] | [standalone]


#5488

Fromdaknok <daknok@example.com>
Date2011-06-05 14:22 +0200
Message-ID<4deb74f0$0$28443$703f8584@textnews.kpn.nl>
In reply to#5485
On 2011-06-05 14:14:25 +0200, BartC said:

> "daknok" <radekslupik@gmail.com> wrote in message 
> news:4deb6008$0$28457$703f8584@textnews.kpn.nl...
>> Hi,
>> 
>> If I want to do simple reference counting for different structures I 
>> would go like this:
>> 
>> struct String {
>> unsigned references;
>> char *cString;
>> size_t length;
>> };
>> 
>> void StringRelease(struct String *str) {
>> str->references--;
>> if (str->references == 0) {
>> free(str->cString);
>> free(str);
>> }
>> }
>> 
>> struct String *StringRetain(struct String *str) {
>> str->references++;
>> return str;
>> }
>> 
>> Though if I have about ten structs, I have ten different functions to 
>> increase and decrease the reference count. Is it, in some way, possible 
>> to just provide one function for increasing and one function for 
>> decreasing the reference count which can be used for all structs with a 
>> reference count?
> 
> How different are these structs? It looks like each struct needs other 
> things doing to it apart from the reference count.

Well I have structs for strings, dates, files, data and URLs basically. 
They all use reference counting.

> 
> I might go for a single, more elaborate struct that does everything, 
> with perhaps a tag in it saying what kind of struct it is. Then you 
> need one set of functions, although they will be more complex (and 
> might still delegate the work to multiple functions).
> 
>> str->references--;
>> if (str->references == 0) {
>> free(str->cString);
>> free(str);
> 
> Could this be called when ->references is already zero? I might check for this.

This should indeed always be called when the number of references 
reaches zero, because in that case it isn't anymore in use.

[toc] | [prev] | [next] | [standalone]


#5492

From"BartC" <bc@freeuk.com>
Date2011-06-05 14:45 +0100
Message-ID<isg1ck$2r8$1@dont-email.me>
In reply to#5488
"daknok" <daknok@example.com> wrote in message
news:4deb74f0$0$28443$703f8584@textnews.kpn.nl...
> On 2011-06-05 14:14:25 +0200, BartC said:

>>> str->references--;
>>> if (str->references == 0) {
>>> free(str->cString);
>>> free(str);
>>
>> Could this be called when ->references is already zero? I might check for
>> this.
>
> This should indeed always be called when the number of references reaches
> zero, because in that case it isn't anymore in use.

I meant the str->references-- bit.

If StringRelease() is called on something that already has a reference count
of 0, then it might go wrong.

And because such a function is likely to be called from many places where
the caller does not know/care how many active references remain, then that
might be an issue.

-- 
bartc 

[toc] | [prev] | [next] | [standalone]


#5496

Fromdaknok <daknok@example.com>
Date2011-06-05 17:01 +0200
Message-ID<4deb9a33$0$28487$703f8584@textnews.kpn.nl>
In reply to#5492
On 2011-06-05 15:45:41 +0200, BartC said:

> "daknok" <daknok@example.com> wrote in message
> news:4deb74f0$0$28443$703f8584@textnews.kpn.nl...
>> On 2011-06-05 14:14:25 +0200, BartC said:
> 
>>>> str->references--;
>>>> if (str->references == 0) {
>>>> free(str->cString);
>>>> free(str);
>>> 
>>> Could this be called when ->references is already zero? I might check for
>>> this.
>> 
>> This should indeed always be called when the number of references reaches
>> zero, because in that case it isn't anymore in use.
> 
> I meant the str->references-- bit.
> 
> If StringRelease() is called on something that already has a reference count
> of 0, then it might go wrong.
> 
> And because such a function is likely to be called from many places where
> the caller does not know/care how many active references remain, then that
> might be an issue.

If the code is written well, this won't be a problem. Even better could 
I write a macro:

    SafeStringRelease(s) if (s != NULL) { StringRelease(s); } s = NULL

and use that.

[toc] | [prev] | [next] | [standalone]


#5529

FromEric Sosman <esosman@ieee-dot-org.invalid>
Date2011-06-05 18:06 -0400
Message-ID<isgum7$31l$1@dont-email.me>
In reply to#5496
On 6/5/2011 11:01 AM, daknok wrote:
> [...]
> If the code is written well, this won't be a problem. Even better could
> I write a macro:
>
> SafeStringRelease(s) if (s != NULL) { StringRelease(s); } s = NULL
>
> and use that.

     Danger, Will Robinson!

	if (x == 42)
	    SafeStringRelease(string);

Note carefully what happens when `x' is *not* forty-two.  (What
you need is known as "the `do { } while(0)' trick.")

     Then, too, there's the matter of side-effects:

	String *array[42];
	...
	int i = ...;
	// Release all Strings from the i'th onward:
	while (i < 42)
	    SafeStringRelease(array[i++]);

With SafeStringRelease as it stands you'll free only about half
of the strings; a corrected version would free only about a third
and leak another third.  Both versions would be likely to do
something weird on or just after the final trip through the loop.

     I'm not a big believer in the efficacy of the `s = NULL' part,
for the same reason I don't use a similar construct with free():
You can NULL out one particular pointer to a released thing, but
there's not much hope of finding and NULLing all of them.  For
example, what if `s' expands to the name of a function parameter?
You can NULL out the parameter -- the function's local variable --
but you can't get at the argument the caller provided.

-- 
Eric Sosman
esosman@ieee-dot-org.invalid

[toc] | [prev] | [next] | [standalone]


#5883

FromDr Nick <3-nospam@temporary-address.org.uk>
Date2011-06-12 07:25 +0100
Message-ID<87d3ijsgzz.fsf@temporary-address.org.uk>
In reply to#5496
daknok <daknok@example.com> writes:

> On 2011-06-05 15:45:41 +0200, BartC said:
>
>> I meant the str->references-- bit.
>>
>> If StringRelease() is called on something that already has a reference count
>> of 0, then it might go wrong.
>>
>> And because such a function is likely to be called from many places where
>> the caller does not know/care how many active references remain, then that
>> might be an issue.
>
> If the code is written well, this won't be a problem. Even better
> could I write a macro:
>
>    SafeStringRelease(s) if (s != NULL) { StringRelease(s); } s = NULL
>
> and use that.

I'd throw as assert in myself (or a custom error routine - cue standard
discussion about whether assert is wonderful or evil).  This is the sort
of thing that should never happen, so rather than ignoring it silently
(passing by the macro issues) it indicates a programming error elsewhere
in your code so I'd want to fail as noisily as possible - certainly when
developing and testing.
-- 
Online waterways route planner            | http://canalplan.eu
Plan trips, see photos, check facilities  | http://canalplan.org.uk

[toc] | [prev] | [next] | [standalone]


#5491

Fromdaknok <daknok@example.com>
Date2011-06-05 15:29 +0200
Message-ID<4deb84c3$0$28443$703f8584@textnews.kpn.nl>
In reply to#5477
Of course this will only be for strings. I need a deallocator for each 
struct, though I could do this with a type field:

typedef enum {
  ReferenceCountTypeString,
  ReferenceCountTypeDate,
  ReferenceCountTypeData,
  ReferenceCountTypeURL,
} ReferenceCountType;

struct ReferenceCount {
  unsigned references;
  ReferenceCountType type;
};

struct String {
  struct ReferenceCount refCount;
  char *cString;
  size_t length;
};

[toc] | [prev] | [next] | [standalone]


#5500

FromShao Miller <sha0.miller@gmail.com>
Date2011-06-05 12:17 -0500
Message-ID<isga6c$s6f$1@dont-email.me>
In reply to#5477
On 6/5/2011 5:52 AM, daknok wrote:
> Hi,
>
> If I want to do simple reference counting for different structures I
> would go like this:
>
> struct String {
>    unsigned references;
>    char *cString;
>    size_t length;
> };
>
> void StringRelease(struct String *str) {
>    str->references--;
>    if (str->references == 0) {
>        free(str->cString);
>        free(str);
>    }
> }
>
> struct String *StringRetain(struct String *str) {
>    str->references++;
>    return str;
> }
>
> Though if I have about ten structs, I have ten different functions to
> increase and decrease the reference count.

Your 'struct String' contains a 'cString' pointer, which implies that 
someone has to set that member somehow.  If you offer an allocator which 
allocates both a 'struct String' as well as the data that 'cString' will 
point to, a reference-counting de-allocator that has knowledge of the 
resource pointed-to by 'cString' seems nicely symmetrical.

Does one 'struct String' "own" the string that its 'cString' member 
points to?  Or are users allowed to modify the 'cString' member 
themselves and point to, let's say, a string literal?  You wouldn't want 
them to free a string literal, most likely. :)

If the string is "owned" by the associated 'struct String', then of 
course, a nice thing about having an array of some element type is that 
you can allocate 'struct String' and the 'char[]' together.

   typedef struct String_ String;
   struct string_ {
       unsigned int references;
       size_t current_length;
       size_t maximum_length;
       char * cString;
       char data_[1];
     };

Now you can have an allocator that does something like:

   String * new_string(size_t maximum_length) {
       String * result;
       result = malloc(sizeof *result + maximum_length);
       if (!result)
         return result;  /* pass the null pointer value on */
       init_string(result, maximum_length, result->data_);
       return result;
     }

where 'init_string' is something like:

   void init_string(String * string, size_t maximum_length, char * cString);

and sets the relevant members (and 'references' to 1, other stuff, 
perhaps).  Now when your reference-counting de-allocator is ready to 
free the 'struct String', its call to 'free' will include deallocating 
the trailing 'char[]' that was allocated by the above call to 'malloc'. 
  This way, the de-allocator doesn't need to free 2 ranges of memory.

> Is it, in some way, possible
> to just provide one function for increasing and one function for
> decreasing the reference count which can be used for all structs with a
> reference count?
>

I think that depends.  If your structs contain references to other 
objects (which might contain references to other objects, etc.), it 
seems that the knowledge for "collapsing" has to go somewhere.  If the 
struct "owns" all of the resources associated with it, you could:
- Explicitly 'free' each resource when the struct is being de-allocated. 
  (Knowledge in the struct-specific function.)
- Track all resources with a linked list and walk the list, freeing 
items, when the struct is being de-allocated.  (Knowledge in the 
resource list.)

If a struct doesn't "own" all of the resources associated with it, then 
perhaps you extend your reference-counting approach to such resources, 
also.  But still, the knowledge for what might be referenced by your 
struct needs to go somewhere.  Perhaps you have a struct-specific, 
reference-counting de-allocator which decrements the references for all 
of the resources it is referencing.  This is a nicely-collapsible chain 
of events.

As already suggested by others, if your structures all begin with the 
same type of member, you can have a single reference-counting release 
function that takes a pointer to it.  While this means not having to use 
'StringRelease', 'FileRelease', 'UrlRelease', etc. all over the place, 
the knowledge of any "sub-resources" still needs to be somewhere; 
possibly in a struct-specific function which can be found via a function 
pointer.

[toc] | [prev] | [next] | [standalone]


#5504

Fromcri@tiac.net (Richard Harter)
Date2011-06-05 17:11 +0000
Message-ID<4debb114.751423946@text.giganews.com>
In reply to#5477
On Sun, 5 Jun 2011 12:52:56 +0200, daknok <radekslupik@gmail.com>
wrote:

>Hi,
>
>If I want to do simple reference counting for different structures I 
>would go like this:
>
>struct String {
>    unsigned references;
>    char *cString;
>    size_t length;
>};
>
>void StringRelease(struct String *str) {
>    str->references--;
>    if (str->references == 0) {
>        free(str->cString);
>        free(str);
>    }
>}
>
>struct String *StringRetain(struct String *str) {
>    str->references++;
>    return str;
>}
>
>Though if I have about ten structs, I have ten different functions to 
>increase and decrease the reference count. Is it, in some way, possible 
>to just provide one function for increasing and one function for 
>decreasing the reference count which can be used for all structs with a 
>reference count?

There are many ways to skin this particular cat.  A simple way is to
pass in the addresses of the components.  In the case of retain you
have one argument, the address of the reference counter.  Thus you
call Retain thusly:

    Retain(&(str->references));

By the by, you don't need to return the pointer to str in the Retain
functions.

The Release functions are a potential problem because different things
might require different numbers of calls to free.  However it looks
like they would each have two - the data array and the struct itself.
Here I will commend to you a little trick.  In your struct you have a
little struct that looks like this:

    struct releasables {
        void * first;
        void * second;
    };

When you init the struct you set first to the payload and second to
the struct itself.  Thus the Release code looks like this.

    Release(&(str->references),str->releasables);

The Release code then looks something like this:

    void Release(unsigned *references, struct releasables releasables)
{
        (*references)--;
        if (*references == 0) {
            free(releasables->first);
            free(releasable->second);
        }
    }

Incidentally I don't think much of making your Release functions void.
You should return something that indicates whether the struct still
exists or whether it has been freed.  Checking the validity of
pointers has a way of preventing unpleasant surprises.

I am sure that you can come up with something slicker and less
cumbersome that the above, which is an off the top of my head sort of
thing.  The important thing is this:  If you can make all of the
release/retain functions somehow smell the same then you can handle
them all the same.


[toc] | [prev] | [next] | [standalone]


#5800

FromImpalerCore <jadill33@gmail.com>
Date2011-06-10 11:30 -0700
Message-ID<e9ef06c1-e30d-4953-8f15-d72b2bdde0eb@k17g2000vbn.googlegroups.com>
In reply to#5477
On Jun 5, 6:52 am, daknok <radekslu...@gmail.com> wrote:
> Hi,
>
> If I want to do simple reference counting for different structures I
> would go like this:
>
> struct String {
>     unsigned references;
>     char *cString;
>     size_t length;
>
> };
>
> void StringRelease(struct String *str) {
>     str->references--;
>     if (str->references == 0) {
>         free(str->cString);
>         free(str);
>     }
>
> }
>
> struct String *StringRetain(struct String *str) {
>     str->references++;
>     return str;
>
> }
>
> Though if I have about ten structs, I have ten different functions to
> increase and decrease the reference count. Is it, in some way, possible
> to just provide one function for increasing and one function for
> decreasing the reference count which can be used for all structs with a
> reference count?

One option is to abstract the reference count out of the structure and
piggyback it onto a raw allocated pointer.  The same trick used to
make debugging allocators could apply to a reference counted pointer.
I've never done it before, but it's something to ponder.  Here's my
first pass.

\code snippet
#define PTR_HEADER_SIZE (sizeof (int))

void* rc_malloc( size_t size )
{
  void* mem = NULL;
  void* p = NULL;

  p = malloc( size + PTR_HEADER_SIZE );

  if ( p )
  {
    /* Set the reference count to 1. */
    *((int*)p) = 1;

    mem = (unsigned char*)p + PTR_HEADER_SIZE;
  }

  return mem;
}

void* rc_copy( void* p )
{
  void* actual_p = NULL;

  if ( p )
  {
    actual_p = (unsigned char*)p - PTR_HEADER_SIZE;

    /* Increment the reference count. */
    *((int*)actual_p) += 1;
  }

  return p;
}

void rc_release( void* p )
{
  void* actual_p = NULL;

  if ( p )
  {
    actual_p = (unsigned char*)p - PTR_HEADER_SIZE;

    /* Decrement the reference count. */
    *((int*)actual_p) -= 1;

    /* If reference count down to zero, release the memory. */
    if ( *((int*)actual_p) == 0 ) {
      free( actual_p );
    }
  }
}
\endcode

You prefix every allocation's pointer with an integer reference
count.  On access, it dereferences just like a regular pointer to the
object.  With a slight change in function interface, you should be
able to use the refcount interface to interact with a reference
counted pointer.  Just don't mix refcount pointers with malloc and
friends.

Not tested, don't know how kosher or brittle the technique is, and I
have no practical experience with reference counting so YMMV.

Best regards,
John D.

[toc] | [prev] | [next] | [standalone]


#5802

FromShao Miller <sha0.miller@gmail.com>
Date2011-06-10 16:04 -0400
Message-ID<istt6p$d8u$1@dont-email.me>
In reply to#5800
On 6/10/2011 14:30, ImpalerCore wrote:
> One option is to abstract the reference count out of the structure and
> piggyback it onto a raw allocated pointer.  The same trick used to
> make debugging allocators could apply to a reference counted pointer.
> I've never done it before, but it's something to ponder.  Here's my
> first pass.
>
> \code snippet
> #define PTR_HEADER_SIZE (sizeof (int))
>
> void* rc_malloc( size_t size )
> {
>    void* mem = NULL;
>    void* p = NULL;
>
>    p = malloc( size + PTR_HEADER_SIZE );
>
>    if ( p )
>    {
>      /* Set the reference count to 1. */
>      *((int*)p) = 1;
>
>      mem = (unsigned char*)p + PTR_HEADER_SIZE;
>    }
>
>    return mem;
> }

'mem' isn't necessarily suitably aligned for any object; a promise that 
the Standard makes of 'malloc'.  Since the 'sizeof (int)' must be an 
integer multiple of the alignment requirement of 'int', you can put the 
'int' at the _end_ of the allocated memory and compute where it needs to 
go so that it doesn't overlap the memory before it and is suitably aligned.

Maybe something like (disclaimer: quickly coded):

   #include <stddef.h>
   #include <stdlib.h>
   #include <stdio.h>

   typedef int footer_t;

   size_t footer_at(size_t size) {
       size_t x = size;
       x += sizeof (footer_t);
       /* Check for wrap-around */
       if (x < size)
         return 0;
       return (x - 1) / sizeof (footer_t);
     }

   size_t size_with_footer(size_t size) {
       size_t x = footer_at(size);
       if (!x)
         return 0;
       x = (x + 1) * sizeof (footer_t);
       /* Check for wrap-around */
       if (x < size)
         return 0;
       return x;
     }

   footer_t * get_footer(void * mem, size_t size) {
       size_t footer_pos = footer_at(size);
       if (!mem || !footer_pos)
         return NULL;
       return (footer_t *) mem + footer_pos;
     }

   void * malloc_with_footer(size_t size) {
       void * mem;
       footer_t * footer;
       mem = malloc(size_with_footer(size));
       if (!mem)
         return mem;
       footer = get_footer(mem, size);
       if (!footer)
         return footer;
       /* Initialize footer */
       /* ... */
       return mem;
     }

   int main(void) {
       size_t sizes[] = {0, 2, 6, 8, 12, 15};
       enum cv {tests = sizeof sizes / sizeof *sizes};
       int i;

       for (i = 0; i < tests; ++i) {
           printf("size: [%d] ", (int)sizes[i]);
           printf(
               "footer_at: [%d] ",
               (int)footer_at(sizes[i]) * sizeof (footer_t)
             );
           printf(
               "size_with_footer: [%d] ",
               (int)size_with_footer(sizes[i])
             );
           puts("");
         }
       return 0;
     }

But then whenever you want to work with the footer, you'd have to use 
'get_footer', instead of a simple cast.

[toc] | [prev] | [next] | [standalone]


#5812

FromJames Kuyper <jameskuyper@verizon.net>
Date2011-06-10 22:56 -0400
Message-ID<isulh0$ipq$1@dont-email.me>
In reply to#5800
On 06/10/2011 02:30 PM, ImpalerCore wrote:
...
> One option is to abstract the reference count out of the structure and
> piggyback it onto a raw allocated pointer.  The same trick used to
> make debugging allocators could apply to a reference counted pointer.
> I've never done it before, but it's something to ponder.  Here's my
> first pass.
> 
> \code snippet
> #define PTR_HEADER_SIZE (sizeof (int))
> 
> void* rc_malloc( size_t size )
> {
>   void* mem = NULL;
>   void* p = NULL;
> 
>   p = malloc( size + PTR_HEADER_SIZE );
> 
>   if ( p )
>   {
>     /* Set the reference count to 1. */
>     *((int*)p) = 1;
> 
>     mem = (unsigned char*)p + PTR_HEADER_SIZE;
>   }
> 
>   return mem;
> }

The value stored in 'p' is guaranteed to be correctly aligned for all
types. However, the only thing portably guaranteed about alignment off
the value stored in 'mem' is that it is suitable for 'int', it need not
be suitably aligned for any type with a size greater than 1 that is
different from that of 'int'.

The draft of the next version of the C standard includes new
alignment-related features that will help with this kind of thing. The
C1X version of your code should probably use alignof(max_align_t), where
max_align_t is declared in <stddef.h>.
-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#5848

FromImpalerCore <jadill33@gmail.com>
Date2011-06-11 12:36 -0700
Message-ID<52c902de-0f66-4bb0-b787-8c440c2405db@hg8g2000vbb.googlegroups.com>
In reply to#5812
On Jun 10, 10:56 pm, James Kuyper <jameskuy...@verizon.net> wrote:
> On 06/10/2011 02:30 PM, ImpalerCore wrote:
> ...
>
>
>
> > One option is to abstract the reference count out of the structure and
> > piggyback it onto a raw allocated pointer.  The same trick used to
> > make debugging allocators could apply to a reference counted pointer.
> > I've never done it before, but it's something to ponder.  Here's my
> > first pass.
>
> > \code snippet
> > #define PTR_HEADER_SIZE (sizeof (int))
>
> > void* rc_malloc( size_t size )
> > {
> >   void* mem = NULL;
> >   void* p = NULL;
>
> >   p = malloc( size + PTR_HEADER_SIZE );
>
> >   if ( p )
> >   {
> >     /* Set the reference count to 1. */
> >     *((int*)p) = 1;
>
> >     mem = (unsigned char*)p + PTR_HEADER_SIZE;
> >   }
>
> >   return mem;
> > }
>
> The value stored in 'p' is guaranteed to be correctly aligned for all
> types. However, the only thing portably guaranteed about alignment off
> the value stored in 'mem' is that it is suitable for 'int', it need not
> be suitably aligned for any type with a size greater than 1 that is
> different from that of 'int'.
>
> The draft of the next version of the C standard includes new
> alignment-related features that will help with this kind of thing. The
> C1X version of your code should probably use alignof(max_align_t), where
> max_align_t is declared in <stddef.h>.

Granted that kind of C1X feature would be superior.  I suppose one
must weigh the utility of the concept against its portability risk.

In the absence of C1X features, I suppose that one could still manage
to make it work by discovering the value corresponding to the concept
of 'alignof(max_align_t)', and configure it for each environment
manually a la '#define ALIGN_MAX N'.  Unfortunately I do not know how
to manually find a platform's ALIGN_MAX.  I've seen some incantations
with unions and offsetof, and autoconf has their AC_CHECK_ALIGNOF, but
I don't know how to use it.

\code snippet
void* rc_malloc( size_t size )
{
  void* mem = NULL;
  void* p = NULL;

  p = malloc( size + ALIGN_MAX );

  if ( p )
  {
    /* Set the reference count to 1. */
    *((int*)p) = 1;

    mem = (unsigned char*)p + ALIGN_MAX;
  }

  return mem;
}
\endcode

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.

Best regards,
John D.

[toc] | [prev] | [next] | [standalone]


#5860

FromShao Miller <sha0.miller@gmail.com>
Date2011-06-11 17:23 -0500
Message-ID<it0mco$bl7$1@dont-email.me>
In reply to#5848
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*

[toc] | [prev] | [next] | [standalone]


Page 1 of 4  [1] 2 3 4  Next page →

Back to top | Article view | comp.lang.c


csiph-web