comp.lang.ada
 help / color / mirror / Atom feed
* Pointers explained?
@ 2007-07-30 17:53 shaunpatterson
  2007-07-30 17:56 ` shaunpatterson
                   ` (2 more replies)
  0 siblings, 3 replies; 20+ messages in thread
From: shaunpatterson @ 2007-07-30 17:53 UTC (permalink / raw)


Hi

   I'm still relatively new to Ada -- coming from a strong C++
background.  Some of this may seem stupid - and feel free to point it
out to me.  I am using Ada 95 - GNAT Pro 3.16a1


I have a message factory I've been screwing around with (converting it
from Ada to C++).

I basically have an abstract message type:

type Message is abstract tagged null record;
type Message_Class is access all Message'Class;


then all other messages are derived from this.

Now from my factory create method, I'm returning a Message_Class.
This message_class
is stored in another record to be handled again later:

type CallbackEvent is
record
     msg : Message_Class;
     ...
end record;


Now my basic problem -- or not really a problem -- is that to create
the Message_Class I have to use
"new" and allocate and deallocate memory.

Now - my solution was to re-write my message factory to return a type
Message'Class.  However, I went
to change my callback structure to:

type CallbackEvent is
record




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Pointers explained?
@ 2007-07-30 17:53 shaunpatterson
  0 siblings, 0 replies; 20+ messages in thread
From: shaunpatterson @ 2007-07-30 17:53 UTC (permalink / raw)


Hi

   I'm still relatively new to Ada -- coming from a strong C++
background.  Some of this may seem stupid - and feel free to point it
out to me.  I am using Ada 95 - GNAT Pro 3.16a1


I have a message factory I've been screwing around with (converting it
from Ada to C++).

I basically have an abstract message type:

type Message is abstract tagged null record;
type Message_Class is access all Message'Class;


then all other messages are derived from this.

Now from my factory create method, I'm returning a Message_Class.
This message_class
is stored in another record to be handled again later:

type CallbackEvent is
record
     msg : Message_Class;
     ...
end record;


Now my basic problem -- or not really a problem -- is that to create
the Message_Class I have to use
"new" and allocate and deallocate memory.

Now - my solution was to re-write my message factory to return a type
Message'Class.  However, I went
to change my callback structure to:

type CallbackEvent is
record




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Pointers explained?
  2007-07-30 17:53 Pointers explained? shaunpatterson
@ 2007-07-30 17:56 ` shaunpatterson
  2007-07-30 19:04   ` Ed Falis
                     ` (4 more replies)
  2007-07-30 20:11 ` Dmitry A. Kazakov
  2007-07-31  8:28 ` Martin Krischik
  2 siblings, 5 replies; 20+ messages in thread
From: shaunpatterson @ 2007-07-30 17:56 UTC (permalink / raw)


------- OKAY sorry... I tried to tab in and accidentally activated the
POST button ----

Hi

   I'm still relatively new to Ada -- coming from a strong C++
background.  Some of this may seem stupid - and feel free to point it
out to me.  I am using Ada 95 - GNAT Pro 3.16a1


I have a message factory I've been screwing around with (converting
it
from Ada to C++).


I basically have an abstract message type:


type Message is abstract tagged null record;
type Message_Class is access all Message'Class;


then all other messages are derived from this.


Now from my factory create method, I'm returning a Message_Class.
This message_class
is stored in another record to be handled again later:


type CallbackEvent is
record
     msg : Message_Class;
     ...
end record;


Now my basic problem -- or not really a problem -- is that to create
the Message_Class I have to use
"new" and allocate and deallocate memory.


Now - my solution was to re-write my message factory to return a type
Message'Class.  However, I went
to change my callback structure to:


type CallbackEvent is
record
    msg : Message'Class
end record;


and I get the message "unconstrained subtype in component declaration"

So, I'm assuming the compiler just doesn't know how to big this
message is.
that's why I believe i should use a pointer (the Message_Class type)
However,
I cannot find a way of converting between a Message'Class to a
Message_Class;

It appears that the only way to get a Message_Class is by some where
in the
code using a "new"

Is this assumption correct?

thanks!

--
Shaun








^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Pointers explained?
  2007-07-30 17:56 ` shaunpatterson
@ 2007-07-30 19:04   ` Ed Falis
  2007-07-30 19:05   ` Ludovic Brenta
                     ` (3 subsequent siblings)
  4 siblings, 0 replies; 20+ messages in thread
From: Ed Falis @ 2007-07-30 19:04 UTC (permalink / raw)


shaunpatterson@gmail.com wrote:

> It appears that the only way to get a Message_Class is by some where
> in the
> code using a "new"
>
> Is this assumption correct?

No.  If you allocate a Message object statically (in package data), you
can do something like:

X : aliased Specific_Message_Type;

function Get_One return Message_Class is
begin
   return X'Access;
end Get_One;



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Pointers explained?
  2007-07-30 17:56 ` shaunpatterson
  2007-07-30 19:04   ` Ed Falis
@ 2007-07-30 19:05   ` Ludovic Brenta
  2007-07-30 19:36   ` Adam Beneschan
                     ` (2 subsequent siblings)
  4 siblings, 0 replies; 20+ messages in thread
From: Ludovic Brenta @ 2007-07-30 19:05 UTC (permalink / raw)


shaunpatterson@gmail.com writes:
> Hi
>
>    I'm still relatively new to Ada -- coming from a strong C++
> background.  Some of this may seem stupid - and feel free to point it
> out to me.  I am using Ada 95 - GNAT Pro 3.16a1
>
> I have a message factory I've been screwing around with (converting
> it from Ada to C++).
>
> I basically have an abstract message type:
>
> type Message is abstract tagged null record;
> type Message_Class is access all Message'Class;
>
> then all other messages are derived from this.
>
> Now from my factory create method, I'm returning a Message_Class.
> This message_class is stored in another record to be handled again
> later:
>
> type CallbackEvent is
> record
>      msg : Message_Class;
>      ...
> end record;
>
>
> Now my basic problem -- or not really a problem -- is that to create
> the Message_Class I have to use "new" and allocate and deallocate
> memory.
>
> Now - my solution was to re-write my message factory to return a
> type Message'Class.  However, I went to change my callback structure
> to:
>
> type CallbackEvent is
> record
>     msg : Message'Class
> end record;
>
> and I get the message "unconstrained subtype in component declaration"
>
> So, I'm assuming the compiler just doesn't know how to big this
> message is.  that's why I believe i should use a pointer (the
> Message_Class type) However, I cannot find a way of converting
> between a Message'Class to a Message_Class;
>
> It appears that the only way to get a Message_Class is by some where
> in the code using a "new"
>
> Is this assumption correct?

I think this is both a language issue and a design issue.

From the language standpoint, your assumption would be correct had you
declared Message_Class thus:

type Message_Class is access Message'Class;

This declares a "pool-specific" access type, and the only way to
create values of this type is by calling "new" which will allocate
from a storage pool (there is a default storage pool, but you could
create your own).  But, your actual declaration reads:

type Message_Class is access all Message'Class;

The "all" keyword makes this a "general" access type, meaning it can
take access values of objects that are in any pool, or on the stack,
or in the data segment.  So, there are two ways to create values of
this type: with "new" or by means of the Access attribute, like this:

declare
   M : aliased Message'Class := Factory; -- Note: M is on the stack
   Event : Callback_Event := (Msg => M'Access);
begin
   ...
end;

Note that, before you can take the 'Access of an object such as M, you
must declare it as aliased.  (In C++, everything is implicitly
aliased.  In Ada, aliasing is explicit and only occurs when you say it
does).

Now, from a design standpoint, I don't think you really want to record
access values for Messages on the stack or data segment, do you?  In
which case, the pool-specific access type and mandatory call to "new"
are really what you want.  So, how about this:

type Message is abstract tagged null record;
type Message_Class is access Message'Class;

type Message_Type is (A, B, C);

function Factory (Kind : Message_Type) return Message_Class is
begin
   case Kind is
      when A => return new Message_A'(...);
      when B => return new Message_B'(...);
      when C => return new Message_C'(...);
   end case;
end Factory;

function Factory (Kind : Message_Type) return Callback_Event is
begin
   return (Msg => Factory (Kind), ...);
end Factory;

HTH

-- 
Ludovic Brenta.



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Pointers explained?
  2007-07-30 17:56 ` shaunpatterson
  2007-07-30 19:04   ` Ed Falis
  2007-07-30 19:05   ` Ludovic Brenta
@ 2007-07-30 19:36   ` Adam Beneschan
  2007-07-30 21:23     ` Maciej Sobczak
  2007-07-30 22:20     ` Adam Beneschan
  2007-07-30 21:31   ` Jeffrey R. Carter
  2007-07-31 17:21   ` Simon Wright
  4 siblings, 2 replies; 20+ messages in thread
From: Adam Beneschan @ 2007-07-30 19:36 UTC (permalink / raw)


On Jul 30, 10:56 am, shaunpatter...@gmail.com wrote:

> Hi
>
>    I'm still relatively new to Ada -- coming from a strong C++
> background. Some of this may seem stupid - and feel free to point it
> out to me.

I don't have a strong C++ background, so some of my response may seem
stupid.

> I am using Ada 95 - GNAT Pro 3.16a1
>
> I have a message factory I've been screwing around with (converting
> it
> from Ada to C++).
>
> I basically have an abstract message type:
>
> type Message is abstract tagged null record;
> type Message_Class is access all Message'Class;
>
> then all other messages are derived from this.
>
> Now from my factory create method, I'm returning a Message_Class.
> This message_class
> is stored in another record to be handled again later:
>
> type CallbackEvent is
> record
>      msg : Message_Class;
>      ...
> end record;
>
> Now my basic problem -- or not really a problem -- is that to create
> the Message_Class I have to use
> "new" and allocate and deallocate memory.
>
> Now - my solution was to re-write my message factory to return a type
> Message'Class.  However, I went
> to change my callback structure to:
>
> type CallbackEvent is
> record
>     msg : Message'Class
> end record;
>
> and I get the message "unconstrained subtype in component declaration"
>
> So, I'm assuming the compiler just doesn't know how to big this
> message is.

That's pretty much correct.  Technically, "Message'Class" is an
"indefinite subtype"; other examples of indefinite subtypes would be
"string", which is an unconstrained array that you haven't given the
bounds for.  You can't have a variable or component declaration that
looks like

   X : String;

The reason is basically the same, though: the compiler wouldn't know
how much to allocate.  Of course the compiler can't know how big a
Message'Class is, because the object could be *any* type that you
derived from Message, including a type in a package that you haven't
even written yet.

> that's why I believe i should use a pointer (the Message_Class type)

I think you're right.  Others will probably point out how the fact
that Message_Class is a pointer ought to be hidden from users of your
Message package.  But at some point, a pointer will likely be needed.

> However,
> I cannot find a way of converting between a Message'Class to a
> Message_Class;
>
> It appears that the only way to get a Message_Class is by some where
> in the
> code using a "new"
>
> Is this assumption correct?

Not quite.  The other thing you can do is use 'Access on a variable
whose type in Message'Class, if the variable is declared "aliased":

   Z : aliased Message_1;

now Z'Access gives you a "pointer" to Z, which can used in a context
where a Message_Class is expected.  (Sort of like the & operator in C+
+.)  But this is unlikely to help you much.  It won't work to declare
Z as a local variable in your factory function---Ada won't let you do
that, and it shouldn't, because the memory used for Z will be on the
stack, and the stack will disappear when your factory function exits
and will be overwritten by the next subroutine you call.  C++ will of
course let you do that, with the likely result that any machine that
runs the program will end up screwing itself up and probably become
part of a botnet that will fill MY inbox with messages about fake
Rolexes and Canadian drugs and web sites that tell me how I can
enlarge my ... um ... bowling score.  So I'd definitely prefer that
you use Ada.

Anyway, there may be some cases where returning an access to a global
variable may be appropriate, but those are probably not the norm.  So
some sort of dynamic allocation (via "new") will likely be necessary,
at some point.

A couple things I might point out: First, if you have a factory
function [say Create_Message] that returns Message'Class (i.e. *not* a
pointer), you can declare variables of type Message'Class as long as
you use the function (or some other function call, maybe) as an
initializer:

    Var1 : Message'Class := Create_Message (...);

