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


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

Why is glibc not extensive?

Started byAmit <amitchoudhary0523@gmail.com>
First post2022-11-16 22:31 -0800
Last post2022-11-23 13:55 -0600
Articles 8 on this page of 28 — 12 participants

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


Contents

  Why is glibc not extensive? Amit <amitchoudhary0523@gmail.com> - 2022-11-16 22:31 -0800
    Re: Why is glibc not extensive? Bart <bc@freeuk.com> - 2022-11-17 13:05 +0000
      Re: Why is glibc not extensive? A <amit234234234234@gmail.com> - 2022-11-17 05:18 -0800
        Re: Why is glibc not extensive? A <amit234234234234@gmail.com> - 2022-11-17 05:24 -0800
        Re: Why is glibc not extensive? Bart <bc@freeuk.com> - 2022-11-17 13:57 +0000
        Re: Why is glibc not extensive? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2022-11-17 17:04 +0000
        Re: Why is glibc not extensive? David Brown <david.brown@hesbynett.no> - 2022-11-18 09:32 +0100
          Re: Why is glibc not extensive? A <amit234234234234@gmail.com> - 2022-11-18 02:32 -0800
            Re: Why is glibc not extensive? David Brown <david.brown@hesbynett.no> - 2022-11-18 13:09 +0100
              Re: Why is glibc not extensive? A <amit234234234234@gmail.com> - 2022-11-18 04:47 -0800
                Re: Why is glibc not extensive? David Brown <david.brown@hesbynett.no> - 2022-11-18 13:59 +0100
                  Re: Why is glibc not extensive? A <amit234234234234@gmail.com> - 2022-11-18 05:27 -0800
                Re: Why is glibc not extensive? Bart <bc@freeuk.com> - 2022-11-18 17:04 +0000
                  Re: Why is glibc not extensive? David Brown <david.brown@hesbynett.no> - 2022-11-21 08:50 +0100
                    Bart (Was: Why is glibc not extensive?) gazelle@shell.xmission.com (Kenny McCormack) - 2022-11-21 14:14 +0000
                Re: Why is glibc not extensive? Michael S <already5chosen@yahoo.com> - 2022-11-21 08:10 -0800
                  Re: Why is glibc not extensive? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2022-11-26 09:07 -0800
                    Re: Why is glibc not extensive? Michael S <already5chosen@yahoo.com> - 2022-11-26 16:11 -0800
                      Re: Why is glibc not extensive? Kaz Kylheku <864-117-4973@kylheku.com> - 2022-11-27 13:05 +0000
                        Re: Why is glibc not extensive? scott@slp53.sl.home (Scott Lurndal) - 2022-11-27 16:30 +0000
                        Re: Why is glibc not extensive? BGB <cr88192@gmail.com> - 2022-11-27 12:20 -0600
                          Re: Why is glibc not extensive? Bart <bc@freeuk.com> - 2022-11-27 21:13 +0000
                            Re: Why is glibc not extensive? BGB <cr88192@gmail.com> - 2022-11-27 21:53 -0600
                      Re: Why is glibc not extensive? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2022-12-03 01:17 -0800
          Re: Why is glibc not extensive? BGB <cr88192@gmail.com> - 2022-11-23 15:11 -0600
    Re: Why is glibc not extensive? Bonita Montero <Bonita.Montero@gmail.com> - 2022-11-17 19:05 +0100
      Re: Why is glibc not extensive? gazelle@shell.xmission.com (Kenny McCormack) - 2022-11-18 08:09 +0000
        Re: Why is glibc not extensive? BGB <cr88192@gmail.com> - 2022-11-23 13:55 -0600

Page 2 of 2 — ← Prev page 1 [2]


#168365

FromBGB <cr88192@gmail.com>
Date2022-11-27 12:20 -0600
Message-ID<tm09ps$1ng2n$1@dont-email.me>
In reply to#168361
On 11/27/2022 7:05 AM, Kaz Kylheku wrote:
> On 2022-11-27, Michael S <already5chosen@yahoo.com> wrote:
>> If current rate of Moore Law is not improved then even with
>> all conservatism of standard bodies it will happen several
>> decades before the first individual object reaches 2**63-1.
> 
> Currently, people are using the top bits of 64 bit pointers
> for funny things:
> 
> - Android implements pointer-tagging. The upper 16 bits of a pointer
> are a tag, which can be used to validate it.  E.g. if you malloc
> some space, free it and malloc again such that the same space
> is returned, it will have a different tag. The hardware strips
> away the tag; only the lower 48 bits (at most) is significant.
> 
> - A collection of techiques called NaN boxing can store a 50 bit
> pointer, fully unboxed 64 bit double, or a 50 bit integer, in a 64 bit
> word. This is a boon for dynamic languages, which can have unboxed
> floats.
> 

In my case, I am doing something similar with a custom ISA of mine...
The top 16 bits of the 64-bit pointers are mostly ignored by Load/Store 
ops, and often used as a dynamic type tag or similar.

The type-tag seemed more valuable in a near term sense than "virtual 
address space limit that likely wont be a big limiting factor for 
decades or more". Can note (on Windows) that after nearly 2 decades of 
having x86-64, we still have not (entirely) dispelled the use of 32-bit 
programs.

And, only a minority of programs on a PC "actually need" much more than 
a few GB (excluding things like FireFox wanting to eat all the RAM in a 
PC or similar).



I didn't use NaN boxing (in my dynamic and hybrid languages), while it 
makes sense for floating point numbers, it "kinda sucks" for pretty much 
everything else. It seemed a lot more sane to shift floating point 
numbers right by 2 bits, and then have a lot more tag space for 
everything else (say, then one can also have a 62-bit integer type in 
this range).

IMO, having a bigger integer type seemed to make more sense.

As can be noted, my mainly used languages on this are mostly static and 
hybrid languages (where in a hybrid language, many values may be kept in 
a tagged form, and dynamic typing is optional; but otherwise the 
language mostly behaves like a statically typed language).


So, top 4 bits, organized by hex:
   0=Pointer (59:48=Object Tag, 0=None)
   1=Small Spaces
   2=Bounds-Checked Pointer (Older Style)
   3=Bounds-Checked Pointer (Newer Style)
   4..7=Fixnum (62-bit integer)
   8..B=Flonum (62-bit floating point)
   C=Base-Offset Array (Older Style)
   D=Packed Vector (2 or 3 element)
   E=Type Tagged Pointer (Encodes a more C style pointer type)
   F=Raw pointer with 60-bit address.


Tag 2: Naively used a 12-bit bound, so only deals with small arrays and 
doesn't allow base-offsetting them (Tag C allowed base-offsetting, but 
required accessing memory to determine the array size).

Tag 3 can address both cases at the same time.


Tag 3:
   (59:56)=Base Offset Bias
   (55:51)=Exponent
   (50:48)=Size Fraction
Array size is interpreted as an 8-bit E5.F3 microfloat, with a base 
offset encoded using the same exponent (but not normalized).

The low 48 bits point to an address somewhere within the body of the array.

This format currently has some dedicated ISA level support.

It is not super exact, so is interpreted in one of two ways:
   Lax: Allow access unless it is "clearly out of bounds";
   Strict: Only allow access known in bounds.

So, say:
   RelIndex=(Index>>Exponent)+OffsetBias
   Lax: allows -1<=RelIndex<=Size
   Strict allows: 0<=RelIndex<Size

Address adjustment uses the adjustment index (shifted right) along with 
the carry out of the low-order bits, to figure out how to adjust the 
base offset bias.

If used as a for bounds-checked pointers in C, the lax version is used.
If used for a high-level array type, the strict version is used (will 
fall back to additional runtime checks, treating the bounds-checked 
version as a "fast path" version).


This version allows array bounds checking with only minimal performance 
overhead relative to bare pointers.

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


#168367

FromBart <bc@freeuk.com>
Date2022-11-27 21:13 +0000
Message-ID<tm0jt0$18kt$1@gioia.aioe.org>
In reply to#168365
On 27/11/2022 18:20, BGB wrote:
> On 11/27/2022 7:05 AM, Kaz Kylheku wrote:
>> On 2022-11-27, Michael S <already5chosen@yahoo.com> wrote:
>>> If current rate of Moore Law is not improved then even with
>>> all conservatism of standard bodies it will happen several
>>> decades before the first individual object reaches 2**63-1.
>>
>> Currently, people are using the top bits of 64 bit pointers
>> for funny things:
>>
>> - Android implements pointer-tagging. The upper 16 bits of a pointer
>> are a tag, which can be used to validate it.  E.g. if you malloc
>> some space, free it and malloc again such that the same space
>> is returned, it will have a different tag. The hardware strips
>> away the tag; only the lower 48 bits (at most) is significant.
>>
>> - A collection of techiques called NaN boxing can store a 50 bit
>> pointer, fully unboxed 64 bit double, or a 50 bit integer, in a 64 bit
>> word. This is a boon for dynamic languages, which can have unboxed
>> floats.
>>
> 
> In my case, I am doing something similar with a custom ISA of mine...
> The top 16 bits of the 64-bit pointers are mostly ignored by Load/Store 
> ops, and often used as a dynamic type tag or similar.
> 
> The type-tag seemed more valuable in a near term sense than "virtual 
> address space limit that likely wont be a big limiting factor for 
> decades or more". Can note (on Windows) that after nearly 2 decades of 
> having x86-64, we still have not (entirely) dispelled the use of 32-bit 
> programs.
> 
> And, only a minority of programs on a PC "actually need" much more than 
> a few GB (excluding things like FireFox wanting to eat all the RAM in a 
> PC or similar).
> 
> 
> 
> I didn't use NaN boxing (in my dynamic and hybrid languages), while it 
> makes sense for floating point numbers, it "kinda sucks" for pretty much 
> everything else. It seemed a lot more sane to shift floating point 
> numbers right by 2 bits, and then have a lot more tag space for 
> everything else (say, then one can also have a 62-bit integer type in 
> this range).
> 
> IMO, having a bigger integer type seemed to make more sense.
> 
> As can be noted, my mainly used languages on this are mostly static and 
> hybrid languages (where in a hybrid language, many values may be kept in 
> a tagged form, and dynamic typing is optional; but otherwise the 
> language mostly behaves like a statically typed language).

I've never used any of these methods. Neither 'Nan' Boxing, nor using 
spare bits at either end of a pointer or integer. They always seemed 
incredibly fiddly. Also the data types are compromised, like not having 
a full 64-bit integer for example.

And, in cases where a compiler can statically determine a type, it could 
generate code to directly operate on the integer, float or pointer 
without bitshifting.

The cost however is using two machine words instead of one, but this 
seemed acceptable for dynamic code which is going to be slow anyway. (My 
dynamic language also has homogeneous arrays where each element is a 
plain i64 or f64 (or u16 etc), so the same overheads as any static 
language.)

64-bit pointers are also wasteful since it is rare that I'd use more 
than 2GB or even 4GB in my programs. But I've experimented with using 
32-bit pointers within a 64-bit environment, and it was too much 
trouble. I'm not exactly short of memory; I'm more in needs of ways to 
fill it up!

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


#168373

FromBGB <cr88192@gmail.com>
Date2022-11-27 21:53 -0600
Message-ID<tm1bbc$1td3t$1@dont-email.me>
In reply to#168367
On 11/27/2022 3:13 PM, Bart wrote:
> On 27/11/2022 18:20, BGB wrote:
>> On 11/27/2022 7:05 AM, Kaz Kylheku wrote:
>>> On 2022-11-27, Michael S <already5chosen@yahoo.com> wrote:
>>>> If current rate of Moore Law is not improved then even with
>>>> all conservatism of standard bodies it will happen several
>>>> decades before the first individual object reaches 2**63-1.
>>>
>>> Currently, people are using the top bits of 64 bit pointers
>>> for funny things:
>>>
>>> - Android implements pointer-tagging. The upper 16 bits of a pointer
>>> are a tag, which can be used to validate it.  E.g. if you malloc
>>> some space, free it and malloc again such that the same space
>>> is returned, it will have a different tag. The hardware strips
>>> away the tag; only the lower 48 bits (at most) is significant.
>>>
>>> - A collection of techiques called NaN boxing can store a 50 bit
>>> pointer, fully unboxed 64 bit double, or a 50 bit integer, in a 64 bit
>>> word. This is a boon for dynamic languages, which can have unboxed
>>> floats.
>>>
>>
>> In my case, I am doing something similar with a custom ISA of mine...
>> The top 16 bits of the 64-bit pointers are mostly ignored by 
>> Load/Store ops, and often used as a dynamic type tag or similar.
>>
>> The type-tag seemed more valuable in a near term sense than "virtual 
>> address space limit that likely wont be a big limiting factor for 
>> decades or more". Can note (on Windows) that after nearly 2 decades of 
>> having x86-64, we still have not (entirely) dispelled the use of 
>> 32-bit programs.
>>
>> And, only a minority of programs on a PC "actually need" much more 
>> than a few GB (excluding things like FireFox wanting to eat all the 
>> RAM in a PC or similar).
>>
>>
>>
>> I didn't use NaN boxing (in my dynamic and hybrid languages), while it 
>> makes sense for floating point numbers, it "kinda sucks" for pretty 
>> much everything else. It seemed a lot more sane to shift floating 
>> point numbers right by 2 bits, and then have a lot more tag space for 
>> everything else (say, then one can also have a 62-bit integer type in 
>> this range).
>>
>> IMO, having a bigger integer type seemed to make more sense.
>>
>> As can be noted, my mainly used languages on this are mostly static 
>> and hybrid languages (where in a hybrid language, many values may be 
>> kept in a tagged form, and dynamic typing is optional; but otherwise 
>> the language mostly behaves like a statically typed language).
> 
> I've never used any of these methods. Neither 'Nan' Boxing, nor using 
> spare bits at either end of a pointer or integer. They always seemed 
> incredibly fiddly. Also the data types are compromised, like not having 
> a full 64-bit integer for example.
> 

If the type is declared, one can have the full width.
If tagged as a variant type, then one only gets 62 bits...


Another option could have been to use 80 or 96 bit tagged-refs, but this 
would be a worse option than being limited to a 62 bit fixnum.


OTOH, the error added for cutting the low 2 bits off of double for 
flonum is unlikely to be particularly noticeable in practice.


For the most part though, MSB tagging was "the lesser of two evils" in 
this case, mostly as LSB tagging would interfere with pointer alignment.


Function and branch pointers do also use LSB tagging though, mostly to 
separate between ignoring the high order bits, or treating them as 
containing the operating mode (such as a way to jump between having the 
CPU run the BJX2 ISA, or run RISC-V RV64IM).

Though, RV64IM code would not be entirely data-compatible with code 
built to use tagged-pointers and bounds checking (neither the RISC-V ISA 
nor ABI design having any concept of tagged pointers or tagged values).


The basic design for the tagged pointer system was originally mostly 
carried over from my "BGBScript2 VM" project, which was using a similar 
system on x86-64. Though, a bit more work is needed on x86-64 as the ISA 
design does not help out with any of this (pretty much everything needs 
to be done manually using shifts and bit manipulation).


> And, in cases where a compiler can statically determine a type, it could 
> generate code to directly operate on the integer, float or pointer 
> without bitshifting.
> 

In these cases, native representations may be used when types are 
statically known.

For my custom ISA though, the tagged pointers *are* the native pointer 
format, though most C pointers are either tag 0 or 3 in this case.

For things like flonums, the "shift right by 2 bits and set the tag" is 
handled as a dedicated CPU instruction.


> The cost however is using two machine words instead of one, but this 
> seemed acceptable for dynamic code which is going to be slow anyway. (My 
> dynamic language also has homogeneous arrays where each element is a 
> plain i64 or f64 (or u16 etc), so the same overheads as any static 
> language.)
> 
> 64-bit pointers are also wasteful since it is rare that I'd use more 
> than 2GB or even 4GB in my programs. But I've experimented with using 
> 32-bit pointers within a 64-bit environment, and it was too much 
> trouble. I'm not exactly short of memory; I'm more in needs of ways to 
> fill it up!

As I see it, a 48-bit virtual address space works well enough for now.


As is, on my ISA, I can run Doom with bounds-checking and tagged 
pointers with no real noticeable drop in frame-rate compared with a 
"plain" version (with no type tags).

Though, on a 50MHz CPU, this does leave Doom mostly in 16..24 fps territory.


Even for more extreme cases (such as running a prime factorization 
algorithm entirely using dynamically typed values), it was (at the time) 
around a 3x slowdown vs a static-typed version (written in C).

Though, much of the overhead here is because for dynamically typed code, 
pretty much every operator needs to be a runtime call (if the type is 
known, the calls can be skipped, and the use of type-tagged values isn't 
a big issue either way).


Though, in premise, if someone wanted, they could try writing something 
Doom-like in a language resembling JavaScript and then try to run it on 
this...

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


#168460

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2022-12-03 01:17 -0800
Message-ID<86fsdw6e2k.fsf@linuxsc.com>
In reply to#168358
Michael S <already5chosen@yahoo.com> writes:

> On Saturday, November 26, 2022 at 7:08:15 PM UTC+2, Tim Rentsch wrote:
>
>> Michael S <already...@yahoo.com> writes:
>>
>>> On Friday, November 18, 2022 at 2:47:42 PM UTC+2, A wrote:
>>>
>>>> On Friday, 18 November 2022 at 17:39:58 UTC+5:30, David Brown wrote:
>>
>> [...]
>>
>>>>> a) Use size_t like the rest of the world.
>>>>
>>>> This is a problem.  If I am not convinced then why should I follow
>>>> the world?  The world can use size_t but I will use long and if the
>>>> world says that I should be using size_t then I will ignore that.
>>>
>>> So, you don't want to use size_t because it is unsigned.  Well.
>>> Then use signed type ptrdiff_t.  When you want to hold size of
>>> arbitrary objects ptrdiff_t is more portable than 'long'.
>>> In corner case of size of object that occupies more than half
>>> of address space both ptrdiff_t and 'long' are not good enough,
>>> but at least ptrdiff_t works in all other cases.  The same can't
>>> be said about 'long' which does not work in pretty common case
>>> of size of big objects (>= 2GB) on Win64.
>>
>> IMO it's a mistake to hard-wire either 'long' or 'ptrdiff_t' to
>> be the name of a (signed) size type.  Whatever type is chosen
>> should allow as wide a range of values as needed, and neither of
>> those types will necessarily do that.  Furthermore the type name
>> used should reflect the purpose rather than the representation.
>> Assuming the name 's_size' is considered appropriate and
>> acceptable, a suitable typedef can be chosen using a scheme
>> along these lines:
>>
>> #include <limits.h>
>> #include <stdint.h>
>>
>> #if INT_MAX >= SIZE_MAX
>> typedef int s_size;
>> #elif LONG_MAX >= SIZE_MAX
>> typedef long s_size;
>> #elif defined LLONG_MAX && LLONG_MAX >= SIZE_MAX
>> typedef long long s_size;
>> #else
>> typedef intmax_t s_size;
>> #endif
>>
>> after which any interfaces desired should use 's_size' for values
>> of a signed size type.
>
> Your solution is theoretically pure but I don't find it practical.
> For example, I don't want 64-bit s_size on my Cortex-M that
> in practice will never ever have objects  bigger than 2**31-1.

I think you are focusing on the less important part of what I'm
saying.  The key point is to define a new type name, and give
that type name a suitable choice of representation.  If you want
to impose a 31-bit limit on object sizes in a particular program
environment, even though SIZE_MAX is much larger, it's easy to
adapt the chain of #if's accordingly, as for example,

  #if   defined MAXIMUM_OBJECT_SIZE &&   INT_MAX >= MAXIMUM_OBJECT_SIZE
  typedef int s_size;
  #elif defined MAXIMUM_OBJECT_SIZE &&  LONG_MAX >= MAXIMUM_OBJECT_SIZE
  typedef long s_size;
  #elif defined MAXIMUM_OBJECT_SIZE && LLONG_MAX >= MAXIMUM_OBJECT_SIZE
  typedef long long s_size;
  #elif INT_MAX >= SIZE_MAX
    ...
  #endif

and use -DMAXIMUM_OBJECT_SIZE=2147483647 as a compilation flag.

> Also, hopefully before I am retired, intmax_t on common 64-bit
> platforms (x86-64, ARM64, POWER) will become 128-bit.
> In my personal opinion, it's long overdue.
> If current rate of Moore Law is not improved then even with
> all conservatism of standard bodies it will happen several
> decades before the first individual object reaches 2**63-1.
> Or, much more likely,  on 64-bit architectures, size of
> individual objects will never be as big as  2**63-1.  If it at all
> happens, it would be long after migration to wider addresses.
> So, if we follow your suggestion, we'll use 128-bit s_size
> on 64-bit platforms for sole benefit of compatibility with very
> unlikely corner case in very remote future.

Same response.  The chain of #if's in the earlier posting is only
an example.  Of course it can and should be adapted to whatever
particular circumstances are relevant for the environment in
question.  The essential property is to decouple the name of the
type being used, so it can tied to whatever underlying type (and
width, etc) is appropriate to the environment(s) being used.

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


#168341

