* Static variables? @ 1997-03-17 0:00 Viqar Abbasi 1997-03-17 0:00 ` Robert Dewar 1997-03-18 0:00 ` Jon S Anthony 0 siblings, 2 replies; 10+ messages in thread From: Viqar Abbasi @ 1997-03-17 0:00 UTC (permalink / raw) Hello, Is there a way to declare local variables in ADA subprograms to be STATIC? That is, they retain the value that they had when the subprogram was last exited. Thanks for the insights, Viqar ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Static variables? 1997-03-17 0:00 Static variables? Viqar Abbasi @ 1997-03-17 0:00 ` Robert Dewar 1997-03-18 0:00 ` nasser 1997-03-18 0:00 ` Jon S Anthony 1 sibling, 1 reply; 10+ messages in thread From: Robert Dewar @ 1997-03-17 0:00 UTC (permalink / raw) Viqar asks <<Is there a way to declare local variables in ADA subprograms to be STATIC? That is, they retain the value that they had when the subprogram was last exited.>> This seems to be one of the most F asked FAQ's The answer is to declare variables in the package body. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Static variables? 1997-03-17 0:00 ` Robert Dewar @ 1997-03-18 0:00 ` nasser 0 siblings, 0 replies; 10+ messages in thread From: nasser @ 1997-03-18 0:00 UTC (permalink / raw) as Dr Dewar mentioned, package variables retain their values from the time the package becomes avaliable to the time the package life ends (usually the end of the program , but not always the case, example, if the package is declared inside a block or procedure), may be a picture will help: package A interface +---------------------+ | i: integer; -----------> retain its value also client <=======> | procedure foo; | | ....... | +---------------------+ ............................................. package A body +---------------------+ |j: integer; --------------> these variables retain | | their values | procedure foo is | | n: integer; ------------> variables here are auto | begin | variables, new copies are | .... | created each time foo is called | end foo; | | | | begin | | .... ----------------> this code execute once when | end A; | package is first elaborated. | | use this code to init package +---------------------+ variables. you can think of variables declared in the package interface as static puplic in C++ class terminolgy, and variables declared in the body of the package but outside the functions and procedure of the package body as static private in C++. offcourse it is a good idea to try to avoid using variables in the interface part of the package. nasser ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Static variables? 1997-03-17 0:00 Static variables? Viqar Abbasi 1997-03-17 0:00 ` Robert Dewar @ 1997-03-18 0:00 ` Jon S Anthony 1997-03-18 0:00 ` Samuel Tardieu 1997-03-19 0:00 ` Robert Dewar 1 sibling, 2 replies; 10+ messages in thread From: Jon S Anthony @ 1997-03-18 0:00 UTC (permalink / raw) In article <332D71FF.4773@cae.ca> Viqar Abbasi <viqar@cae.ca> writes: > Is there a way to declare local variables in ADA subprograms to be > STATIC? That is, they retain the value that they had when the > subprogram was last exited. This may be in the FAQ (see: www.adahome.com for the FAQ). Just put the variable at the same or lower scope than the subprogram that is to use it. Typically this is at package level. Ex.1: procedure P is V : Some_Variable_Type ... procedure Sub_P is ...-- V works as you wish for all invocation of Sub_P end Sub_P; ... end P; Ex.2: package P is V: Some_Variable_Type .... procedure P1 ... procedure P2 ... ... -- V works as you wish for all invocations of any Px here -- (also for any subprograms in the body of P and any child unit -- of P or, for that matter, any importer of P (with P...) end P; /Jon -- Jon Anthony Organon Motives, Inc. Belmont, MA 02178 617.484.3383 jsa@organon.com ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Static variables? 1997-03-18 0:00 ` Jon S Anthony @ 1997-03-18 0:00 ` Samuel Tardieu 1997-03-18 0:00 ` Tom Moran 1997-03-19 0:00 ` Robert Dewar 1 sibling, 1 reply; 10+ messages in thread From: Samuel Tardieu @ 1997-03-18 0:00 UTC (permalink / raw) >>>>> "Jon" == Jon S Anthony <jsa@alexandria> writes: Jon> In article <332D71FF.4773@cae.ca> Viqar Abbasi <viqar@cae.ca> Jon> writes: >> Is there a way to declare local variables in ADA subprograms to be >> STATIC? That is, they retain the value that they had when the >> subprogram was last exited. Jon> Just put the variable at the same or lower scope than the Jon> subprogram that is to use it. Typically this is at package Jon> level. This is of course the way to do it, but your answer corresponds to the case of a C toplevel static variable, not to the case of a C static variable located in a function. In the first case, your variable may be accessed by several subprograms, in the second one, it can only be accessed by *one* C function. This is not possible in Ada to have the equivalent of a C static variable located in a function, you have to put it at the module (package) level, let's say in the package body as Jon said. Sam -- Samuel Tardieu -- sam@ada.eu.org ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Static variables? 1997-03-18 0:00 ` Samuel Tardieu @ 1997-03-18 0:00 ` Tom Moran 0 siblings, 0 replies; 10+ messages in thread From: Tom Moran @ 1997-03-18 0:00 UTC (permalink / raw) If the variable should really be private to a single function, like a C static variable inside a function, how about: package lots_of_things is ... procedure p_with_state; ... end lots_of_things; package body lots_of_things is ... package state_p is procedure actual_p; end state_p; package body state_p is static_variable : integer := 0; procedure actual_p is ... -- has access to static_variable end state_p; ... procedure p_with_state is begin state_p.actual_p; -- call the real p procedure to do its thing end p_with_state; ... ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Static variables? 1997-03-18 0:00 ` Jon S Anthony 1997-03-18 0:00 ` Samuel Tardieu @ 1997-03-19 0:00 ` Robert Dewar 1997-03-25 0:00 ` Richard A. O'Keefe 1 sibling, 1 reply; 10+ messages in thread From: Robert Dewar @ 1997-03-19 0:00 UTC (permalink / raw) Jon said (answering question about static variables) package P is V: Some_Variable_Type .... procedure P1; Robert notes: This is not good advice, or at least does not answer the question. The idea of static variables (e.g. in Algol60 or C) is to create a variable that can only be referenced by the procedure, but which retains its value from call to call. You certainly do not map such a facility by putting variables in the package spec, which can be accessed by clients. A much closer approximation is to place the variable in the package body, where it cannot be seen by a client. Note that in Ada 95, the variable definition can go right next to the body (this is one of the good arguments for dropping the annoying basic-later ordering restrictions on declarations in Ada 83). The closest approximation is package body P is package P1_Package is procedure P1_Proc; end P1_Package; package body P1_Package is V : Some_Variable_Type ... procedure P1_Proc; end P1_Package; procedure P1 renames P1_Package.P1_Proc; ... and now the variable V is not directly visible even in the body of package P, but for most purposes this is probably overkill, since simple naming conventions and discipline can presumably be trusted at the single package level, it is clients who must be stopped from fiddling with the variable directly. Note that the whole idea of static variables is fundamentally inconsistent with task safety, since the variable V here is almost certainly going to be a shared variable which is in danger of generating erroneous behavior (RM 9.10(11-15)). Possible solutions are Make V a protected object (i.e. of a protected type), and get and set its value with protected calls. This is likely to be very expensive. On bare board implementations, protected types can be made quite efficient, but when operating over an operating system, protected object semantics are heavy, and protected calls are likely to result in multiple kernel calls. Make P1 a generic, with the understanding that separate tasks should instantiate separate versions, each of which will have its own variable V. Give the caller a handle to V, which is then passed as a parameter, with a constructor, and the understanding that different tasks do not share the same handle (see Ada.Numerics.Discrete_Random for an example of this approach). Make V atomic, so that updates are task safe. Solution 1 (the protected object) will always work, but might be expensive. Solutions 2-3 are appropriate only if it is OK to have multiple V's (the random number case is an archetype of this case). SOlution 4 works only if the operations on V are limited to simple loads and stores (e.g. a First_Time_In Boolean would work, although you have to be prepared for race conditoins, so that two tasks could both think it was the first time in. If you need to do x := x + 1, then the atomic solution creates additional race conditions. Note that in solution 1, to avoid race conditions, you need to take operations like x := x + 1 inside the protected type. Making things task safe is not easy at all if you have state of this kind that must be retained from call to call and if you want efficiency. Let's consider for example the issue of a memoized Ackerman function. we really do not want a protected call on every call to Ackerman, since in typical Unix systems, these calls can be distressingly inefficient, and one can find that protected calls are comparable to task switching in overhead. This is a fundamental property of the way that protected objects were designed (e.g. to respect ceiling priorities accurately) and it was known during the design that the choices made would result in a relatively heavy locking mechanism when working over an operating system (e.g. a protected call cannot use a simple test-and-set lock, since this would cause possible priority inversions in some unlikely worst case scenarios). Back to Ackerman. One approach is to have two (two-D) memory arrays, one has booleans showing if a value is set, the other has the values. Let's assume that the values are large composites representing extended precision values, too big to be atomic. If a boolean is set, we know we can access the value, without a lock, and all is safe. If a boolean is not set, then we take a lock (i.e. we do this in a protected object) and set the value in place. This approach means that at least we only pay the price of a lock on the set, not on every access. Of course if the values to be stored are small enough to be atomic, then we can just store them and retrieve them directly (this is a case of solution 4 above). Code that casually ignores task safety is often very hard to fix up so that later on it is task safe, without introducing lots of inefficient locks. This is the problem that is often faced in making C runtime libraries safe, although in C the problem is made much worse by not having nested functions, so that one ends up using static variables gratuitously, which in Ada or Pascal would be up level (task safe) references. And that by the way is a reminder to C programmers writing in Ada. Do NOT use global variables gratuitously. For example, suppose you are writing a scanning package in Ada, where internally there is a scan pointer variable that is only needed for one outer level client call, but the operation is complex, and there are many internal procedure calls in the package body. There are three basic approaches: 1. Pass the scan pointer around everywhere as an in-out parameter, this can add a lot of junk to the code. 2. Use a static variable which is set on entry, and then referenced by the various procedures (in Ada, the static variable is a package body variable) 3. Make the variable be a local variable of the outer procedure and nest all other procedures within this procedure. Assuming you are not explicitly using tasking, approach 3 is task safe, but may not easily occur to C programmers writing in Ada, because they are not used to writing nested procedures (note the phrasing of the original question -- when anyone asks "How can I do X in language Y", where X is a technical term from some other language, alarm bells should go off, because it is likely that someone is trying to port an unnatural design. In other words, the best answer to the question "How do I get a static variable in Ada" is often "Just say NO to static variables". In general, library level variables in package specs or package bodies raise task safety issues. A reasonable protocol in an environment where task safety has to be considered is that EVERY such variable should be annotated with comments discussing its task safety. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Static variables? 1997-03-19 0:00 ` Robert Dewar @ 1997-03-25 0:00 ` Richard A. O'Keefe 1997-03-25 0:00 ` Larry Kilgallen 0 siblings, 1 reply; 10+ messages in thread From: Richard A. O'Keefe @ 1997-03-25 0:00 UTC (permalink / raw) dewar@merv.cs.nyu.edu (Robert Dewar) writes: >And that by the way is a reminder to C programmers writing in Ada. Do NOT >use global variables gratuitously. ... >Assuming you are not explicitly using tasking, approach 3 is task safe, but >may not easily occur to C programmers writing in Ada, because they are not >used to writing nested procedures (note the phrasing of the original >question -- when anyone asks "How can I do X in language Y", where X is >a technical term from some other language, alarm bells should go off, because >it is likely that someone is trying to port an unnatural design. One of the things that has me bewildered and worried is the growing number of concurrent languages _without_ nested subprograms. Java is an obvious example. Another recent example is Limbo. The Limbo IPC mechanism is tranmitting messages over named typed channels. All processes run in the same address space. There are no nested procedures. Presto no-chango: it is the _programmer's_ job to ensure that variables are not operated on in multiple threads. Ada looks better and better every day. -- Will maintain COBOL for money. Richard A. O'Keefe; http://www.cs.rmit.edu.au/%7Eok; RMIT Comp.Sci. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Static variables? 1997-03-25 0:00 ` Richard A. O'Keefe @ 1997-03-25 0:00 ` Larry Kilgallen 1997-03-27 0:00 ` Robert Dewar 0 siblings, 1 reply; 10+ messages in thread From: Larry Kilgallen @ 1997-03-25 0:00 UTC (permalink / raw) In article <5h8786$oml$1@goanna.cs.rmit.edu.au>, ok@goanna.cs.rmit.edu.au (Richard A. O'Keefe) writes: > One of the things that has me bewildered and worried is the growing number > of concurrent languages _without_ nested subprograms. Java is an obvious > example. Another recent example is Limbo. The Limbo IPC mechanism is > tranmitting messages over named typed channels. All processes run in the > same address space. There are no nested procedures. Presto no-chango: > it is the _programmer's_ job to ensure that variables are not operated on > in multiple threads. Ada looks better and better every day. Is the quality being sought just nested subprograms, or is uplevel addressing actually required ? There are languages which have nested subprograms without uplevel addressing. I suppose one can simulate uplevel addressing with lots of in-out parameters, but for me that moves away from readability. Larry Kilgallen ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Static variables? 1997-03-25 0:00 ` Larry Kilgallen @ 1997-03-27 0:00 ` Robert Dewar 0 siblings, 0 replies; 10+ messages in thread From: Robert Dewar @ 1997-03-27 0:00 UTC (permalink / raw) Larry said <<Is the quality being sought just nested subprograms, or is uplevel addressing actually required ? There are languages which have nested subprograms without uplevel addressing. I suppose one can simulate uplevel addressing with lots of in-out parameters, but for me that moves away from readability.>> Absolutely the issue is uplevel addressing. nested procedures without uplevel addressing are a rather small feature, they provide a bit of namespace protection, which can be provided by other means. The context of the original remark was to do with threaded programs, where nested procedures and uplevel addressing are an enormous help in writing thread safe code. Have a look back at the start of the thread, and reread my comments on the structure of printf for an example. ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~1997-03-27 0:00 UTC | newest] Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 1997-03-17 0:00 Static variables? Viqar Abbasi 1997-03-17 0:00 ` Robert Dewar 1997-03-18 0:00 ` nasser 1997-03-18 0:00 ` Jon S Anthony 1997-03-18 0:00 ` Samuel Tardieu 1997-03-18 0:00 ` Tom Moran 1997-03-19 0:00 ` Robert Dewar 1997-03-25 0:00 ` Richard A. O'Keefe 1997-03-25 0:00 ` Larry Kilgallen 1997-03-27 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