When you do this, Create_Message can return any type derived from
Message.  At that point, the program will determine how much space is
needed for Var1 and allocate it.  Var1's type can't be changed after
that, though; if Create_Message returns a Message_3, Var1's type will
be fixed at Message_3, and you can't, say, assign

    Var1 := Y;

unless Y also happens to have type Message_3.  (If it's the wrong
type, a Constraint_Error exception will be raised.)  This applies to
record components also; by default, the function will be called to set
up the component when any variable of that record type is created.
The variable will be allocated dynamically, but you won't need a "new"
to allocate it and you won't have to worry about deallocation---that
will all be taken care of automatically.

Second, if there's some place in the program where you *know* what
type that factory function will return, you can take advantage of
that, e.g.:

   type Record_With_Message_4 is record
       Msg : Message_4;
   end record;

   R : Record_With_Message_4;
   ...

   R.Msg := Create_Message (...);

Now the code will call Create_Message but then check to make sure the
type returned is actually Message_4.  If it isn't, a Constraint_Error
exception will be raised.  If it is, the message will be set up, and
Msg will probably not be dynamically allocated.

Anyway, those are a couple cases where you can use your factory
function without "new".  Because of that, I'd recommend writing an
overloaded function:

   function Create_Message (...) return Message'Class;
   function Create_Message (...) return Message_Class;

where the body of the second function would be

   function Create_Message (...) return Message_Class is
   begin
      return new Message'Class (Create_Message (...));
   end;

or something to that effect.  The compiler will be able to tell from
context which Create_Message, the one that returns the Message'Class
or the one that returns the pointer, is being called, unless the
context is ambiguous.

Anyway, I'm sure others have some other ideas they can give you.  In
places where "new" will be necessary somewhere, you may want to look
into controlled types to get the deallocation to be done
automatically.  But this message is already real long, so I'll let
others enlighten you with the details of that.

Hope at least some of this is helpful,

                    -- Adam





^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Pointers explained?
  2007-07-30 17:53 Pointers explained? shaunpatterson
  2007-07-30 17:56 ` shaunpatterson
@ 2007-07-30 20:11 ` Dmitry A. Kazakov
  2007-07-31  8:28 ` Martin Krischik
  2 siblings, 0 replies; 20+ messages in thread
From: Dmitry A. Kazakov @ 2007-07-30 20:11 UTC (permalink / raw)


On Mon, 30 Jul 2007 10:53:16 -0700, shaunpatterson@gmail.com wrote:

> Now from my factory create method, I'm returning a Message_Class.
> This message_class is stored in another record to be handled again later:
> 
> type CallbackEvent is
> record
>      msg : Message_Class;
>      ...
> end record;

Are you sure that you want to copy messages? Let there are 10000
subscribers to a messages publisher. Then upon emitting a message you will
copy it 10000 times!

I would consider:

type CallbackEvent (Message : access Message'Class) is

> Now my basic problem -- or not really a problem -- is that to create
> the Message_Class I have to use "new" and allocate and deallocate memory.

> Now - my solution was to re-write my message factory to return a type
> Message'Class.  However, I went
> to change my callback structure to:

No problem, leave factory as-is, returning Message'Class. Whenever you
would need to allocate Message, you could still do it like this:

    new Message'Class'(Factory (...));

Factory returns Message'Class used to initialize the memory allocated for
the new object.

> type CallbackEvent is
> record

You could consider making reference counted Messages and handles to them.
Handles will be copied around and placed into containers like
CallbackEvent.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Pointers explained?
  2007-07-30 19:36   ` Adam Beneschan
@ 2007-07-30 21:23     ` Maciej Sobczak
  2007-07-30 22:36       ` Adam Beneschan
  2007-07-31  1:15       ` Anh Vo
  2007-07-30 22:20     ` Adam Beneschan
  1 sibling, 2 replies; 20+ messages in thread
From: Maciej Sobczak @ 2007-07-30 21:23 UTC (permalink / raw)


On 30 Lip, 21:36, Adam Beneschan <a...@irvine.com> wrote:

> C++ will of
> course let you do that

C++ will of course let you do that, but this statement itself is
meaningless, because languages are never used directly. In real life
you might want to use a *compiler* to compile the C++ code and recent
versions of g++ produce a nice warning message when you try to return
an address of a local variable (even without any additional options).
I guess other C++ compilers are smart enough to do the same, so it's
not that bad.

On the other hand it is true that the whole scenario can be made more
complex up to the point where the compiler will not catch the problem,
but will have to accept it, so it's not perfect either.

Note that Ada programmers also have 'Unrestricted_Access (GNAT) and
'Unchecked_Access to cheat around the rules.

--
Maciej Sobczak
http://www.msobczak.com/




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Pointers explained?
  2007-07-30 17:56 ` shaunpatterson
                     ` (2 preceding siblings ...)
  2007-07-30 19:36   ` Adam Beneschan
@ 2007-07-30 21:31   ` Jeffrey R. Carter
  2007-07-31 17:21   ` Simon Wright
  4 siblings, 0 replies; 20+ messages in thread
From: Jeffrey R. Carter @ 2007-07-30 21:31 UTC (permalink / raw)


shaunpatterson@gmail.com wrote:
> ------- OKAY sorry... I tried to tab in and accidentally activated the
> POST button ----

Once you get used to the de facto Ada standard of never using tabs in 
source, you won't have this problem.

> Now - my solution was to re-write my message factory to return a type
> Message'Class.  However, I went
> to change my callback structure to:
> 
> type CallbackEvent is
> record
>     msg : Message'Class
> end record;

> and I get the message "unconstrained subtype in component declaration"

Right, 'Class is always an unconstrained subtype. However, you can 
declare objects of an unconstrained subtype, provided you provide an 
initial value. The object takes its constraints from the initial value:

S : String := "abc";

Similarly, if you define a function F that returns Message'Class, you 
can declare objects of the subtype:

M : Message'Class := F;

This may or may not help you, because you still can't have components of 
an unconstrained subtype. If you need a component, you will need access 
types. Then good practice is to hide the use of access types from your 
package's clients.

-- 
Jeff Carter
"Have you gone berserk? Can't you see that that man is a ni?"
Blazing Saddles
38



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Pointers explained?
  2007-07-30 19:36   ` Adam Beneschan
  2007-07-30 21:23     ` Maciej Sobczak
@ 2007-07-30 22:20     ` Adam Beneschan
  1 sibling, 0 replies; 20+ messages in thread
From: Adam Beneschan @ 2007-07-30 22:20 UTC (permalink / raw)


On Jul 30, 12:36 pm, I wrote while half-asleep:

> A couple things I might point out: First, if you have a factory
> function [say Create_Message] that returns Message'Class (i.e. *not* a
> pointer), you can declare variables of type Message'Class as long as
> you use the function (or some other function call, maybe) as an
> initializer:
>
>     Var1 : Message'Class := Create_Message (...);
>
> When you do this, Create_Message can return any type derived from
> Message.  At that point, the program will determine how much space is
> needed for Var1 and allocate it.  Var1's type can't be changed after
> that, though; if Create_Message returns a Message_3, Var1's type will
> be fixed at Message_3, and you can't, say, assign
>
>     Var1 := Y;
>
> unless Y also happens to have type Message_3.  (If it's the wrong
> type, a Constraint_Error exception will be raised.)  This applies to
> record components also

No, it doesn't.  My bad.  Record components have to have definite
subtypes.  Sorry---I should have tried it first to make sure.

                     -- Adam




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Pointers explained?
  2007-07-30 21:23     ` Maciej Sobczak
@ 2007-07-30 22:36       ` Adam Beneschan
  2007-07-31  7:33         ` Dmitry A. Kazakov
  2007-07-31  1:15       ` Anh Vo
  1 sibling, 1 reply; 20+ messages in thread
From: Adam Beneschan @ 2007-07-30 22:36 UTC (permalink / raw)