FromBGB <cr88192@gmail.com>
Date2022-11-23 15:11 -0600
Message-ID<tlm29b$ee1c$2@dont-email.me>
In reply to#168245
On 11/18/2022 2:32 AM, David Brown wrote:
> On 17/11/2022 14:18, A wrote:
>> On Thursday, 17 November 2022 at 18:35:22 UTC+5:30, Bart wrote:
>>> On 17/11/2022 06:31, Amit wrote:
>>>
>>> Anyway a lot of your suggestions really demand generic solutions, and C
>>> doesn't have generic types. For those, there are myriad more assorted
>>> ways to add those to C, but the results are usually ungainly and painful
>>> to use.
>>>
>>> C is just not suited for such things.
>>
>> Generics can be implemented in C without much hassle.
>>
> 
> No, they cannot.
> 

IMHO, one may eventually reach a point where it becomes "less of a 
hassle" to use an API wrapper to implement dynamic types, say for 
example, one has types like:
   lvoVariant  //can hold "whatever"

Then say, calls like:
   lvoVariant lvoFixnum(int64_t val);     //wrap as a fixnum
   int64_t lvoGetFixnum(lvoVariant var);  //get the fixnum
   bool lvoFixnumP(lvoVariant var);       //is this a fixnum?

   lvoVariant lvoFlonum(double val);      //wrap as a flonum
   double lvoGetFlonum(lvoVariant var);   //get the flonum
   bool lvoFlonumP(lvoVariant var);       //is this a flonum?

   ...

For arrays:
   lvoVariant lvoGetIndex(lvoVariant obj, int idx);
   int lvoSetIndex(lvoVariant obj, int idx, lvoVariant var);
   ...

For cons lists:
   lvoVariant lvoCons(lvoVariant car, lvoVariant cdr);  //make a cons
   bool lvoConsP(lvoVariant var);  //is this a cons?
   lvoVariant lvoCar(lvoVariant);  //get 'car' from cons
   lvoVariant lvoCdr(lvoVariant);  //get 'cdr' from cons
   ...

For other stuff:
   lvoVariant lvoAdd(lvoVariant va, lvoVariant vb);  //add two values
   ...


So, for your "generic" array or dictionary, one can basically just put 
whatever into it, and it "magically works", as the containers don't 
actually need to care what types they are being used to hold.


Granted, yes, this sort of thing is very awkward and slow vs normal C 
style, but can scale better to more complex cases than trying to pretend 
that C is C++ ...



No good way to do automatic GC or "destructors" in pure C, this would 
effectively require wrapper calls to initialize and destroy every local 
variable, wrappers to manage things like variable assignment, ...

Say (as macros):
   lvoInit(varA);     //create and initialize a variable to null
   lvoDestroy(varA);  //destroy variable when it leaves scope
   lvoSet(varA, value); //modify a variable


This crosses the line though in terms of how much hassle one can 
reasonably expect people to deal with.

Say:
   lvoInit2(varA, varB);
   lvoSet(varB, lvoFixnum(3));
   lvoSet(varA, lvoAdd(varB, lvoFixnum(4)));
   ...
   lvoDestroy2(varA, varB);




Slightly less of a pain if one can have compiler extensions though:
   __var varA, varB;  //"__var" keyword invokes magic
   varA=3;
   varB=varA+4;

Where the compiler can manage most of the "arcane magic" (so, no need to 
'init', 'set' or 'destroy' variables as the compiler can figure out this 
part).


But, alas, this will not work in a compiler that does not support 
dynamic types, whereas an API like the above doesn't need to assume any 
special compiler support.

Overall performance impact would be similar in both cases (just because 
they are less visible, doesn't mean that the code isn't being 
implemented internally in terms of a mess of function calls into the 
runtime library and similar).

Similarly, it is still kinda awkward to use given the typesystems don't 
mix particularly cleanly (no good way around this).

Though, can note that, even as such, at least in my case, the relative 
performance overhead of using the dynamic typesystem tends to be "less 
severe than one might intuitively expect".

...


>> I am currently implementing C++ STL in C. And the my data structures 
>> are generic - any type of data can be used just like in C++ STL.
>>
> 
> No, they cannot.
> 
> Of course you can make generic containers in C, but you cannot approach 
> the user convenience, safety, or efficiency that is found in other 
> languages that have better support for this kind of thing.  You have no 
> choice but to use generic "void *" pointers, long names, and awkward 
> syntax.
> 
> If you have a vector of "widgets" in a programming language, and you try 
> to add a "whatsit" to it, there are basically three things that can 
> happen :
> 
> 1. The compiler will complain (that's the C++ style).
> 
> 2. The language can happily work correctly with a vector containing 
> "widgets" and "whatsits" and treat them safely (even if the application 
> code gets confused).  That's Python style.
> 
> 3. The language can happily accept the nonsense at compile time, perhaps 
> copying only bits of the "whatsit" or including rubbish in the vector. 
> No one knows what will happen, and as you try to use the "whatsit" as 
> though it were a "widget", you can cause all kinds of corruption or 
> problems that turn up as unexpected effects in completely different 
> parts of the code making debugging a nightmare.  That's C "void*" style.
> 
> 
> Then you have user convenience.  If you want to set the field "x" in 
> element "i" of vector "v" to 1, in C++ you write "v[i].x = 1;".  In C 
> "generic containers", you write:
> 
>      widget * p;
>      vector_get_as_reference(v, i, &p);
>      p->x = 1;
> 
> Or maybe you have something with macro wrappers :
> 
>      VECTOR_GET_AS_REF(v, i, widget)->x = 1;
> 
> 
> I haven't even covered whether you should be holding copies of the 
> widget structures in the vector, or references to them, or references 
> with reference counters, or how you might handle allocation of new 
> widgets and freeing of old ones.
> 
> You /can/ do it all in C, but the usage of the containers will not be 
> comparable in terms of convenience for the programmer, safety, or 
> efficiency.
> 
> The norm in C is to make the lists or containers you need for the data 
> types you need and the features you need.  Usually that's not too hard, 
> and the results are hugely nicer to use and more efficient than any C 
> generic containers.
> 
> 
> That doesn't mean generic containers in C are a bad idea - especially 
> more advanced containers that are harder for programmers to write 
> themselves.  But don't kid yourself that you'll get something as nice as 
> C++'s standard containers, or the containers built into most higher 
> level languages.

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


#168236

FromBonita Montero <Bonita.Montero@gmail.com>
Date2022-11-17 19:05 +0100
Message-ID<tl5t5c$2mnpk$1@dont-email.me>
In reply to#168197
Am 17.11.2022 um 07:31 schrieb Amit:
> Hi,
> 
> In my opinion, glibc should have support for maps, sets, balanced binary trees, many more string functions, etc. (I know tree and hash are there in glibc), so that developers don't have to implement them themselves, thus saving lots of man hours all over the world. This will also make C more user friendly like C++ and Java.
> 
> Amit

glibc is for everything the C language supports as well as
Posix- SysV-,BSD- and Linux-spefic APIs. As C doesn't support
anything you suggest your idea doesn't fit.

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


#168243

Fromgazelle@shell.xmission.com (Kenny McCormack)
Date2022-11-18 08:09 +0000
Message-ID<tl7eiv$6jrs$1@news.xmission.com>
In reply to#168236
In article <tl5t5c$2mnpk$1@dont-email.me>,
Bonita Montero  <Bonita.Montero@gmail.com> wrote:
>Am 17.11.2022 um 07:31 schrieb Amit:
>> Hi,
>> 
>>In my opinion, glibc should have support for maps, sets, balanced
>>binary trees, many more string functions, etc. (I know tree and hash
>>are there in glibc), so that developers don't have to implement them
>>themselves, thus saving lots of man hours all over the world. This
>>will also make C more user friendly like C++ and Java.
>> 
>> Amit
>
>glibc is for everything the C language supports as well as
>Posix- SysV-,BSD- and Linux-spefic APIs. As C doesn't support
>anything you suggest your idea doesn't fit.
>

I heard about this time, back in 1993 or thereabouts, where someone made a
Usenet suggestion that something should be added to the existing libraries
in either C or Unix (not sure which, it was a long time ago) and at least
one responder *didn't* crap all over the idea.

Hasn't happened since, of course...

-- 
There's nothing more American than demanding to carry an AR-15 to
"protect yourself" but refusing to wear a mask to protect everyone else.

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


#168340

FromBGB <cr88192@gmail.com>
Date2022-11-23 13:55 -0600
Message-ID<tlltqr$ee1c$1@dont-email.me>
In reply to#168243
On 11/18/2022 2:09 AM, Kenny McCormack wrote:
> In article <tl5t5c$2mnpk$1@dont-email.me>,
> Bonita Montero  <Bonita.Montero@gmail.com> wrote:
>> Am 17.11.2022 um 07:31 schrieb Amit:
>>> Hi,
>>>
>>> In my opinion, glibc should have support for maps, sets, balanced
>>> binary trees, many more string functions, etc. (I know tree and hash
>>> are there in glibc), so that developers don't have to implement them
>>> themselves, thus saving lots of man hours all over the world. This
>>> will also make C more user friendly like C++ and Java.
>>>
>>> Amit
>>
>> glibc is for everything the C language supports as well as
>> Posix- SysV-,BSD- and Linux-spefic APIs. As C doesn't support
>> anything you suggest your idea doesn't fit.
>>
> 
> I heard about this time, back in 1993 or thereabouts, where someone made a
> Usenet suggestion that something should be added to the existing libraries
> in either C or Unix (not sure which, it was a long time ago) and at least
> one responder *didn't* crap all over the idea.
> 
> Hasn't happened since, of course...
> 

Though to be fair, most stuff that makes sense in the C library is stuff 
that is either relevant to the core language, or can't be done in a 
portable or efficient way in C.

High-level features, like container libraries or data structures, do not 
fit. These are better left to platform or 3rd party libraries.



As noted in the past, my ideas would include:
Ability to load/store values from a pointer with a specific size and 
endianess;
Some extensions for malloc;
Some alternate memcpy variants with different semantics;
...

But could go further:
   Some standardized-ish API for working with SIMD vectors.

As-is, this is a mix of implementation dependent and/or platform 
dependent extensions. Ideally, it should also work independently of 
if/what specific SIMD features are supported by the CPU (able to fall 
back to a plain C implementation for targets) which lack native SIMD.




In my implementation, there are features which would not make as much 
sense in C proper, such as extensions for a dynamic type system (my 
compiler and ISA also partly get involved in the mechanics of the 
dynamic type-system; which are also defined as part of the ABI rules).

Basically, it allows a "variant" type which may hold any type of value 
as a tagged reference (or occasionally "boxing" values as heap-allocated 
objects if they can't be held directly in the tagged-reference format).


This was relevant mostly to some of my other languages, and is also 
seemingly coming up in the context of communication between tasks.

Say: Task A exists in one address space, Task B exists in another, and 
one wants to pass some data from one to another.

If A malloc's something, and passes it to B, then B can't do anything 
with it. A traditional approach would involve RPC and an IDL compiler 
which has enough context to serialize and pass the data structures (say 
via ASN.1 or whatever else).

But, with a dynamic type-system, it can be serialized and decoded 
transparently without needing an IDL (and things like object-level 
interfaces can be maintained transparently across task boundaries; the 
underlying RPC events being mostly hidden from both parties).

Similarly, a more specialized mechanisms can be used for dealing with 
buffer-like objects (say, a blob of bytes for IO, the contents of a "DIB 
Bitmap Object", ...). (Say, the sending task registers the buffer as 
"shared" and the receiving task "maps" the buffer via a syscall, which 
then then performs a Task-to-Task memory copy if "read" or "dirty", and 
when the buffer is released its contents are copied back to the original 
buffer if it was mapped as "dirty" or "write"; the buffer typically 
being "unshared" once the original call finishes).


This would then be wrapped in a more traditional C style interface.
Seemed like a "lesser evil" vs needing to deal with IDLs.

Note that local communication would use a bulky (but fast) serialization 
scheme (mostly passing data as a blob of tagrefs with pointers replaced 
with internal references into this blob). For "more general" use, would 
likely use something akin to S-Expressions (the dynamic typesystem in 
this case is along vaguely similar lines to those seen in Scheme and 
Common Lisp), just printing and parsing S-Expressions would be too much 
overhead for local communication between tasks.
An intermediate option being a more compact variable-length binary 
serialization (say, not always burning 8 bytes for every fixnum, etc).

Such as a program talking to a GUI or Display HAL interface; used so 
that it can draw contents to the screen without needing direct access to 
the display hardware's framebuffer or similar. Where, in this case, this 
was used rather than sockets (or the X11 protocol or similar). Seems 
also like sockets would have had a higher overhead and latency in this 
case than an RPC style mechanism (which in this case, more directly 
invokes the task-switch mechanism; as a special type of syscall).

Interfaces across this mechanism can also take a form resembling COM 
objects (but, a lot of the above comes up with "how does one pass data 
beyond the basic argument list?"...).


But, yeah, not really sure what to make of this.
Makes some sense as platform level features, but not really as part of C 
itself.

[toc] | [prev] | [standalone]


Page 2 of 2 — ← Prev page 1 [2]

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


csiph-web