From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Thread: 103376,41967527237c1aa2 X-Google-Attributes: gid103376,public X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news1.google.com!postnews.google.com!r56g2000hsd.googlegroups.com!not-for-mail From: "Adam Beneschan" Newsgroups: comp.lang.ada Subject: Re: Fun with Tasking Date: 28 Mar 2007 09:55:48 -0700 Organization: http://groups.google.com Message-ID: <1175100948.580216.145940@r56g2000hsd.googlegroups.com> References: <1175097196.113031.259000@r56g2000hsd.googlegroups.com> NNTP-Posting-Host: 66.126.103.122 Mime-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" X-Trace: posting.google.com 1175100950 7245 127.0.0.1 (28 Mar 2007 16:55:50 GMT) X-Complaints-To: groups-abuse@google.com NNTP-Posting-Date: Wed, 28 Mar 2007 16:55:50 +0000 (UTC) In-Reply-To: <1175097196.113031.259000@r56g2000hsd.googlegroups.com> User-Agent: G2/1.0 X-HTTP-UserAgent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.12) Gecko/20050922 Fedora/1.7.12-1.3.1,gzip(gfe),gzip(gfe) Complaints-To: groups-abuse@google.com Injection-Info: r56g2000hsd.googlegroups.com; posting-host=66.126.103.122; posting-account=cw1zeQwAAABOY2vF_g6V_9cdsyY_wV9w Xref: g2news1.google.com comp.lang.ada:14653 Date: 2007-03-28T09:55:48-07:00 List-Id: On Mar 28, 8:53 am, mhamel...@yahoo.com wrote: > Below is sample code I made representing something I wanted to do with > a program, of course it doesn't work quite the way I would like. > Hopefully this sample doesn't cause eye (or brain) injury, it is more > symbolic than useful - the procedure "Exec" is, of course, really a > package (rather, several similar packages). > > The problem is, how to "transport" a task? As seen in the sample > below, I would like to use just a single address in the Control_Block > type, but it's never that simple, is it? In actuality, how I get this > program in its full incarnation to work is to define the "test_task"s > in the acc_add_test part of the program. I really don't like doing > this, as I mentioned, "exec" is representative of a family of several > different packages. I would like the task definition to be local to > the "exec" pacakage(s), not all kludged together in acc_add_test, > which then requires all sorts of (ideally private) types being moved > out of the local "exec" packages into acc_add_test and then the > Control_Block record now has nearly a dozen different task pointers > stuffed into it, only one of which is going to be used at any given > time. > > One last caveat, the Acc_Add_Test program should have *no* visibility > into the "exec" procedure/package. The "exec" package(s), in fact, > "push" their procedures into the main program. So is there something > simple I'm having a brain fart over in missing here, or is a complete > re-architecture required here? > > with Text_Io; > with System; > with System.Address_To_Access_Conversions; > > procedure Acc_Add_test is > > Exec_Count : constant Natural := 10; > > type Control_Block is > record > Task_Addr : System.Address; > end record; > > type Mode_Type is (preprocess, process); > > procedure Exec (Mode : in Mode_Type; > Cntl : in out Control_Block) is > > task type Test_Task is > entry Start (Addr : System.Address); > entry Complete; > end Test_Task; > > package Convert is new System.Address_To_Access_Conversions > (Test_Task); > use Convert; > > task body Test_Task is > Task_Ptr : Convert.Object_Pointer := null; > Count : Natural := 0; > begin > loop > begin > select > accept Start (Addr : System.Address) do > Task_Ptr := Convert.To_Pointer (Addr); > end Start; > > or > accept Complete do > Count := Count + 1; > end Complete; > if Count = Exec_Count then > Text_Io.Put_Line ("Completed All Tasks"); > abort Task_Ptr.all; > end if; > end select; > end; > end loop; > end Test_Task; > > begin > case Mode is > when Preprocess => > declare > Task_Ptr : Convert.Object_Pointer; > Address : System.Address; > begin > Task_Ptr := new Test_Task; > Address := Convert.To_Address (Task_Ptr); > Task_Ptr.Start (Address); > Cntl.Task_Addr := Address; > end; > > when Process => > declare > Task_Ptr : Convert.Object_Pointer; > begin > Task_Ptr := Convert.To_Pointer (Cntl.Task_Addr); > Task_Ptr.Complete; > end; > end case; > end Exec; > > Controls : Control_Block; > > begin > Exec (Preprocess, Controls); > for I in 1 .. Exec_Count loop > Exec (Process, Controls); > end loop; > end Acc_Add_Test; > > Thanks for any input! Your main problem is that your tasks aren't going to live long enough. When a task is created by an allocator, it depends on the "master" that declares the access type (or if the access type is a derived type, which isn't the case here, on the "ultimate ancestor" of the access type). See RM section 9.3. In this case, the master that declares the access type (Convert.Object_Pointer) is the Exec procedure. This means that any task that you create using this access type depends on Exec, and Exec will not finish until any such tasks are completed. It looks to me that you're trying to be able to call Exec multiple times, and have it start a task the first time and then use the same task the next time Exec is called. This won't work if the task type is declared inside Exec, because any such tasks will not be allowed to keep running if Exec isn't running. You'll need to move the task types (and the access type that points to the task type) outside Exec. This is the only thing that makes sense, anyway. If your task type is declared inside Exec, the task body will have access to Exec's parameters and local variables; how then could it be possible for the task body to stay running while Exec isn't? I'm not real clear on what you're trying to do. Your sample has "Exec" as a procedure, which makes it a master, but your discussion talks about "Exec" *packages*---and a package is not a master. If you wanted an Exec *package* that declares its own task type and its own procedure to do the processing, but the task type isn't inside the procedure, then I suspect that you may be able to accomplish what you're trying to do; and there should be a way to keep certain things private without having to resort to hokeyness like System.Address or Address_To_Access_Conversions. But I'm not up to trying to guess what you're trying to do; I'd recommend that you redo your example a bit to avoid the task dependence problem and then ask again if you still aren't sure how to do what you need to do. -- Adam