comp.lang.ada
 help / color / mirror / Atom feed
* Global Varibles!!
@ 1997-02-19  0:00 Richard Pearce
  1997-02-20  0:00 ` Matthew Heaney
  0 siblings, 1 reply; 6+ messages in thread
From: Richard Pearce @ 1997-02-19  0:00 UTC (permalink / raw)



Hello!!

I've jsut written a procedure which sets a value to a varible, and I
can't seen to keep the value for use in another procedure.  I know it
has to be global but I don't know how to set a variable as global in
ada95.

Can anyone please help me by telling me how to set a varible as global.

Many thanks.




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

* Re: Global Varibles!!
  1997-02-19  0:00 Global Varibles!! Richard Pearce
@ 1997-02-20  0:00 ` Matthew Heaney
  1997-02-21  0:00   ` Norman H. Cohen
  0 siblings, 1 reply; 6+ messages in thread
From: Matthew Heaney @ 1997-02-20  0:00 UTC (permalink / raw)



In article <330B6914.22CD@hotmail.com>, rp71@hotmail.com wrote:

I've jsut written a procedure which sets a value to a varible, and I
>can't seen to keep the value for use in another procedure.  I know it
>has to be global but I don't know how to set a variable as global in
>ada95.
>
>Can anyone please help me by telling me how to set a varible as global.

I will tell you want to do, but with a warning: you must be careful with
global variables.

If you wish to save the state of a variable across subprogram invokations,
then the variable must be declared in a static scope, which means in a
package spec or body.  For example,

package Global is

   X : Integer;

end;

with Global;
procedure Set_X is
begin
   Global.X := 1;
end;


with Global;
procedure Get_X is
begin
   ... := Global.X;
end;


However, using a package to declare global variables shared by subprograms
is a very old style of software architecture.  You see it when Fortran
programmers first program in Ada: they have a global mindset.

Realize that this creates danderous coupling amoung pieces of the system. 
If you change Global.X, then how do you know what will break because of the
change?

Better is to encapsulate the data, and expose its representation to only a
few subprograms.  This is better known as object-oriented programming: the
data is described not in terms of its representation, but rather in terms
of the things you can do to it.

For example, 

   The_Stack : Stack;
begin
   Push (5, On => The_Stack);
...
   The_Value := Top (The_Stack);
   Pop (The_Stack);

The representation of the stack is hidden, and clients call primitive
operations to manipulate stack instances.

Your original problem was needing a static scope for global variables. 
While it's true we don't generally use global data anymore, we still have
global entities in the guise of "well-known" objects.  These are objects
that are known across subsystem boundaries.

We want to minimize coupling across subsystem boundaries, but of course we
can't completely eliminate it.  Subsystems have to have some minimum amount
of coupling; otherwise, they'd wouldn't be part of the same system.

For more information about this important topic, see visit the Singleton
pattern, at the nascent SIGAda Patterns Working Group home page.

<http://www.acm.org/sigada/wg/patterns/>
<http://www.acm.org/sigada/wg/patterns/ada_singleton.html>

-matt

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
<mailto:matthew_heaney@acm.org>
(818) 985-1271




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

* Re: Global Varibles!!
  1997-02-20  0:00 ` Matthew Heaney
@ 1997-02-21  0:00   ` Norman H. Cohen
  1997-02-23  0:00     ` Robert Dewar
  0 siblings, 1 reply; 6+ messages in thread
From: Norman H. Cohen @ 1997-02-21  0:00 UTC (permalink / raw)



Matthew Heaney wrote:

> If you wish to save the state of a variable across subprogram invokations,
> then the variable must be declared in a static scope, which means in a
> package spec or body.  For example,
> 
> package Global is
> 
>    X : Integer;
> 
> end;
> 
> with Global;
> procedure Set_X is
> begin
>    Global.X := 1;
> end;
> 
> with Global;
> procedure Get_X is
> begin
>    ... := Global.X;
> end;
> 
> However, using a package to declare global variables shared by subprograms
> is a very old style of software architecture.  You see it when Fortran
> programmers first program in Ada: they have a global mindset.
> 
> Realize that this creates danderous coupling amoung pieces of the system.
> If you change Global.X, then how do you know what will break because of the
> change?
> 
> Better is to encapsulate the data, and expose its representation to only a
> few subprograms.  
...

In other words, if Set_X and Get_X are the only subprograms that will be
using Global.X, enclose the subprogram in a package and hide the
variable in the package body:

package X_State is
   procedure Set_X;
   procedure Get_X;
end X_State;

package body X_State is
   X: Integer;
   procedure Set_X is 
   begin
      X := 1;
   end Set_X;
   procedure Get_X is
   begin
      ...
   end Get_X;
end X_State;

It's quite reasonable to write a package that provides only a single
subprogram, but encapsulates a persistent variable:

package Serial_Numbers is
   procedure Get_Next (Number: out Natural);
end Serial_Numbers;

package body Serial_Numbers is
   Next: Natural := 0:
   procedure Get_Next (Number: out Natural) is
   begin
      Number := Next;
      if Number = Natural'Last then
         Number := 0;
      else
         Number := Number + 1;
      end if;
   end Get_Next;
end Serial_Numbers;

-- 
Norman H. Cohen
mailto:ncohen@watson.ibm.com
http://www.research.ibm.com/people/n/ncohen




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

* Re: Global Varibles!!
  1997-02-21  0:00   ` Norman H. Cohen
@ 1997-02-23  0:00     ` Robert Dewar
  1997-02-25  0:00       ` Norman H. Cohen
  0 siblings, 1 reply; 6+ messages in thread
From: Robert Dewar @ 1997-02-23  0:00 UTC (permalink / raw)



Norman said

<< package Serial_Numbers is
   procedure Get_Next (Number: out Natural);
end Serial_Numbers;

package body Serial_Numbers is
   Next: Natural := 0:
   procedure Get_Next (Number: out Natural) is
   begin
      Number := Next;
      if Number = Natural'Last then
         Number := 0;
      else
         Number := Number + 1;
      end if;
   end Get_Next;
end Serial_Numbers;
>>

Of course in general this kind of hiding is quite appropriate. Note however
a danger, here we have an unexposed global variable that is not protected
against task switches. If the global is in the spec, you are at least
clearly publishing a warning that you have an unprotected global.





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

* Re: Global Varibles!!
  1997-02-23  0:00     ` Robert Dewar
@ 1997-02-25  0:00       ` Norman H. Cohen
  1997-02-25  0:00         ` Robert Dewar
  0 siblings, 1 reply; 6+ messages in thread
From: Norman H. Cohen @ 1997-02-25  0:00 UTC (permalink / raw)



Robert Dewar wrote:
> 
> Norman said
> 
> << package Serial_Numbers is
>    procedure Get_Next (Number: out Natural);
> end Serial_Numbers;
> 
> package body Serial_Numbers is
>    Next: Natural := 0:
>    procedure Get_Next (Number: out Natural) is
>    begin
>       Number := Next;
>       if Number = Natural'Last then
>          Number := 0;
>       else
>          Number := Number + 1;
>       end if;
>    end Get_Next;
> end Serial_Numbers;
> >>

Oops!  What I meant to write, of course, is:

   if Next = Natural'Last then
      Next := 0;
   else
      Next := Next + 1;
   end if;

> Of course in general this kind of hiding is quite appropriate. Note however
> a danger, here we have an unexposed global variable that is not protected
> against task switches. If the global is in the spec, you are at least
> clearly publishing a warning that you have an unprotected global.

Robert correctly points out that this version of Serial_Numbers is not
task-safe.  If the intent is that the package be task-safe, it can be
made so in any of a number of ways (at the cost of performance and/or
simplicity of the interface), including:

1. using a protected object in the package body

2. replacing Next by a per-task attribute (see "The Package
Task_Attributes", RM C.7.2)

3. replacing the global variable with a parameter carrying private
per-task state, which might be considered overkill in the Serial_Numbers
case, but is essentially the role that type Generator plays in the
predefined random-numbers packages (RM A.5.2).

If the intent is that the package not be task-safe, this should indeed
be documented, but I would prefer to do this with a comment rather then
by exposing the global variable in the package spec.  

Alternatively, if approach #1 is used to make the package task safe,
this could be documented by declaring the protected object in the
package spec rather than declaring a procedure in the spec, declaring
the protected object in the body, and implementing the visible procedure
with a call on a corresponding protected procedure.

This gives rise to the following question:  In the absence of any
documentation to the contrary, should a package be assumed to be
task-safe or task-unsafe?  A purist view is that all packages should be
assumed by default to be task-safe, and that the author of a task-unsafe
package should document the fact that the package is not task-safe.  In
reality, many programmers implicitly regard a single-task program as the
"normal" case and a multitask program as an exotic special case.

-- 
Norman H. Cohen
mailto:ncohen@watson.ibm.com
http://www.research.ibm.com/people/n/ncohen




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

* Re: Global Varibles!!
  1997-02-25  0:00       ` Norman H. Cohen
@ 1997-02-25  0:00         ` Robert Dewar
  0 siblings, 0 replies; 6+ messages in thread
From: Robert Dewar @ 1997-02-25  0:00 UTC (permalink / raw)



Norman said

<<This gives rise to the following question:  In the absence of any
documentation to the contrary, should a package be assumed to be
task-safe or task-unsafe?  A purist view is that all packages should be
assumed by default to be task-safe, and that the author of a task-unsafe
package should document the fact that the package is not task-safe.  In
reality, many programmers implicitly regard a single-task program as the
"normal" case and a multitask program as an exotic special case.>>

Since Ada.Text_IO is clearly unsafe (it has naked global variables in
the spec), it seems reasonable to assume task-unsafe, but there is some
language in the RM that implies that the standard packages should be safe.





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

end of thread, other threads:[~1997-02-25  0:00 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1997-02-19  0:00 Global Varibles!! Richard Pearce
1997-02-20  0:00 ` Matthew Heaney
1997-02-21  0:00   ` Norman H. Cohen
1997-02-23  0:00     ` Robert Dewar
1997-02-25  0:00       ` Norman H. Cohen
1997-02-25  0:00         ` Robert Dewar

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