* Pointer to instance of indefinite array? @ 2014-08-13 2:07 NiGHTS 2014-08-13 2:09 ` Jeffrey Carter 2014-08-13 2:29 ` Shark8 0 siblings, 2 replies; 15+ messages in thread From: NiGHTS @ 2014-08-13 2:07 UTC (permalink / raw) Suppose I have a package like this... package Test_Package is type Element is record ID_1 : Positive; ID_2 : Positive; end record; type Element_Array is array (Positive range <>) of Element; type Element_Array_Ptr is access Element_Array; procedure Do_Something_With_Array ( In_Array : in Element_Array_Ptr ); end Test_Package; In this situation I have an array of "Element" records with an unknown number of elements. The number of elements are to be defined by the user of this package and passed as a pointer to the procedure "Do_Something_With_Array". So a simple implementation would be something like this... with Test_Package; use Test_Package; procedure main is Test_Array : aliased Element_Array (1 .. 20); begin -- Initialize the array, then call this function... Do_Something_With_Array (In_Array => Test_Array'Access); end main; So this does not compile and with countless errors no matter what configuration I try. I have a feeling my approach is fundamentally wrong. Essentially I am trying to pass a constrained array to a package accepting an array of any length, both of the same element type. I would parse the contents of this array using "for in" or 'First -> 'Last or 'Range. What is the best way to achieve this goal without using new / free? ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Pointer to instance of indefinite array? 2014-08-13 2:07 Pointer to instance of indefinite array? NiGHTS @ 2014-08-13 2:09 ` Jeffrey Carter 2014-08-13 2:29 ` Shark8 1 sibling, 0 replies; 15+ messages in thread From: Jeffrey Carter @ 2014-08-13 2:09 UTC (permalink / raw) On 08/12/2014 07:07 PM, NiGHTS wrote: > > In this situation I have an array of "Element" records with an unknown number > of elements. The number of elements are to be defined by the user of this > package and passed as a pointer to the procedure "Do_Something_With_Array". Why are you using an access type? There is no need for it. > What is the best way to achieve this goal without using new / free? Think in Ada and get rid of the access type. -- Jeff Carter "That was the most fun I've ever had without laughing." Annie Hall 43 ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Pointer to instance of indefinite array? 2014-08-13 2:07 Pointer to instance of indefinite array? NiGHTS 2014-08-13 2:09 ` Jeffrey Carter @ 2014-08-13 2:29 ` Shark8 2014-08-13 3:06 ` NiGHTS 1 sibling, 1 reply; 15+ messages in thread From: Shark8 @ 2014-08-13 2:29 UTC (permalink / raw) On 12-Aug-14 20:07, NiGHTS wrote: > package Test_Package is > > type Element is > record > ID_1 : Positive; > ID_2 : Positive; > end record; > > type Element_Array is array (Positive range <>) of Element; > type Element_Array_Ptr is access Element_Array; > > procedure Do_Something_With_Array ( > In_Array : in Element_Array_Ptr > ); > > end Test_Package; What are you really trying to do? You can do everything you want in the example w/o touching access types: package Test_Package is type Element is record ID_1 : Positive; ID_2 : Positive; end record; type Element_Array is array (Positive range <>) of Element; procedure Do_Something_With_Array (In_Array : in Element_Array); end Test_Package; package body Test_Package is procedure Do_Something_With_Array (In_Array : in Element_Array) is begin for E of In_Array loop declare Key : String renames Positive'Image(E.ID_1); Value : String renames Positive'Image(E.ID_2); begin Ada.Text_IO.Put_Line( "Key:"&Key &ASCII.HT& "Value:"&Value &'.' ); end; end loop; end Do_Something_With_Array; end Test_Package; ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Pointer to instance of indefinite array? 2014-08-13 2:29 ` Shark8 @ 2014-08-13 3:06 ` NiGHTS 2014-08-13 4:28 ` Jeffrey Carter 2014-08-13 4:31 ` Per Sandberg 0 siblings, 2 replies; 15+ messages in thread From: NiGHTS @ 2014-08-13 3:06 UTC (permalink / raw) On Tuesday, August 12, 2014 10:29:04 PM UTC-4, Shark8 wrote: > On 12-Aug-14 20:07, NiGHTS wrote: > What are you really trying to do? You can do everything you want in the > example w/o touching access types: On Tuesday, August 12, 2014 10:09:37 PM UTC-4, Jeffrey Carter wrote: > Think in Ada and get rid of the access type. Hmm. You're right. It worked! Compiler must be changing it internally to a pointer though since it would be far too inefficient to copy the entire array. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Pointer to instance of indefinite array? 2014-08-13 3:06 ` NiGHTS @ 2014-08-13 4:28 ` Jeffrey Carter 2014-08-13 16:06 ` NiGHTS 2014-08-13 4:31 ` Per Sandberg 1 sibling, 1 reply; 15+ messages in thread From: Jeffrey Carter @ 2014-08-13 4:28 UTC (permalink / raw) On 08/12/2014 08:06 PM, NiGHTS wrote: > > Hmm. You're right. It worked! Compiler must be changing it internally to a > pointer though since it would be far too inefficient to copy the entire > array. The parameter-passing mechanism used by the compiler is generally not something we need to worry about. Having to explicitly pass a pointer to obtain by-reference semantics is a mark of low-level languages. It is not a good way to do almost anything. In a mid-level language, such as Pascal, one often specifies the parameter-passing mechanism, and the compiler uses that mechanism. This is pretty much what VAR (by reference) and non-VAR (by copy) parameters are in Pascal, though they're usually described in terms of whether or not changes to the formal parameter also change the actual. In a high-level language, such as Ada, one specifies how the subprogram uses the parameter (in, in out, and out modes) and the compiler uses that and the type being passed to determine the parameter-passing mechanism. -- Jeff Carter "That was the most fun I've ever had without laughing." Annie Hall 43 ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Pointer to instance of indefinite array? 2014-08-13 4:28 ` Jeffrey Carter @ 2014-08-13 16:06 ` NiGHTS 2014-08-13 17:43 ` Jeffrey Carter ` (2 more replies) 0 siblings, 3 replies; 15+ messages in thread From: NiGHTS @ 2014-08-13 16:06 UTC (permalink / raw) On Wednesday, August 13, 2014 12:28:14 AM UTC-4, Jeffrey Carter wrote: > On 08/12/2014 08:06 PM, NiGHTS wrote: > > > > > > Hmm. You're right. It worked! Compiler must be changing it internally to a > > > pointer though since it would be far too inefficient to copy the entire > > > array. > > > > The parameter-passing mechanism used by the compiler is generally not something > > we need to worry about. > > > > Having to explicitly pass a pointer to obtain by-reference semantics is a mark > > of low-level languages. It is not a good way to do almost anything. > > > > In a mid-level language, such as Pascal, one often specifies the > > parameter-passing mechanism, and the compiler uses that mechanism. This is > > pretty much what VAR (by reference) and non-VAR (by copy) parameters are in > > Pascal, though they're usually described in terms of whether or not changes to > > the formal parameter also change the actual. > > > > In a high-level language, such as Ada, one specifies how the subprogram uses the > > parameter (in, in out, and out modes) and the compiler uses that and the type > > being passed to determine the parameter-passing mechanism. > > > > -- > > Jeff Carter > > "That was the most fun I've ever had without laughing." > > Annie Hall > > 43 Is it possible to have a constrained array of indefinite arrays without using access? In my target program, the "Do_Something_With_Array" function is actually an interface to a FIFO queue where groups of indefinite arrays are temporarily buffered for use by another task. Of course this will be via an entry to a protected object but those details aside how can I construct a constrained array of indefinite arrays? ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Pointer to instance of indefinite array? 2014-08-13 16:06 ` NiGHTS @ 2014-08-13 17:43 ` Jeffrey Carter 2014-08-13 17:58 ` Shark8 2014-08-13 18:36 ` Dmitry A. Kazakov 2 siblings, 0 replies; 15+ messages in thread From: Jeffrey Carter @ 2014-08-13 17:43 UTC (permalink / raw) On 08/13/2014 09:06 AM, NiGHTS wrote: > > Is it possible to have a constrained array of indefinite arrays without using > access? In my target program, the "Do_Something_With_Array" function is > actually an interface to a FIFO queue where groups of indefinite arrays are > temporarily buffered for use by another task. Of course this will be via an > entry to a protected object but those details aside how can I construct a > constrained array of indefinite arrays? If I need something like that, I'll usually use an array of an unbounded-array data structure, which in Ada is found in Ada.Containers.Vectors. -- Jeff Carter "C++ is vast and dangerous, a sort of Mordor of programming languages." Jason R. Fruit 120 ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Pointer to instance of indefinite array? 2014-08-13 16:06 ` NiGHTS 2014-08-13 17:43 ` Jeffrey Carter @ 2014-08-13 17:58 ` Shark8 2014-08-13 18:36 ` Dmitry A. Kazakov 2 siblings, 0 replies; 15+ messages in thread From: Shark8 @ 2014-08-13 17:58 UTC (permalink / raw) On 13-Aug-14 10:06, NiGHTS wrote: > Of course this will be via an entry to a protected object but > those details aside how can I construct a constrained array > of indefinite arrays? For that you *do* need accesses, this is because the compiler needs to know the size of the elements. Of course this implementation detail can be hidden away from clients: Package Test_UCA is Type Positive_Array is Array (Positive Range <>) of Positive; Type Array_Array(Len : Positive) is Private; -- Obj's Entries should be used as follows: -- O.Test( P ); -- Saves P into J. -- ... -- O.Result_Length( Temp ); -- Gets the length of J. -- declare -- New_Array : Positive_Array(1..Temp); -- begin -- O.Result( New_Array ); -- Copies J into New_Array & clears J. -- --... (Whatever processing you need.) -- end; Protected type Obj(Len : Positive) is Entry Test ( P : Positive_Array ); Entry Result_Length ( Len : out Positive ); Entry Result ( R : out Positive_Array ); Private J : access Positive_Array; K : Array_Array(Len); End Obj; Private Type Internal_Array_Array is Array (Positive Range <>) of not null access Positive_Array; Type Array_Array(Len : Positive) is record Data : Internal_Array_Array(1..Len); end record; Default : Constant Internal_Array_Array:= ( 1..0 => New Positive_Array'(1,1) ); End Test_UCA; Package Body Test_UCA is Protected Body Obj is Entry Test ( P : Positive_Array ) when True is Begin J:= new Positive_Array'(P); End Test; Entry Result_Length ( Len : out Positive ) when J /= null is Begin Len:= J'Length; End Result_Length; Entry Result ( R : out Positive_Array ) when J /= null is Begin R:= J.All; J:= Null; End Result; End Obj; End Test_UCA; ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Pointer to instance of indefinite array? 2014-08-13 16:06 ` NiGHTS 2014-08-13 17:43 ` Jeffrey Carter 2014-08-13 17:58 ` Shark8 @ 2014-08-13 18:36 ` Dmitry A. Kazakov 2 siblings, 0 replies; 15+ messages in thread From: Dmitry A. Kazakov @ 2014-08-13 18:36 UTC (permalink / raw) On Wed, 13 Aug 2014 09:06:51 -0700 (PDT), NiGHTS wrote: > Is it possible to have a constrained array of indefinite arrays without > using access? Yes, if the semantics is by-value/copy > In my target program, the "Do_Something_With_Array" function is actually > an interface to a FIFO queue where groups of indefinite arrays are > temporarily buffered for use by another task. Of course this will be via > an entry to a protected object but those details aside how can I construct > a constrained array of indefinite arrays? I have several questions to that: 1. Do you really need marshaling? You say you buffer arrays that means the producer and consumer are decoupled and you could enqueue several request before servicing one. Is to so? Because in a synchronous schema when requests are serviced as they appear you don't need to marshal requests. You simply do a rendezvous from the producer to the consumer and do not copy anything. This is also possible to implement though a protected object (but would require an access type). In both cases the producer holds the array, which is possible due to synchronicity. 2. It is almost always a bad idea to service requests in a protected operation. Since you are working with arrays, it would involve loops, which is certainly not good to do within such an operation. Sooner or later you would like to do some I/O or other blocking stuff. 3. 1-1 FIFO actually does not need locking. You can implement it without protected objects. One possible implementation is here http://www.dmitry-kazakov.de/ada/components.htm#Generic_Indefinite_FIFO It works with indefinite arrays. Arrays will copied in and out (marshaled). 4. For n-1, 1-m, n-m FIFOs, deploying a mutex for interlocking is almost always better than servicing on the context of a protected action. It might be slightly slower but much safer. A FIFO end with has 1 task attached can access FIFO in a lock-free manner. E.g. for n-1, you must interlock only producers etc. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Pointer to instance of indefinite array? 2014-08-13 3:06 ` NiGHTS 2014-08-13 4:28 ` Jeffrey Carter @ 2014-08-13 4:31 ` Per Sandberg 2014-08-13 7:47 ` Georg Bauhaus 2014-08-13 18:17 ` Niklas Holsti 1 sibling, 2 replies; 15+ messages in thread From: Per Sandberg @ 2014-08-13 4:31 UTC (permalink / raw) Well, The compiler uses the most appropriate method of passing parameters (by value or by reference) depending on the kind of object, this usually means that composite types is passed by reference and scalars is passed by value. However your sample does compile with some small modifications: ------------------------------------------ package Test_Package is type Element is record ID_1 : Positive; ID_2 : Positive; end record; type Element_Array is array (Positive range <>) of Element; type Element_Array_Ptr is access all Element_Array; --> Use "all" to be able to reference objects allocated on staticly or stack. procedure Do_Something_With_Array (In_Array : in Element_Array_Ptr); end Test_Package; ----------------------------- with Test_Package; use Test_Package; procedure main is Test_Array : aliased Element_Array (1 .. 20); begin Do_Something_With_Array (In_Array => Test_Array'Unrestricted_Access); -- Use Unrestricted_Access attribute to disable -- accessibility and aliased view checks end main; ---------------------------- /Per On 13.08.2014 05:06, NiGHTS wrote: > On Tuesday, August 12, 2014 10:29:04 PM UTC-4, Shark8 wrote: >> On 12-Aug-14 20:07, NiGHTS wrote: >> What are you really trying to do? You can do everything you want in the >> example w/o touching access types: > > On Tuesday, August 12, 2014 10:09:37 PM UTC-4, Jeffrey Carter wrote: >> Think in Ada and get rid of the access type. > > Hmm. You're right. It worked! Compiler must be changing it internally to a pointer though since it would be far too inefficient to copy the entire array. > ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Pointer to instance of indefinite array? 2014-08-13 4:31 ` Per Sandberg @ 2014-08-13 7:47 ` Georg Bauhaus 2014-08-13 8:05 ` Egil H H 2014-08-13 15:32 ` Adam Beneschan 2014-08-13 18:17 ` Niklas Holsti 1 sibling, 2 replies; 15+ messages in thread From: Georg Bauhaus @ 2014-08-13 7:47 UTC (permalink / raw) On 13.08.14 06:31, Per Sandberg wrote: > procedure main is > Test_Array : aliased Element_Array (1 .. 20); > begin > Do_Something_With_Array (In_Array => Test_Array'Unrestricted_Access); > -- Use Unrestricted_Access attribute to disable > -- accessibility and aliased view checks > end main; Since 'Unrestricted_Access is not Ada but a GNAT specific pragma, and since it is not strictly needed, I think that standard Ada's own 'Unchecked_Acceess should be enough? procedure Main is Test_Array : aliased Element_Array := (1 .. 20 => (1, 2)); -- declared as an unconstrained type to match the pointer type begin Do_Something_With_Array (In_Array => Test_Array'Unchecked_Access); -- Use Unchecked_Access attribute since passing -- an object that will be inaccessibility at higher levels -- (that of the pointer type) end Main; If there is need to use a pointer at all, e.g. when using GNAT and a really big array and the stack of GNAT's environment task is limited by the operating system, then one may still pass the dereference Test_Array_Ptr.all without any concerns about copying. So Do_Something_With_Array can declare just an array type in its profile, not a pointer. I remember something about the ICC compiler supporting an implementation specific attribute similar to 'Unrestricted_Access. Is there a significant advantage in using 'Unrestricted_Access in user programs, perhaps suppression of more checks so that to something runs a lot faster? ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Pointer to instance of indefinite array? 2014-08-13 7:47 ` Georg Bauhaus @ 2014-08-13 8:05 ` Egil H H 2014-08-13 15:32 ` Adam Beneschan 1 sibling, 0 replies; 15+ messages in thread From: Egil H H @ 2014-08-13 8:05 UTC (permalink / raw) On Wednesday, August 13, 2014 9:47:40 AM UTC+2, Georg Bauhaus wrote: > I remember something about the ICC compiler supporting an implementation > > specific attribute similar to 'Unrestricted_Access. Is there a significant > > advantage in using 'Unrestricted_Access in user programs, perhaps suppression > > of more checks so that to something runs a lot faster? I don't know the performance characteristics of 'Unrestricted_Access, but it enables the effect of 'Unchecked_Access for subprograms. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Pointer to instance of indefinite array? 2014-08-13 7:47 ` Georg Bauhaus 2014-08-13 8:05 ` Egil H H @ 2014-08-13 15:32 ` Adam Beneschan 2014-08-14 8:03 ` Georg Bauhaus 1 sibling, 1 reply; 15+ messages in thread From: Adam Beneschan @ 2014-08-13 15:32 UTC (permalink / raw) On Wednesday, August 13, 2014 12:47:40 AM UTC-7, Georg Bauhaus wrote: > Since 'Unrestricted_Access is not Ada but a GNAT specific pragma, > and since it is not strictly needed, I think that standard Ada's own > 'Unchecked_Acceess should be enough? No, because of a somewhat obscure rule that deals with 'Access on an array when the target type is access-to-unconstrained-array. The rule is in 3.10.2(27-27.2). The reason for the rule is that access-to-unconstrained-array types need to either carry or point to information about the bounds; and in implementations where the bounds have to be stored together with the data, and the access object points to the bounds, you don't want to force the program to store the bounds for *every* array. Because of this, even if 'Unrestricted_Access compiles on GNAT in Per's example code, it would have to be tested to make sure it works. If there's no bound information, then the resulting code will be incorrect. I think GNAT stores the bounds next to the data, but I'm not sure. > I remember something about the ICC compiler supporting an implementation > specific attribute similar to 'Unrestricted_Access. Is there a significant > advantage in using 'Unrestricted_Access in user programs, perhaps suppression > of more checks so that to something runs a lot faster? 'Unrestricted_Access in ICC Ada just allows you to get the 'Access of something that wouldn't otherwise be legal. I think it's the same in GNAT, but I'm not positive. Note that 'Unchecked_Access suppresses accessibility checks (allowing an access object to point to something on the stack that could disappear before the access object does), and therefore it allows you to violate the static accessibility rules, but it doesn't allow you to violate other rules. For example, if you use X'Unchecked_Access, X still has to be aliased, and there are other rules that are still checked. 'Unrestricted_Access suppresses checks like that too. (In addition (as Egil posted), it can be used on subprograms, for which Ada doesn't allow 'Unchecked_Access.) So, no, 'Unrestricted_Access doesn't affect performance. In any case, the only checks performed at run-time are accessibility-level checks, and 'Unchecked_Access suppresses those, so it's hard to come up with any further performance improvements. -- Adam ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Pointer to instance of indefinite array? 2014-08-13 15:32 ` Adam Beneschan @ 2014-08-14 8:03 ` Georg Bauhaus 0 siblings, 0 replies; 15+ messages in thread From: Georg Bauhaus @ 2014-08-14 8:03 UTC (permalink / raw) On 13.08.14 17:32, Adam Beneschan wrote: >> Since 'Unrestricted_Access is not Ada but a GNAT specific pragma, >> >and since it is not strictly needed, I think that standard Ada's own >> >'Unchecked_Acceess should be enough? > No, because of a somewhat obscure rule that deals with 'Access on an array when the target type is access-to-unconstrained-array. The rule is in 3.10.2(27-27.2). Wow. Also found AI95-363. This is similar to, but more entertaining than Sudoku. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Pointer to instance of indefinite array? 2014-08-13 4:31 ` Per Sandberg 2014-08-13 7:47 ` Georg Bauhaus @ 2014-08-13 18:17 ` Niklas Holsti 1 sibling, 0 replies; 15+ messages in thread From: Niklas Holsti @ 2014-08-13 18:17 UTC (permalink / raw) On 14-08-13 07:31 , Per Sandberg wrote: > Well, > The compiler uses the most appropriate method of passing parameters (by > value or by reference) depending on the kind of object, this usually > means that composite types is passed by reference and scalars is passed > by value. Anecdote: Long ago, there was an (in)famous version of GNAT (something like 2.95p, perhaps?) for which AdaCore had decided to be "more compatible with C" and therefore to pass record types by copy. I was developing an application that heavily relied on passing large records around. We ended up delivering the application with advice to use a 10 MB stack limit... a large amount, at the time. Luckily the application was not time-critical. However, this compiler "feature" also revealed an aliasing bug in the application, where one of my procedures was reading a record object passed as a parameter, while modifying it as a global (IIRC). Perhaps GNAT should have an option to use pass-by-copy wherever it can, to smoke out such bugs :-). -- Niklas Holsti Tidorum Ltd niklas holsti tidorum fi . @ . ^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2014-08-14 8:03 UTC | newest] Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2014-08-13 2:07 Pointer to instance of indefinite array? NiGHTS 2014-08-13 2:09 ` Jeffrey Carter 2014-08-13 2:29 ` Shark8 2014-08-13 3:06 ` NiGHTS 2014-08-13 4:28 ` Jeffrey Carter 2014-08-13 16:06 ` NiGHTS 2014-08-13 17:43 ` Jeffrey Carter 2014-08-13 17:58 ` Shark8 2014-08-13 18:36 ` Dmitry A. Kazakov 2014-08-13 4:31 ` Per Sandberg 2014-08-13 7:47 ` Georg Bauhaus 2014-08-13 8:05 ` Egil H H 2014-08-13 15:32 ` Adam Beneschan 2014-08-14 8:03 ` Georg Bauhaus 2014-08-13 18:17 ` Niklas Holsti
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox