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


Groups > comp.arch.embedded > #30508

Re: C++, Ada, ...

From Niklas Holsti <niklas.holsti@tidorum.invalid>
Newsgroups comp.arch.embedded
Subject Re: C++, Ada, ...
Date 2021-04-19 13:51 +0300
Organization Tidorum Ltd
Message-ID <ie55l3F3ou7U1@mid.individual.net> (permalink)
References (1 earlier) <s5f3c1$s06$1@dont-email.me> <AaGeI.148580$qHh9.147135@fx18.ams4> <s5h32f$edv$1@dont-email.me> <ie32luFlvghU1@mid.individual.net> <s5hogv$77o$1@dont-email.me>

Show all headers | View raw


On 2021-04-18 19:59, David Brown wrote:
> On 18/04/2021 17:48, Niklas Holsti wrote:
>> On 2021-04-18 13:53, David Brown wrote:
>>> On 17/04/2021 20:55, Tom Gardner wrote:
>>>> On 17/04/21 17:45, David Brown wrote:
>>>>> And most of
>>>>> the advantages of Ada (such as better typing) can be achieved in C++
>>>>> with less effort, and at the same time C++ can give additional
>>>>> safety on
>>>>> resources that is harder to get on Ada.
>>>>
>>>> Interesting. Could you give a quick outline of that?
>>>>
>>>
>>> Which part?
>>>
>>> My understanding of Ada classes is that, like Pascal classes, you need
>>> to explicitly construct and destruct objects.  This gives far greater
>>> scope for programmers to get things wrong than when they are handled
>>> automatically by the language.
>>
>>
>> If you mean automatic allocation and deallocation of storage, Ada lets
>> you define types that have an "initializer" that is called
>> automatically, and can allocate memory if it needs to, and a "finalizer"
>> that is automatically called when leaving the scope of the object in
>> question. The finalizer does have to explicitly deallocate any
>> explicitly allocated and owned resources, and it may have to use
>> reference counting for that, for complex data structures.
> 
> I had a little look for this (these discussions are great for inspiring
> learning!).  The impression I got was that it was possible, but what
> takes a few lines of C++ (excluding whatever work must be done inside
> the constructor and destructor bodies) involves inheriting from a
> specific library type.


Yes, you must inherit from one of the types Ada.Finalization.Controlled 
or Ada.Finalization.Limited_Controlled when you create a type for which 
you can program an initializer and/or a finalizer.

However, you can aggregate a component of such a type into some other 
composite type, and then that component's initializer and finalizer will 
be called automatically when any object of the containing composite type 
is constructed and destroyed.


> And you don't have automatic initialisation of
> subobjects and ancestors in a controlled order, nor automatic
> finalisation of them in the reverse order.


No, and yes. Subobjects (components) are automatically initialized 
before the composite is initialized (bottom-up), and are automatically 
finalized after the composite is finalized (top-down). But there is no 
automatic invocation of the initializer or finalizer of the parent 
class; that would have to be called explicitly (except in the case of an 
"extension aggregate" expression, where an object of the parent type is 
created and then extended to an object of the derived class).

The Ada initializer and finalizer concept is subtly different from the 
C++ constructor and destructor concept. In Ada, the construction and 
destruction are considered to happen implicitly and automatically. The 
construction step can assign some initial values that can be defined by 
default (pointers default to null, for example) or can be specified for 
the type of the component in question, or can be defined for that 
component explicitly. For example:

    type Down_Counter is range 0 .. 100 with Default_Value => 100;

    type Zero_Handler is access procedure;

    type Counter is record
       Count   : Down_Counter;      -- Implicit init to 100.
       Running : Boolean := False;  -- Explicit init.
       At_Zero : Zero_Handler;      -- Default init to null.
    end record;

Beyond that automatic construction step, the programmable initializer is 
used to perform further automatic activities that may further initialize 
the object, or may have some other effects. For example, we might want 
to automatically register every instance of a Counter (as above) with 
the kernel, and that would be done in the initializer. Conversely, the 
finalizer would then deregister the Counter, before the Counter is 
automatically destroyed (removed from the stack or from the heap).

So the Ada "initializer" is not like a C++ constructor, which in Ada 
corresponds more closely to a function returning an object of the class.

An Ada "finalizer" is more similar to a C++ destructor, taking care of 
any clean-up that is needed before the object disappears.

> 
> Let's take a little example.  And since this is comp.arch.embedded,
> let's take a purely embedded example of disabling interrupts, rather
> than shunned dynamic memory allocations:
> 
> static inline uint32_t disableGlobalInterrupts(void) {
>      uint32_t pri;
>      asm volatile(
>          "  mrs %[pri], primask\n\t" // Get old mask
>          "  cpsid i\n\t"             // Disable interrupts entirely
>          "  dsb"	    // Ensures that this takes effect before next
>                      // instruction
>          : [pri] "=r" (pri) :: "memory");
>      return pri;
> }
> 
> static inline void restoreGlobalInterrupts(uint32_t pri) {
>      asm volatile(
>          "  msr primask, %[pri]"         // Restore old mask
>          :: [pri] "r" (pri) : "memory");
> }


I won't try to write Ada equivalents of the above :-) though I have of 
course written much Ada code to manage and handle interrupts.


> class CriticalSectionLock {
> private :
>      uint32_t oldpri;
> public :
>      CriticalSectionLock() { oldpri = disableGlobalInterrupts(); }
>      ~CriticalSectionLock() { restoreGlobalInterrupts(oldpri); }
> };


Here is the same in Ada. I chose to derive from Limited_Controlled 
because that makes it illegal to assign a Critical_Section value from 
one object to another.

    -- Declaration of the type:

    type Critical_Section is new Ada.Finalization.Limited_Controlled
    with record
       old_pri : Interfaces.Unsigned_32;
    end record;

    overriding procedure Initialize (This : in out Critical_Section);
    overriding procedure Finalize   (This : in out Critical_Section);

    -- Implementation of the operations:

    procedure Initialize (This : in out Critical_Section)
    is begin
       This.old_pri := disableGlobalInterrupts;
    end Initialize;

    procedure Finalize (This : in out Critical_Section)
    is begin
       restoreGlobalInterrupts (This.old_pri);
    end Finalize;


> 
> You can use it like this:
> 
> bool compare_and_swap64(uint64_t * p, uint64_t old, uint64_t x)
> {
> 	CriticalSectionLock lock;
> 
> 	if (*p != old) return false;
> 	*p = x;
> 	return true;
> }
> 


    function Compare_and_Swap64 (
       p      : access Interfaces.Unsigned_64;
       old, x : in     Interfaces.Unsigned_64)
    return Boolean
    is
       Lock : Critical_Section;
    begin
       if p.all /= old then
          return False;
       else
          p.all := x;
          return True;
       end if;
    end Compare_and_Swap64;

(I think there should be a "volatile" spec for the "p" object, don't you?)



> This is the code compiled for a 32-bit Cortex-M device:
> 
> <https://godbolt.org/z/7KM9M6Kcd>
> 
> The use of the class here has no overhead compared to manually disabling
> and re-enabling interrupts.
> 
> What would be the Ada equivalent of this class, and of the
> "compare_and_swap64" function?


See above. I don't have an Ada-to-Cortex-M compiler at hand to compare 
the target code, sorry.

But critical sections in Ada applications are more often written using 
the Ada "protected object" feature. Here is the same as a protected 
object "CS", with separate declaration and body as usual in Ada. Here I 
must write the operation as a procedure instead of a function, because 
protected objects have "single writer, multiple readers" semantics, and 
any function is considered a "reader" although it may have side effects:

    protected CS
       with Priority => System.Interrupt_Priority'Last
    is

       procedure Compare_and_Swap64 (
          p      : access Interfaces.Unsigned_64;
          old, x : in     Interfaces.Unsigned_64;
          result :    out Boolean);

    end CS;

    protected body CS
    is

       procedure Compare_and_Swap64 (
          p      : access Interfaces.Unsigned_64;
          old, x : in     Interfaces.Unsigned_64;
          result :    out Boolean);
       is begin
	  result := p.all = old;
	  if result then
              p.all := x;
           end if;
       end Compare_and_Swap64;

    end CS;

However, it would be more in the style of Ada to focus on the thing that 
is being "compared and swapped", so that "p" would be either a 
discriminant of the protected object, or a component of the protected 
object, instead of a parameter to the copy-and-swap operation. But it 
would look similar to the above.


>>> On the third hand (three hands are always useful for programming), the
>>> wordy nature of type conversions in Ada mean programmers would be
>>> tempted to take shortcuts and skip these extra types.
>>
>>
>> Huh? A normal conversion in C is written "(newtype)expression", the same
>> in Ada is written "newtype(expression)". Exactly the same number of
>> characters, only the placement of the () is different. The C form might
>> even require an extra set of parentheses around it, to demarcate the
>> expression to be converted from any containing expression.
>>
>> Of course, in C you have implicit conversions between all kinds of
>> numerical types, often leading to a whole lot of errors... not only
>> apples+oranges, but also truncation or other miscomputation.
> 
> C also makes explicit conversions wordy, yes.  In C++, you can choose
> which conversions are explicit and which are implicit - done carefully,
> your safe conversions will be implicit and unsafe ones need to be explicit.


Ada does not have programmable implicit conversions, but one can 
override some innocuous operator, usually "+", to perform whatever 
conversions one wants. For example:

    function "+" (Item : Boolean) return Float
    is (if Item then 1.0 else 0.0);

or more directly

    function "+" (Item : Boolean) return Float
    is (Float (Boolean'Pos (Item)));


> (C++ suffers from its C heritage and backwards compatibility, meaning it
> can't fix things that were always implicit conversion.  It's too late to
> make "int x = 123.4;" an error.  The best C++ can do is add a new syntax
> with better safety - so "int y { 123 };" is fine but "int z { 123.4 };"
> is an error.)


Ada also has some warts, but perhaps not as easily illustrated.

Back to comp.arch.embedded | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread


Thread

C++, Ada, ... pozz <pozzugno@gmail.com> - 2021-04-17 17:48 +0200
  Re: C++, Ada, ... David Brown <david.brown@hesbynett.no> - 2021-04-17 18:45 +0200
    Re: C++, Ada, ... Tom Gardner <spamjunk@blueyonder.co.uk> - 2021-04-17 19:55 +0100
      Re: C++, Ada, ... David Brown <david.brown@hesbynett.no> - 2021-04-18 12:53 +0200
        Re: C++, Ada, ... Niklas Holsti <niklas.holsti@tidorum.invalid> - 2021-04-18 18:48 +0300
          Re: C++, Ada, ... David Brown <david.brown@hesbynett.no> - 2021-04-18 18:59 +0200
            Re: C++, Ada, ... Niklas Holsti <niklas.holsti@tidorum.invalid> - 2021-04-19 13:51 +0300
              Re: C++, Ada, ... David Brown <david.brown@hesbynett.no> - 2021-04-19 14:22 +0200
                Re: C++, Ada, ... Niklas Holsti <niklas.holsti@tidorum.invalid> - 2021-04-19 19:16 +0300
                Re: C++, Ada, ... David Brown <david.brown@hesbynett.no> - 2021-04-19 22:19 +0200
                Re: C++, Ada, ... Niklas Holsti <niklas.holsti@tidorum.invalid> - 2021-04-20 01:03 +0300
                Re: C++, Ada, ... Richard Damon <Richard@Damon-Family.org> - 2021-04-19 18:09 -0400
                Re: C++, Ada, ... David Brown <david.brown@hesbynett.no> - 2021-04-20 06:58 +0200
                Re: C++, Ada, ... Paul Rubin <no.email@nospam.invalid> - 2021-04-19 23:18 -0700
                Re: C++, Ada, ... David Brown <david.brown@hesbynett.no> - 2021-04-20 09:36 +0200
              Re: C++, Ada, ... Paul Rubin <no.email@nospam.invalid> - 2021-04-19 12:20 -0700
                Re: C++, Ada, ... Niklas Holsti <niklas.holsti@tidorum.invalid> - 2021-04-20 00:26 +0300
                Re: C++, Ada, ... Paul Rubin <no.email@nospam.invalid> - 2021-04-19 16:01 -0700
                Re: C++, Ada, ... Niklas Holsti <niklas.holsti@tidorum.invalid> - 2021-04-20 10:47 +0300
                Re: C++, Ada, ... Tom Gardner <spamjunk@blueyonder.co.uk> - 2021-04-19 23:30 +0100
    Re: C++, Ada, ... Clifford Heath <no.spam@please.net> - 2021-04-18 08:29 +1000
    Re: C++, Ada, ... Niklas Holsti <niklas.holsti@tidorum.invalid> - 2021-04-18 10:39 +0300
      Re: C++, Ada, ... David Brown <david.brown@hesbynett.no> - 2021-04-18 14:59 +0200
        Re: C++, Ada, ... Niklas Holsti <niklas.holsti@tidorum.invalid> - 2021-04-18 19:23 +0300
          Re: C++, Ada, ... David Brown <david.brown@hesbynett.no> - 2021-04-18 19:26 +0200
            Re: C++, Ada, ... Tom Gardner <spamjunk@blueyonder.co.uk> - 2021-04-18 19:29 +0100
              Re: C++, Ada, ... David Brown <david.brown@hesbynett.no> - 2021-04-18 22:23 +0200
                Re: C++, Ada, ... Tom Gardner <spamjunk@blueyonder.co.uk> - 2021-04-18 23:09 +0100
                Re: C++, Ada, ... David Brown <david.brown@hesbynett.no> - 2021-04-19 08:56 +0200
                Re: C++, Ada, ... Niklas Holsti <niklas.holsti@tidorum.invalid> - 2021-04-19 14:04 +0300
                Re: C++, Ada, ... Dimiter_Popoff <dp@tgi-sci.com> - 2021-04-19 15:16 +0300
                Re: C++, Ada, ... Paul Rubin <no.email@nospam.invalid> - 2021-04-19 12:47 -0700
                Re: C++, Ada, ... Niklas Holsti <niklas.holsti@tidorum.invalid> - 2021-04-20 00:37 +0300
                Re: C++, Ada, ... David Brown <david.brown@hesbynett.no> - 2021-04-20 07:50 +0200
                Re: C++, Ada, ... David Brown <david.brown@hesbynett.no> - 2021-04-19 14:26 +0200
            Re: C++, Ada, ... Tom Gardner <spamjunk@blueyonder.co.uk> - 2021-04-18 19:30 +0100
              Re: C++, Ada, ... David Brown <david.brown@hesbynett.no> - 2021-04-18 22:17 +0200
                Re: C++, Ada, ... Tom Gardner <spamjunk@blueyonder.co.uk> - 2021-04-18 23:17 +0100
                Re: C++, Ada, ... David Brown <david.brown@hesbynett.no> - 2021-04-19 08:52 +0200
                Re: C++, Ada, ... Tom Gardner <spamjunk@blueyonder.co.uk> - 2021-04-19 10:08 +0100
                Re: C++, Ada, ... David Brown <david.brown@hesbynett.no> - 2021-04-19 12:15 +0200
                Re: C++, Ada, ... Tom Gardner <spamjunk@blueyonder.co.uk> - 2021-04-19 12:00 +0100
                Re: C++, Ada, ... Tauno Voipio <tauno.voipio@notused.fi.invalid> - 2021-04-19 16:15 +0300
                Re: C++, Ada, ... David Brown <david.brown@hesbynett.no> - 2021-04-19 15:43 +0200
    Re: C++, Ada, ... pozz <pozzugno@gmail.com> - 2021-04-19 18:38 +0200
      Re: C++, Ada, ... Paul Rubin <no.email@nospam.invalid> - 2021-04-19 10:48 -0700
      Re: C++, Ada, ... Tom Gardner <spamjunk@blueyonder.co.uk> - 2021-04-19 19:33 +0100
        Re: C++, Ada, ... Tauno Voipio <tauno.voipio@notused.fi.invalid> - 2021-04-20 15:09 +0300
          Re: C++, Ada, ... Tom Gardner <spamjunk@blueyonder.co.uk> - 2021-04-20 15:29 +0100
      Re: C++, Ada, ... David Brown <david.brown@hesbynett.no> - 2021-04-19 22:48 +0200
        Re: C++, Ada, ... pozz <pozzugno@gmail.com> - 2021-04-19 23:17 +0200
          Re: C++, Ada, ... Paul Rubin <no.email@nospam.invalid> - 2021-04-19 15:55 -0700
            Re: C++, Ada, ... David Brown <david.brown@hesbynett.no> - 2021-04-20 08:21 +0200
          Re: C++, Ada, ... David Brown <david.brown@hesbynett.no> - 2021-04-20 08:20 +0200
  Re: C++, Ada, ... Dave Nadler <drn@nadler.com> - 2021-04-17 21:07 -0400
    Re: C++, Ada, ... Don Y <blockedofcourse@foo.invalid> - 2021-04-17 18:53 -0700
    Re: C++, Ada, ... Tom Gardner <spamjunk@blueyonder.co.uk> - 2021-04-18 09:42 +0100
  Re: C++, Ada, ... dalai lamah <antonio12358@hotmail.com> - 2021-04-18 14:39 +0200

csiph-web