On Jul 30, 2:23 pm, Maciej Sobczak <see.my.homep...@gmail.com> wrote:
> On 30 Lip, 21:36, Adam Beneschan <a...@irvine.com> wrote:
>
> > C++ will of
> > course let you do that
>
> C++ will of course let you do that, but this statement itself is
> meaningless, because languages are never used directly. In real life
> you might want to use a *compiler* to compile the C++ code and recent
> versions of g++ produce a nice warning message when you try to return
> an address of a local variable (even without any additional options).
> I guess other C++ compilers are smart enough to do the same, so it's
> not that bad.

Please refer to the first thing I said in my response.  I guess you
proved it correct.  :)  I basically use C++ when I'm absolutely forced
to and never at any other time, so I'll take your word for it.


> On the other hand it is true that the whole scenario can be made more
> complex up to the point where the compiler will not catch the problem,
> but will have to accept it, so it's not perfect either.
>
> Note that Ada programmers also have 'Unrestricted_Access (GNAT) and
> 'Unchecked_Access to cheat around the rules.

Yes, but Ada programmers are aware of the danger and understand why
the rules are there; and they won't use 'Unchecked_Access unless it's
absolutely necessary and they know there won't be any dangling pointer
problems.

Note that "Ada programmer" is not a synonym for "programmer who uses
Ada" here.  I'm sure there are plenty of programmers who use Ada but
think like C/C++ programmers.  Those programmers would see the error
message that says 'Access is illegal because of the accessibility
rules, and figure they can solve the problem simply by changing it to
'Unchecked_Access".  Unfortunately, I've seen that sort of Ada code---
quite frustrating.

                        -- Adam




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Pointers explained?
  2007-07-30 21:23     ` Maciej Sobczak
  2007-07-30 22:36       ` Adam Beneschan
@ 2007-07-31  1:15       ` Anh Vo
  1 sibling, 0 replies; 20+ messages in thread
From: Anh Vo @ 2007-07-31  1:15 UTC (permalink / raw)


On Jul 30, 2:23 pm, Maciej Sobczak <see.my.homep...@gmail.com> wrote:
> On 30 Lip, 21:36, Adam Beneschan <a...@irvine.com> wrote:
[...]
>
> Note that Ada programmers also have 'Unrestricted_Access (GNAT) and
> 'Unchecked_Access to cheat around the rules.
>

I do not think they are used to cheat around the rules at all. They
are there, by design, for the experts who know what they are doing.
However, most of Ada software engineers including me are not experts
who make more mistakes than others. Therefore, these features are not
the default ones.

On the opposite, these features are the default ones in C/C++ because
C/C++ assumes that all C/C++ software engineers are experts who know
what they are doing including biting their tongs. Unfortunately, it is
not quite true. Furthermore, even the experts can not immune to making
mistakes due to tireness, after 5:00 PM synchrome,...

AV




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Pointers explained?
  2007-07-30 22:36       ` Adam Beneschan
@ 2007-07-31  7:33         ` Dmitry A. Kazakov
  0 siblings, 0 replies; 20+ messages in thread
From: Dmitry A. Kazakov @ 2007-07-31  7:33 UTC (permalink / raw)


On Mon, 30 Jul 2007 15:36:02 -0700, Adam Beneschan wrote:

> Those programmers would see the error
> message that says 'Access is illegal because of the accessibility
> rules, and figure they can solve the problem simply by changing it to
> 'Unchecked_Access".  Unfortunately, I've seen that sort of Ada code---
> quite frustrating.

I disagree. Unchecked_Access is required too often to be discarded as just
a problem of lazy programmers. Sometimes the rules are too strict,
sometimes pointers are forced where objects should be used instead (like in
function parameters or in discriminants). To me it is an indicator of some
language design problems.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Pointers explained?
  2007-07-30 17:53 Pointers explained? shaunpatterson
  2007-07-30 17:56 ` shaunpatterson
  2007-07-30 20:11 ` Dmitry A. Kazakov
@ 2007-07-31  8:28 ` Martin Krischik
  2 siblings, 0 replies; 20+ messages in thread
From: Martin Krischik @ 2007-07-31  8:28 UTC (permalink / raw)


Am 30.07.2007, 19:53 Uhr, schrieb <shaunpatterson@gmail.com>:

>    I'm still relatively new to Ada -- coming from a strong C++
> background.  Some of this may seem stupid - and feel free to point it
> out to me.  I am using Ada 95 - GNAT Pro 3.16a1

http://en.wikibooks.org/wiki/Ada_Programming/Object_Orientation

has quite a bit of comparison to between C++ and Ada OO. Also interesting  
is:

http://en.wikibooks.org/wiki/Ada_Programming/Types/access

Have fun.

Martin



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Pointers explained?
  2007-07-30 17:56 ` shaunpatterson
                     ` (3 preceding siblings ...)
  2007-07-30 21:31   ` Jeffrey R. Carter
@ 2007-07-31 17:21   ` Simon Wright
  2007-07-31 18:06     ` Dmitry A. Kazakov
  4 siblings, 1 reply; 20+ messages in thread
From: Simon Wright @ 2007-07-31 17:21 UTC (permalink / raw)


shaunpatterson@gmail.com writes:

> type Message is abstract tagged null record;
> type Message_Class is access all Message'Class;
>
>
> then all other messages are derived from this.
>
>
> Now from my factory create method, I'm returning a Message_Class.
> This message_class is stored in another record to be handled again
> later:
>
>
> type CallbackEvent is
> record
>      msg : Message_Class;
>      ...
> end record;

Could you have an abstract operation dispatching on Message?

   procedure Handler (M : Message);

(of course you could add extra parameters as required to correspond to
your ... in CallbackEvent).

> Now my basic problem -- or not really a problem -- is that to create
> the Message_Class I have to use "new" and allocate and deallocate
> memory.

Not clear why this is a problem? On the 1.5 GHz Powerbook it takes
about 1 us to allocate, 1.5 us to deallocate 32 bytes.

If you are worried about losing track of allocations and running out
of storage, you could consider some sort of smart pointer scheme (the
Booch Components at http://booch95.sf.net have such a thing, or you
could roll your own).

Or you could adopt a "procedural" approach -- individual posters of
events do the 'new', but the event queue manager does the
deallocation.

I don't believe you can have a queue of messages like this without
'new'. If you just want to handle the messages in the context where
they're created, you may be able to swing it.



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Pointers explained?
  2007-07-31 17:21   ` Simon Wright
@ 2007-07-31 18:06     ` Dmitry A. Kazakov
  2007-07-31 22:38       ` shaunpatterson
  0 siblings, 1 reply; 20+ messages in thread
From: Dmitry A. Kazakov @ 2007-07-31 18:06 UTC (permalink / raw)


On Tue, 31 Jul 2007 18:21:30 +0100, Simon Wright wrote:

> I don't believe you can have a queue of messages like this without
> 'new'. If you just want to handle the messages in the context where
> they're created, you may be able to swing it.

Not necessary. There exist important cases:

1. When messages handling is synchronous, i.e. when the publisher waits for
message processing completion, then no heap is needed. It is just Ada's
rendezvous model. 

2. When the number of messages of same type is limited. That is when you
want to ensure QoS. Then you would probably block at emission point until
a pending message of same type is underway or else coalesce when processing
is not yet started. Otherwise you could quickly chock the system.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Pointers explained?
  2007-07-31 18:06     ` Dmitry A. Kazakov
@ 2007-07-31 22:38       ` shaunpatterson
  2007-08-01  7:53         ` Martin Krischik
                           ` (2 more replies)
  0 siblings, 3 replies; 20+ messages in thread
From: shaunpatterson @ 2007-07-31 22:38 UTC (permalink / raw)


Thanks for all the help.

I figured I had to use "new" eventually.  In C++, allocating memory
doesn't
seem to bother me - mainly because I'm confident with the language and
feel like I can control the program flow better.  However, in Ada,
that whole
"Unchecked_Deallocation" bothers me... although I seem to have used it
effectively.
The "Unchecked" part just makes it seem like Ada provides a better
way...
Are there any version of GNAT that support garbage collection?  I'm
working
with 10-15 year old government system.  Perhaps I can convince them to
upgrade
to an Ada compiler with a garbage collector

--
Shaun




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Pointers explained?
  2007-07-31 22:38       ` shaunpatterson
@ 2007-08-01  7:53         ` Martin Krischik
  2007-08-01  8:21         ` Dmitry A. Kazakov
  2007-08-10 19:52         ` Simon Wright
  2 siblings, 0 replies; 20+ messages in thread
From: Martin Krischik @ 2007-08-01  7:53 UTC (permalink / raw)


 shaunpatterson@gmail.com wrote:

> Thanks for all the help.
> 
> I figured I had to use "new" eventually.  In C++, allocating memory
> doesn't
> seem to bother me - mainly because I'm confident with the language and
> feel like I can control the program flow better.  However, in Ada,
> that whole
> "Unchecked_Deallocation" bothers me... although I seem to have used it
> effectively.
> The "Unchecked" part just makes it seem like Ada provides a better
> way...
> Are there any version of GNAT that support garbage collection?  I'm
> working
> with 10-15 year old government system.  Perhaps I can convince them to
> upgrade
> to an Ada compiler with a garbage collector

Garbage Collection is indeed added to GNAT. AFAIK it is in an early stage
and will take some time until finished.

However, you are a GNAT/PRO customer so you will get premium support from
AdaCore - so go for it. Make your live easy ;-) .

Martin
-- 
mailto://krischik@users.sourceforge.net
Ada programming at: http://ada.krischik.com



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Pointers explained?
  2007-07-31 22:38       ` shaunpatterson
  2007-08-01  7:53         ` Martin Krischik
@ 2007-08-01  8:21         ` Dmitry A. Kazakov
  2007-08-10 19:52         ` Simon Wright
  2 siblings, 0 replies; 20+ messages in thread
From: Dmitry A. Kazakov @ 2007-08-01  8:21 UTC (permalink / raw)


On Tue, 31 Jul 2007 22:38:24 -0000, shaunpatterson@gmail.com wrote:

> Are there any version of GNAT that support garbage collection?  I'm
> working with 10-15 year old government system.  Perhaps I can convince them to
> upgrade to an Ada compiler with a garbage collector

AFAIK there exists implementations of Boehm garbage collector for Ada.
Maybe others could provide links. You could also use reference counting
collection (smart pointers), which is more predictable than other
strategies. There also exist many implementations of.

My personal attitude is that GC is in general a bad idea and especially for
a messaging system. It can be justified only when it is *proven* that there
is no other way to manage collection.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Pointers explained?
  2007-07-31 22:38       ` shaunpatterson
  2007-08-01  7:53         ` Martin Krischik
  2007-08-01  8:21         ` Dmitry A. Kazakov
@ 2007-08-10 19:52         ` Simon Wright
  2 siblings, 0 replies; 20+ messages in thread
From: Simon Wright @ 2007-08-10 19:52 UTC (permalink / raw)


shaunpatterson@gmail.com writes:

> Are there any version of GNAT that support garbage collection?  I'm
> working with 10-15 year old government system.

3.16a1 isn't _that_ old! About 2002, I think ..



^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2007-08-10 19:52 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-07-30 17:53 Pointers explained? shaunpatterson
2007-07-30 17:56 ` shaunpatterson
2007-07-30 19:04   ` Ed Falis
2007-07-30 19:05   ` Ludovic Brenta
2007-07-30 19:36   ` Adam Beneschan
2007-07-30 21:23     ` Maciej Sobczak
2007-07-30 22:36       ` Adam Beneschan
2007-07-31  7:33         ` Dmitry A. Kazakov
2007-07-31  1:15       ` Anh Vo
2007-07-30 22:20     ` Adam Beneschan
2007-07-30 21:31   ` Jeffrey R. Carter
2007-07-31 17:21   ` Simon Wright
2007-07-31 18:06     ` Dmitry A. Kazakov
2007-07-31 22:38       ` shaunpatterson
2007-08-01  7:53         ` Martin Krischik
2007-08-01  8:21         ` Dmitry A. Kazakov
2007-08-10 19:52         ` Simon Wright
2007-07-30 20:11 ` Dmitry A. Kazakov
2007-07-31  8:28 ` Martin Krischik
  -- strict thread matches above, loose matches on Subject: below --
2007-07-30 17:53 shaunpatterson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox