Any clues on why the use of an allocator would cause a single
function invocation to be called twice ?
the_Movie : media.Video.view := new_Movie;
the_next_Frame : openGL.Image :=
the_Movie.next_Frame; -- case 1
the_next_Frame : access openGL.Image := new
opengl.Image' (the_Movie.next_Frame); -- case 2
In the 1st case, the 'next_Frame' function is called once.
In the 2nd case, it is called twice.
'the_Movie' is an access to an object of tagged type
'media.Video.item'.
package media.Video is
type Item is tagged limited private;
type View is access all Item;
...
function next_Frame (Self : access Item) return opengl.Image;
...
end media.Video;
'opengl.Image' is an array with two unconstrained indices ...
package openGL is
...
type Image is array (Index_t range <>, Index_t range <>) of
Color;
end openGL;
In case it matters, the 'next_Frame' function contains a rendezvous
with a decoder task.
The decoder task is a component of the 'media.Video.item' record.
regards,
Rod.
Wouldn't Image be controlled by any chance? In that case, the assignment
may involve the creation of an intermediate object
--
---------------------------------------------------------
J-P. Rosen (ro...@adalog.fr)
Adalog a déménagé / Adalog has moved:
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
Not in this case, no.
'opengl.Image' is fairly simple array type with 2 unconstrained
indices ...
Rod, may be you should have a look at the produced assembly ? and post an
excerpt here
--
Si les chats miaulent et font autant de vocalises bizarres, c’est pas pour
les chiens.
“ c++; /* this makes c bigger but returns the old value */ ” [Anonymous]
A good idea.
I created a small test program ...
with media.Video;
with openGL;
procedure Tester
is
the_Movie : media.Video.view := media.Video.new_Video ("xyz.avi");
Case_1 : openGL.Image := the_Movie.next_Frame;
Case_2 : access openGL.Image := new
opengl.Image' (the_Movie.next_Frame);
begin
null;
end;
... and generated the mixed ada/asm, which is here:
http://109.74.196.91:8080/doubled_next_Frame_call_results.txt
In brief, the mixed ada/asm shows next_Frame being called twice for
Case_2 ...
**** Case_2 : access openGL.Image := new
opengl.Image' (the_Movie.next_Frame);
...
call media__video__next_frame
...
call __gnat_malloc
...
call media__video__next_frame
...
call memcpy
Hope this helps.
regards.
> ... and generated the mixed ada/asm, which is here:
> http://109.74.196.91:8080/doubled_next_Frame_call_results.txt
Could you show the -gnatG output as well?
Source recreated from tree for Tester (body)
--------------------------------------------
with media;
with media.media__video;
with opengl;
with ada.ada__tags;
with system.system__secondary_stack;
procedure tester is
M13b : system__secondary_stack__mark_id :=
$system__secondary_stack__ss_mark;
procedure tester___clean is
begin
$system__secondary_stack__ss_release (M13b);
return;
end tester___clean;
begin
the_movie : media.media__video.media__video__view := media.
media__video.media__video__new_video__2 ("xyz.avi");
[constraint_error when
the_movie = null
"access check failed"]
-- Case 1 begins here ...
type tester__A3b is access all opengl__image;
R4b : constant tester__A3b := media__video__next_frame (the_movie,
selfL => 0)'reference;
subtype tester__Tcase_1S is opengl__image (R4b.all'first(1) ..
R4b.all'
last(1), R4b.all'first(2) .. R4b.all'last(2));
[constraint_error when
R4b.all'last(2) >= R4b.all'first(2) and then (R4b.all'first(2) <
0 or else R4b.all'last(2) > 65535)
"range check failed"]
[constraint_error when
R4b.all'last(1) >= R4b.all'first(1) and then (R4b.all'first(1) <
0 or else R4b.all'last(1) > 65535)
"range check failed"]
case_1 : opengl__image (R4b.all'first(1) .. R4b.all'last(1),
R4b.all'
first(2) .. R4b.all'last(2)) := R4b.all;
-- Case 2 begins here ...
type tester__A10b is access all opengl__image;
R11b : constant tester__A10b := (media__video__next_frame
(the_movie,
selfL => 0))'reference;
subtype tester__A9b is opengl__image ((R11b.all)'first(1) ..
(R11b.all)'
last(1), (R11b.all)'first(2) .. (R11b.all)'last(2));
[constraint_error when
(R11b.all)'last(2) >= (R11b.all)'first(2) and then ((R11b.all)'
first(2) < 0 or else (R11b.all)'last(2) > 65535)
"range check failed"]
[constraint_error when
(R11b.all)'last(1) >= (R11b.all)'first(1) and then ((R11b.all)'
first(1) < 0 or else (R11b.all)'last(1) > 65535)
"range check failed"]
case_2 : access opengl.opengl__image := new opengl.opengl__image'(
tester__A9b?((media__video__next_frame (the_movie, selfL =>
0))));
[subtype tester__T6b is access opengl__image]
reference tester__T6b
null;
return;
at end
tester___clean;
end tester;
For Case_2, it appears the 1st call to next_Frame is used purely to
get the bounds of the returned array. The bounds are then used to
define 'tester__A9b' which is a subtype of opengl.Image of the correct
size. 'tester__A9b' is then used to convert the result of the 2nd call
to next_Frame, during allocation.
What compiler do you use? Do you mind to post the complete (minimum
required) source. I would like to see if I get the same result on my
machine.
Anh Vo
I'm using the GPL10 edition of Gnat on Ubuntu 10.04 (32bit).
Here's a tarball of the testcase ... http://109.74.196.91:8080/double_next_frame_call.tar.gz
You may need to install ffmpeg development packages (libavutil-dev,
libswscale-dev, libavcodec-dev, libavformat-dev on debian/ubuntu).
Also, it should be built with gprbuild.
> I'm using the GPL10 edition of Gnat on Ubuntu 10.04 (32bit).
>
> Here's a tarball of the testcase ... http://109.74.196.91:8080/double_next_frame_call.tar.gz
>
> You may need to install ffmpeg development packages (libavutil-dev,
> libswscale-dev, libavcodec-dev, libavformat-dev on debian/ubuntu).
>
> Also, it should be built with gprbuild.
First, I can confirm that on Mac OS X the assembly listing
of tester shows three calls, too:
$ grep _media__video__next_frame build/tester.s
call _media__video__next_frame
call _media__video__next_frame
call _media__video__next_frame
$
(I've had to make a few changes to c_media due to recent
changes in ffmpeg, viz. definitions CODEC_TYPE_VIDEO and
others seem to have been replaced with AVMEDIA_TYPE_VIDEO
and others; avcodec_decode_video2 is new for
avcodec_decode_video. Just grabbed patches from ffmpeg
clients from the net, I don't understand them.)
The following appears to be generating two calls only, FWIW:
the_Movie : media.Video.view := media.Video.new_Video ("xyz.avi");
Case_1 : openGL.Image := the_Movie.next_Frame;
Workaround : openGL.Image renames The_Movie.Next_Frame;
Case_2 : access openGL.Image := new opengl.Image' (Workaround);
$ grep _media__video__next_frame build/tester.s
call _media__video__next_frame
call _media__video__next_frame
$
Thanks for the info.
> The following appears to be generating two calls only, FWIW:
>
> the_Movie : media.Video.view := media.Video.new_Video ("xyz.avi");
>
> Case_1 : openGL.Image := the_Movie.next_Frame;
> Workaround : openGL.Image renames The_Movie.Next_Frame;
> Case_2 : access openGL.Image := new opengl.Image' (Workaround);
>
Heh, this is indeed how I ended up tackling the problem in the real
source :).
Thank you for posting the code. However, I had problem to download
this tar file. Any one else had problem as I did?
Anh Vo
package Media is
type Color is
record
val : integer;
end record;
type Image is array (integer range <>) of Color;
pragma pack (Image); -- matters!
function next_Frame return Image;
end Media;
with Ada.Text_IO; use Ada.Text_IO;
package body Media is
counter: integer := 0;
function next_Frame return Image is
begin
put_line("in next_frame");
counter := counter + 1;
return (1..10 => (val => counter));
end next_Frame;
end Media;
with Media;
with text_io;
procedure Test1 is
Case_1 : Media.Image := Media.Image' (Media.next_Frame);
Case_2 : access Media.Image := new Media.Image' (Media.next_Frame);
begin
text_io.put_line(case_1(5).val'img);
text_io.put_line(case_2(5).val'img);
end;
Thank you for making the simplest test case.
I got double calls, too. It is absolutely a compiler bug.
Anh Vo
Ah, very nice, thank you.
Yes, I also 'pragma pack' the openGL.Image type.
Yes, I suppose it must be. It will be interesting to try it again
when GPL11 arrives.
Have you sent a bug report yet? I hope you did if you want to see it
fix in GNAT-GPL-2011.
package Media is
type Color is
record
val : integer;
end record;
type Image is array (integer range <>) of Color;
pragma pack (Image); -- matters!
function next_Frame return Image;
type Image_ptr is access Media.Image;
end Media;
with Text_IO; use Text_IO;
package body Media is
counter: integer := 0;
function next_Frame return Image is
begin
put_line("in next_frame");
counter := counter + 1;
return (1 .. 5-counter => (val => 10));
end next_Frame;
end Media;
with Media;
with text_io;
procedure Test2 is
Case_1 : Media.Image(1..4) := Media.Image' (Media.next_Frame);
Case_2 : Media.Image_ptr := new Media.Image' (Media.next_Frame);
procedure put(x: Media.Image) is
j: integer;
begin
for i in x'range loop
text_io.put_line(x(i).val'img);
j := 1/x(i).val; -- ensure val is not zero
end loop;
text_io.new_line;
end;
begin
put(case_1);
put(case_2.all);
end;
One has been sent now (thank you Jesse Lang).
And thanks to all who've replied and to Dan for taking the time to
simplify the test case.
I would like this bug report to be public in the GCC bugzilla database;
for multiple reasons, this is better than for the bug to remain private
in AdaCore's bug tracking system. Could someone take the time to file
it properly in Bugzilla?
--
Ludovic Brenta.
Submitted ... http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48995
regards.