* confusion about message passing between the tasks @ 2014-10-24 16:44 compguy45 2014-10-24 18:39 ` Ludovic Brenta ` (4 more replies) 0 siblings, 5 replies; 38+ messages in thread From: compguy45 @ 2014-10-24 16:44 UTC (permalink / raw) I am really kind of lost with tasks and message passing. Would anyone show me an example where 2 tasks would be created by environment task...each task has same body and one entry...so for example one task waits at entry while the other one completes the entry block and on the exit lets waiting task that's its done. ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: confusion about message passing between the tasks 2014-10-24 16:44 confusion about message passing between the tasks compguy45 @ 2014-10-24 18:39 ` Ludovic Brenta 2014-10-25 1:51 ` compguy45 2014-10-24 23:49 ` Stribor40 ` (3 subsequent siblings) 4 siblings, 1 reply; 38+ messages in thread From: Ludovic Brenta @ 2014-10-24 18:39 UTC (permalink / raw) compguy45@gmail.com writes: > I am really kind of lost with tasks and message passing. Would anyone > show me an example where 2 tasks would be created by environment > task...each task has same body and one entry...so for example one task > waits at entry while the other one completes the entry block and on > the exit lets waiting task that's its done. Maybe you'll be interested in the talk I gave at FOSDEM 2014; this was part two of "Multitasking made easy", subtitled "Ada Task Pools". Source code is available here: http://people.debian.org/~lbrenta/ada-fosdem2014.tar.gz and the one-hour video is here: http://video.fosdem.org/2014/K4601/Saturday/ In the example discussed, the main task starts N identical tasks and then calls an entry Start on each task. The number of tasks is computed at run time. -- Ludovic Brenta. ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: confusion about message passing between the tasks 2014-10-24 18:39 ` Ludovic Brenta @ 2014-10-25 1:51 ` compguy45 2014-10-25 7:13 ` Ludovic Brenta 0 siblings, 1 reply; 38+ messages in thread From: compguy45 @ 2014-10-25 1:51 UTC (permalink / raw) In those directories all example are graphics example. Which directory is one that creates N tasks? ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: confusion about message passing between the tasks 2014-10-25 1:51 ` compguy45 @ 2014-10-25 7:13 ` Ludovic Brenta 0 siblings, 0 replies; 38+ messages in thread From: Ludovic Brenta @ 2014-10-25 7:13 UTC (permalink / raw) compguy45@gmail.com writes: > In those directories all example are graphics example. Which directory > is one that creates N tasks? The directories 1..5 all contain different versions of the same graphical program. Version 1: no tasks. Version 2: N tasks, race condition when multiple tasks want to draw using a shared graphics context. Version 3: race condition solved by placing the graphics context in a protected object. But the problem now, with 10_000 tasks, is excessive virtual memory consumption (8 MiB of stack per task), which luckily does not translate into physical memory usage, at least on Linux. Version 4: Introduce a task queue. Now the number of tasks is independent on the number of rectangles. But there is still a problem; a deadlock exists when one task A finds that there remains a rectangle in the queue but another task B gets to dequeue it first. Then A tries to dequeue the last rectangle but waits forever as the queue is now empty. As a consequence the master task waits forever for A to complete. Version 5: deadlock solved by a select statement. -- Ludovic Brenta. ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: confusion about message passing between the tasks 2014-10-24 16:44 confusion about message passing between the tasks compguy45 2014-10-24 18:39 ` Ludovic Brenta @ 2014-10-24 23:49 ` Stribor40 2014-10-25 7:03 ` Ludovic Brenta 2014-10-25 7:58 ` Simon Wright ` (2 subsequent siblings) 4 siblings, 1 reply; 38+ messages in thread From: Stribor40 @ 2014-10-24 23:49 UTC (permalink / raw) Do you have a simpler example by any chance? Your examples are great but just way too complicated for my level... ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: confusion about message passing between the tasks 2014-10-24 23:49 ` Stribor40 @ 2014-10-25 7:03 ` Ludovic Brenta 0 siblings, 0 replies; 38+ messages in thread From: Ludovic Brenta @ 2014-10-25 7:03 UTC (permalink / raw) Stribor40 writes: > Do you have a simpler example by any chance? Your examples are great > but just way too complicated for my level... John English has another, non-graphical example here: http://www.adaic.org/resources/add_content/docs/craft/html/ch19.htm but I doubt it is simpler than mine. He has a select statement, for example, which I don't. -- Ludovic Brenta. ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: confusion about message passing between the tasks 2014-10-24 16:44 confusion about message passing between the tasks compguy45 2014-10-24 18:39 ` Ludovic Brenta 2014-10-24 23:49 ` Stribor40 @ 2014-10-25 7:58 ` Simon Wright 2014-10-25 13:01 ` compguy45 2014-10-25 17:25 ` Dennis Lee Bieber 2014-10-25 23:42 ` compguy45 4 siblings, 1 reply; 38+ messages in thread From: Simon Wright @ 2014-10-25 7:58 UTC (permalink / raw) compguy45@gmail.com writes: > I am really kind of lost with tasks and message passing. Would anyone > show me an example where 2 tasks would be created by environment > task...each task has same body and one entry...so for example one task > waits at entry while the other one completes the entry block and on > the exit lets waiting task that's its done. with Ada.Text_IO; use Ada.Text_IO; procedure Strib is type T; type T_Access is access T; task type T (Next : T_Access) is entry Start (Message : Integer); end T; task body T is Data : Integer; begin Put_Line ("waiting"); accept Start (Message : Integer) do Data := Message; end Start; Put_Line ("working with " & Integer'Image (Data)); delay 1.0; if Next /= null then Put_Line ("kicking off next task"); Next.Start (Data + 1); else Put_Line ("no next task"); end if; Put_Line ("done"); end T; Tasks : array (1 .. 2) of T_Access; begin -- we have to create the tasks in reverse order, because the first -- task needs to be able to reach the second task. Tasks (2) := new T (Next => null); Tasks (1) := new T (Next => Tasks (2)); Tasks (1).Start (42); end Strib; ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: confusion about message passing between the tasks 2014-10-25 7:58 ` Simon Wright @ 2014-10-25 13:01 ` compguy45 2014-10-25 14:11 ` Simon Wright 0 siblings, 1 reply; 38+ messages in thread From: compguy45 @ 2014-10-25 13:01 UTC (permalink / raw) Why are you passing task as parametar? ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: confusion about message passing between the tasks 2014-10-25 13:01 ` compguy45 @ 2014-10-25 14:11 ` Simon Wright 0 siblings, 0 replies; 38+ messages in thread From: Simon Wright @ 2014-10-25 14:11 UTC (permalink / raw) compguy45@gmail.com writes: > Why are you passing task as parametar? I assume you mean task type T (Next : T_Access) is ? (it would help if you quoted _some_ context) I can see why you might think of that as a parameter, but in Ada the word is "discriminant". Next *either* designates (contains a pointer to) the "next" task in the chain of tasks, the one whose entry _this_ task is supposed to call when it's done, *or* is null, in which case _this_ task is the last in the chain; as implemented in if Next /= null then Put_Line ("kicking off next task"); Next.Start (Data + 1); else Put_Line ("no next task"); end if; The task has to have some way of knowing which, if any, task it's supposed to let know that it's finished. ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: confusion about message passing between the tasks 2014-10-24 16:44 confusion about message passing between the tasks compguy45 ` (2 preceding siblings ...) 2014-10-25 7:58 ` Simon Wright @ 2014-10-25 17:25 ` Dennis Lee Bieber 2014-10-25 17:54 ` Jeffrey Carter 2014-10-25 23:42 ` compguy45 4 siblings, 1 reply; 38+ messages in thread From: Dennis Lee Bieber @ 2014-10-25 17:25 UTC (permalink / raw) On Fri, 24 Oct 2014 09:44:08 -0700 (PDT), compguy45@gmail.com declaimed the following: >I am really kind of lost with tasks and message passing. Would anyone show me an example where 2 tasks would be created by environment task...each task has same body and one entry...so for example one task waits at entry while the other one completes the entry block and on the exit lets waiting task that's its done. If they are the "same body and one entry" there is NO WAY to do what you want. Either both tasks will be waiting on their entry for another to rendezvous, or both tasks will be blocked waiting to rendezvous on a called entry. First case (pseudo code): accept theEntry() -- both blocked waiting for some task to call it -- note that it can't restrict which task calls do stuff end theEntry other.theEntry() Second case: other.theEntry() -- both blocked waiting for known other task to accept -- you'll have to initialize each task with the -- knowledge of the other accept theEntry() do stuff end theEntry -- Wulfraed Dennis Lee Bieber AF6VN wlfraed@ix.netcom.com HTTP://wlfraed.home.netcom.com/ ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: confusion about message passing between the tasks 2014-10-25 17:25 ` Dennis Lee Bieber @ 2014-10-25 17:54 ` Jeffrey Carter 2014-10-25 22:23 ` Robert A Duff 0 siblings, 1 reply; 38+ messages in thread From: Jeffrey Carter @ 2014-10-25 17:54 UTC (permalink / raw) On 10/25/2014 10:25 AM, Dennis Lee Bieber wrote: > On Fri, 24 Oct 2014 09:44:08 -0700 (PDT), compguy45@gmail.com declaimed the > following: > >> I am really kind of lost with tasks and message passing. Would anyone show me an example where 2 tasks would be created by environment task...each task has same body and one entry...so for example one task waits at entry while the other one completes the entry block and on the exit lets waiting task that's its done. > > If they are the "same body and one entry" there is NO WAY to do what > you want. Either both tasks will be waiting on their entry for another to > rendezvous, or both tasks will be blocked waiting to rendezvous on a called > entry. > > First case (pseudo code): > > accept theEntry() -- both blocked waiting for some task to call it > -- note that it can't restrict which task calls > do stuff > end theEntry > other.theEntry() > > Second case: > other.theEntry() -- both blocked waiting for known other task to accept > -- you'll have to initialize each task with the > -- knowledge of the other > accept theEntry() > do stuff > end theEntry That's not entirely true, if the task has a discriminant. For example task type T (First : Boolean); task body T is begin if First then accept E do ... end E; Other.E; else Other.E; accept E do ... end E; end if; end T; I think the OP's problem is that he's trying to think about Ada tasking in terms of message passing. Ada tasks operate with rendezvous and protected objects, which are synchronous by default, rather than with message passing as in Erlang, which is asynchronous by default. -- Jeff Carter "Your mother was a hamster and your father smelt of elderberries." Monty Python & the Holy Grail 06 ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: confusion about message passing between the tasks 2014-10-25 17:54 ` Jeffrey Carter @ 2014-10-25 22:23 ` Robert A Duff 2014-10-25 23:26 ` compguy45 2014-10-26 5:37 ` J-P. Rosen 0 siblings, 2 replies; 38+ messages in thread From: Robert A Duff @ 2014-10-25 22:23 UTC (permalink / raw) Jeffrey Carter <spam.jrcarter.not@spam.not.acm.org> writes: > I think the OP's problem is that he's trying to think about Ada tasking in terms > of message passing. Ada tasks operate with rendezvous and protected objects, > which are synchronous by default, rather than with message passing as in Erlang, > which is asynchronous by default. Right. If you want to think in terms of message passing, then you should think of a rendezvous as involving TWO messages. The entry caller sends a message to the callee, and then awaits a reply. When the callee reaches the accept, it receives the message, then does the stuff in the accept, then sends a reply message back to the caller. Then the caller wakes up and continues on its way. So the callee doesn't need to explicitly send a reply message back to the caller -- that happens automatically at the end of the accept. The callee doesn't know the identity of the caller. The caller needs to know the name of the callee, so it can call the entry. I prefer protected objects. Less coupling: two tasks can communicate with each other with neither one knowing the identity of the other -- they both just know about the protected object. If I were redesigning Ada from scratch, I'd leave out rendezvous. Everything you can do with rendezvous you can do with (something like) protected objects. - Bob ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: confusion about message passing between the tasks 2014-10-25 22:23 ` Robert A Duff @ 2014-10-25 23:26 ` compguy45 2014-10-26 4:50 ` Dennis Lee Bieber 2014-10-26 10:20 ` Georg Bauhaus 2014-10-26 5:37 ` J-P. Rosen 1 sibling, 2 replies; 38+ messages in thread From: compguy45 @ 2014-10-25 23:26 UTC (permalink / raw) Can anyone tell me why i am getting zero printed to the screen even though i am passing 5? 2 use Ada.Text_IO, Ada.Integer_Text_IO; 3 4 with Ada.Calendar; use Ada.Calendar; 5 6 procedure strib1 is 7 8 task type Counter_Task is 9 entry Get (Value : out Integer); 10 end Counter_Task; 11 12 13 p: Counter_Task; 14 i : Integer; 15 16 17 18 task body Counter_Task is 19 V : Integer := 0; 20 begin 21 loop 22 select 23 accept Get (Value : out Integer) do 24 put("Value of parametar passed in is ");put(Value); --Why am i getting zero printed??? 25 Value := V; 26 V := V + 1; 27 end Get; 28 or 29 terminate; 30 end select; 31 end loop; 32 end Counter_Task; 33 34 begin 35 i := 5; 36 p.Get(i); 37 ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: confusion about message passing between the tasks 2014-10-25 23:26 ` compguy45 @ 2014-10-26 4:50 ` Dennis Lee Bieber 2014-10-26 10:20 ` Georg Bauhaus 1 sibling, 0 replies; 38+ messages in thread From: Dennis Lee Bieber @ 2014-10-26 4:50 UTC (permalink / raw) On Sat, 25 Oct 2014 16:26:42 -0700 (PDT), compguy45@gmail.com declaimed the following: > Can anyone tell me why i am getting zero printed to the screen even though i am passing 5? > 17 > 18 task body Counter_Task is > 19 V : Integer := 0; > 20 begin > 21 loop > 22 select > 23 accept Get (Value : out Integer) do > 24 put("Value of parametar passed in is ");put(Value); > --Why am i getting zero printed??? Maybe because you declared it to be an OUTPUT; nothing is passed in (I'm surprised that Ada didn't complain about "used before assignment") -- Wulfraed Dennis Lee Bieber AF6VN wlfraed@ix.netcom.com HTTP://wlfraed.home.netcom.com/ ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: confusion about message passing between the tasks 2014-10-25 23:26 ` compguy45 2014-10-26 4:50 ` Dennis Lee Bieber @ 2014-10-26 10:20 ` Georg Bauhaus 1 sibling, 0 replies; 38+ messages in thread From: Georg Bauhaus @ 2014-10-26 10:20 UTC (permalink / raw) On 26.10.14 01:26, compguy45@gmail.com wrote: > 23 accept Get (Value : out Integer) do > 24 put("Value of parametar passed in is ");put(Value); > --Why am i getting zero printed??? That's a coincidence: the parameter is passed in mode "out", meaning that its value is to be established during Get, but not expected to be anything known, within Get, before that. Do you have some time left in order to become somewhat more familiar with these basics such as the mode of parameters? ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: confusion about message passing between the tasks 2014-10-25 22:23 ` Robert A Duff 2014-10-25 23:26 ` compguy45 @ 2014-10-26 5:37 ` J-P. Rosen 2014-10-26 8:14 ` Pascal Obry 2014-10-26 20:27 ` Robert A Duff 1 sibling, 2 replies; 38+ messages in thread From: J-P. Rosen @ 2014-10-26 5:37 UTC (permalink / raw) Le 26/10/2014 00:23, Robert A Duff a écrit : > I prefer protected objects. Less coupling: two tasks can communicate > with each other with neither one knowing the identity of the other -- > they both just know about the protected object. > > If I were redesigning Ada from scratch, I'd leave out rendezvous. > Everything you can do with rendezvous you can do with (something like) > protected objects. ... and everything you can do with structured statements you can do with if and goto. I strongly disagree with this position. Rendezvous is a nice model that implements directly a client-server model. Of course, in this model, the client has to know the server. So what? I view protected objects as a much lower level abstraction than rendezvous; they are nice for simple synchronisation and simple needs, but they don't scale up well for higher level abstactions. Try to Ravenscarize (!) existing software that uses rendezvous, and you'll see what I mean (I did that recently). And don't forget that with PO, you lose a very nice and poweful feature of rendezvous: automatic termination. -- J-P. Rosen Adalog 2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00 http://www.adalog.fr ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: confusion about message passing between the tasks 2014-10-26 5:37 ` J-P. Rosen @ 2014-10-26 8:14 ` Pascal Obry 2014-10-26 15:47 ` J-P. Rosen 2014-10-26 20:27 ` Robert A Duff 1 sibling, 1 reply; 38+ messages in thread From: Pascal Obry @ 2014-10-26 8:14 UTC (permalink / raw) Le dimanche 26 octobre 2014 à 06:37 +0100, J-P. Rosen a écrit : > I view protected objects as a much lower level abstraction than > rendezvous; they are nice for simple synchronisation and simple needs, > but they don't scale up well for higher level abstactions. Try to > Ravenscarize (!) existing software that uses rendezvous, and you'll see > what I mean (I did that recently). > > And don't forget that with PO, you lose a very nice and poweful feature > of rendezvous: automatic termination. Agreed, but with PO you avoid synchronization and that is one feature that can give you full speed in large simulations with many tasks. A rendez-vous is ok when the tasks are not waiting too much for each others, and this is never possible. A PO is then a good use as a buffer for data being exchanged without requiring a task to wait for another. To me both rendez-vous and PO are really nice features of the language and I don't see one of them removing the need for the other. -- Pascal Obry / Magny Les Hameaux (78) The best way to travel is by means of imagination http://v2p.fr.eu.org http://www.obry.net gpg --keyserver keys.gnupg.net --recv-key F949BD3B ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: confusion about message passing between the tasks 2014-10-26 8:14 ` Pascal Obry @ 2014-10-26 15:47 ` J-P. Rosen 0 siblings, 0 replies; 38+ messages in thread From: J-P. Rosen @ 2014-10-26 15:47 UTC (permalink / raw) Le 26/10/2014 09:14, Pascal Obry a écrit : > To me both rendez-vous and PO are really nice features of the language > and I don't see one of them removing the need for the other. I fully agree with this! -- J-P. Rosen Adalog 2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00 http://www.adalog.fr ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: confusion about message passing between the tasks 2014-10-26 5:37 ` J-P. Rosen 2014-10-26 8:14 ` Pascal Obry @ 2014-10-26 20:27 ` Robert A Duff 2014-10-26 20:31 ` Robert A Duff ` (2 more replies) 1 sibling, 3 replies; 38+ messages in thread From: Robert A Duff @ 2014-10-26 20:27 UTC (permalink / raw) "J-P. Rosen" <rosen@adalog.fr> writes: > Le 26/10/2014 00:23, Robert A Duff a écrit : >> I prefer protected objects. Less coupling: two tasks can communicate >> with each other with neither one knowing the identity of the other -- >> they both just know about the protected object. >> >> If I were redesigning Ada from scratch, I'd leave out rendezvous. >> Everything you can do with rendezvous you can do with (something like) >> protected objects. > > ... and everything you can do with structured statements you can do with > if and goto. OK, then I'll make a stronger claim: Everything you can do with rendezvous you can do with (something like) protected objects, and do it just as cleanly, and sometimes even better. Now you're goto analogy doesn't work. ;-) I like case statements and while loops. > I strongly disagree with this position. Rendezvous is a nice model that > implements directly a client-server model. Of course, in this model, the > client has to know the server. So what? > > I view protected objects as a much lower level abstraction than > rendezvous; they are nice for simple synchronisation and simple needs, > but they don't scale up well for higher level abstactions. I agree rendezvous is higher level than PO's, but "higher level" is not always synonymous with "better". I find PO's to be at the *right* level. Ada 83 tasking has some baroque bells and whistles that, though they could reasonably be considered "high level", the just get in the way. In Ada 83, I found that in between every pair of communicating tasks, I wanted to add a passive "buffer" task or some such. I'm happy to use a PO there. >...Try to > Ravenscarize (!) existing software that uses rendezvous, and you'll see > what I mean (I did that recently). That's not a fair comparison, because Ravenscar is far more restricted than just "no rendezvous". For example, I find the queue-length-1 restriction pretty onerous. > And don't forget that with PO, you lose a very nice and poweful feature > of rendezvous: automatic termination. That's why I used the weasel words "(something like)". I would extend PO's to support everything that rendezvous can do, and eliminate rendezvous. It's tricky to figure out how terminate alternatives should work with PO's, but I think I've got it. Another thing is that you'd want multi-way call. I don't mean to say rendezvous is a Bad Thing. It's just not necessary when you have (something like) PO's, and it adds a lot of complexity to the language. I'm pretty sure that if Ada 83 had PO's, Ada 95 would NOT have added rendezvous! - Bob ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: confusion about message passing between the tasks 2014-10-26 20:27 ` Robert A Duff @ 2014-10-26 20:31 ` Robert A Duff 2014-10-26 20:36 ` Jeffrey Carter 2014-10-27 7:44 ` J-P. Rosen 2014-10-26 20:42 ` Dmitry A. Kazakov 2014-10-27 7:40 ` J-P. Rosen 2 siblings, 2 replies; 38+ messages in thread From: Robert A Duff @ 2014-10-26 20:31 UTC (permalink / raw) Robert A Duff <bobduff@shell01.TheWorld.com> writes: > OK, then I'll make a stronger claim: Everything you can do with > rendezvous you can do with (something like) protected objects, > and do it just as cleanly, and sometimes even better. ...but the other way around isn't true. Here's Tucker's example that convinced me that some sort of "pragma Passive(Buffer_Task);" wasn't going to cut it. Write a PO a that is in one of two states, "accepting calls to Entry_1" and "accepting calls to Entry_2", never in both states at the same time, and never in neither state (as observed by callers). Pretty easy. With rendezvous, not so much. - Bob ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: confusion about message passing between the tasks 2014-10-26 20:31 ` Robert A Duff @ 2014-10-26 20:36 ` Jeffrey Carter 2014-10-26 22:27 ` Robert A Duff 2014-10-27 7:44 ` J-P. Rosen 1 sibling, 1 reply; 38+ messages in thread From: Jeffrey Carter @ 2014-10-26 20:36 UTC (permalink / raw) On 10/26/2014 01:31 PM, Robert A Duff wrote: > > ...but the other way around isn't true. Here's Tucker's example that > convinced me that some sort of "pragma Passive(Buffer_Task);" wasn't > going to cut it. Write a PO a that is in one of two states, > "accepting calls to Entry_1" and "accepting calls to Entry_2", > never in both states at the same time, and never in neither state > (as observed by callers). Pretty easy. With rendezvous, not so > much. That seems pretty straightforward, whether with a PO or a passive task. Is there some complication I'm missing? -- Jeff Carter "Why, the Mayflower was full of Fireflies, and a few horseflies, too. The Fireflies were on the upper deck, and the horseflies were on the Fireflies." Duck Soup 95 ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: confusion about message passing between the tasks 2014-10-26 20:36 ` Jeffrey Carter @ 2014-10-26 22:27 ` Robert A Duff 2014-10-26 23:23 ` Jeffrey Carter 0 siblings, 1 reply; 38+ messages in thread From: Robert A Duff @ 2014-10-26 22:27 UTC (permalink / raw) Jeffrey Carter <spam.jrcarter.not@spam.not.acm.org> writes: > On 10/26/2014 01:31 PM, Robert A Duff wrote: >> >> ...but the other way around isn't true. Here's Tucker's example that >> convinced me that some sort of "pragma Passive(Buffer_Task);" wasn't >> going to cut it. Write a PO a that is in one of two states, >> "accepting calls to Entry_1" and "accepting calls to Entry_2", >> never in both states at the same time, and never in neither state >> (as observed by callers). Pretty easy. With rendezvous, not so >> much. > > That seems pretty straightforward, whether with a PO or a passive task. Is there > some complication I'm missing? Maybe. Here's my PO code: type State_Enum is (Accepting_Entry_1, Accepting_Entry_2); protected P is entry Entry_1; entry Entry_2; private State: State_Enum := Accepting_Entry_1; end P; protected body P is entry body Entry_1 when State = Accepting_Entry_1 do ... if ... State := Accepting_Entry_2; end Entry_1; entry body Entry_2 when State = Accepting_Entry_2 do ... if ... State := Accepting_Entry_1; end Entry_2; end P; Can you show equivalent code using "accept"? - Bob ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: confusion about message passing between the tasks 2014-10-26 22:27 ` Robert A Duff @ 2014-10-26 23:23 ` Jeffrey Carter 2014-10-27 0:46 ` Robert A Duff 0 siblings, 1 reply; 38+ messages in thread From: Jeffrey Carter @ 2014-10-26 23:23 UTC (permalink / raw) On 10/26/2014 03:27 PM, Robert A Duff wrote: > > Maybe. Here's my PO code: > > type State_Enum is (Accepting_Entry_1, Accepting_Entry_2); > > protected P is > entry Entry_1; > entry Entry_2; > private > State: State_Enum := Accepting_Entry_1; > end P; > > protected body P is > > entry body Entry_1 when State = Accepting_Entry_1 do > ... > if ... > State := Accepting_Entry_2; > end Entry_1; > > entry body Entry_2 when State = Accepting_Entry_2 do > ... > if ... > State := Accepting_Entry_1; > end Entry_2; > > end P; > > Can you show equivalent code using "accept"? I'm pretty sure entry bodies use "is", not "do". I think so. task T is pragma Passive; entry Entry_1; entry Entry_2; end T; task body T is State : State_Enum := Accepting_Entry_1; begin -- T loop select when State = Accepting_Entry_1 => accept Entry_1 do ... if ... then State := Accepting_Entry_2; end if; end Entry_1; or when State = Accepting_Entry_2 => accept Entry_2 do ... if ... then State := Accepting_Entry_1; end if; end Entry_2; or terminate; end select; end loop; end T; -- Jeff Carter "Why, the Mayflower was full of Fireflies, and a few horseflies, too. The Fireflies were on the upper deck, and the horseflies were on the Fireflies." Duck Soup 95 ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: confusion about message passing between the tasks 2014-10-26 23:23 ` Jeffrey Carter @ 2014-10-27 0:46 ` Robert A Duff 2014-10-27 2:18 ` Jeffrey Carter 2014-10-27 7:51 ` J-P. Rosen 0 siblings, 2 replies; 38+ messages in thread From: Robert A Duff @ 2014-10-27 0:46 UTC (permalink / raw) Jeffrey Carter <spam.jrcarter.not@spam.not.acm.org> writes: > I'm pretty sure entry bodies use "is", not "do". Sorry. Obviously I didn't compile my code. ;-) > I think so. > > task T is > pragma Passive; > > entry Entry_1; > entry Entry_2; > end T; > > task body T is > State : State_Enum := Accepting_Entry_1; > begin -- T > loop > select when State = Accepting_Entry_1 => > accept Entry_1 do > ... > if ... then > State := Accepting_Entry_2; > end if; > end Entry_1; > or when State = Accepting_Entry_2 => > accept Entry_2 do > ... > if ... then > State := Accepting_Entry_1; > end if; > end Entry_2; > or > terminate; > end select; > end loop; > end T; I think that has slightly different semantics. For example: select T.Entry_1(...); else ... end select; In the PO case, we know that if Entry_1 was not acceptable, then Entry_2 must be (at that time). In the "select/accept" case, there is a moment in time when neither entry is acceptable (when T is going around that loop, jumping back to the "select"). That might seem like a nitpick, but imagine the thing (PO or task) alternates between the two states, and clients depend on that fact. In the passive-task case, we have this weird in-between state in which neither entry is open. And that's unlikely to be caught by testing, because it's rare. In the PO case, we know for sure that if the above conditional entry call finds Entry_1 closed, then Entry_2 must be open (at that time). OTOH, perhaps you mean that "pragma Passive_Task" should change the semantics of loop statements containing selects (and nothing else) such that that window doesn't happen. That could work, I suppose, but it means that the pragma is not just an optimization, but has a subtle semantic effect. I'm not sure how to even write RM wording to capture that. My first experience with a high-level language supporting concurrency (as opposed to rolling-your-own in assembly, or via OS calls) was Per-Brinch Hansen's Concurrent Pascal. Processes (like Ada tasks) and monitors (like Ada PO's, except PO entries crucially have barriers). When I learned Ada 83, it struck me as weird that you have to write write a task with a loop and a select-with-terminate to do what a monitor does (it doesn't DO anything, but simply waits to be told what to do). - Bob ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: confusion about message passing between the tasks 2014-10-27 0:46 ` Robert A Duff @ 2014-10-27 2:18 ` Jeffrey Carter 2014-10-27 7:51 ` J-P. Rosen 1 sibling, 0 replies; 38+ messages in thread From: Jeffrey Carter @ 2014-10-27 2:18 UTC (permalink / raw) On 10/26/2014 05:46 PM, Robert A Duff wrote: > > In the PO case, we know that if Entry_1 was not acceptable, then Entry_2 > must be (at that time). In the "select/accept" case, there is a moment > in time when neither entry is acceptable (when T is going around that > loop, jumping back to the "select"). > > OTOH, perhaps you mean that "pragma Passive_Task" should change the > semantics of loop statements containing selects (and nothing else) such > that that window doesn't happen. That could work, I suppose, but it > means that the pragma is not just an optimization, but has a subtle > semantic effect. I'm not sure how to even write RM wording to capture > that. DEC Ada, and I think one other Ada-83 compiler, had pragma Passive (or something similar) which had the effect of optimizing the task so that it didn't have a thread of control. The task didn't have a time when it wasn't ready to accept one of the entries. It was effectively a PO. Back in the 1980s I heard presentations by compiler writers on automatically recognizing and optimizing passive tasks, and heard them say that they thought that the language designers expected that compilers would do that. As with variant records that only take up the space needed by the current instance, for which I've heard a similar claim, most compilers didn't do this. However, Ada 95 could have standardized the pragma and made it mandatory. This would have saved a new reserved word, and the result wouldn't have had any restrictions on what could go in an accept. I always thought it was a mistake to throw away all that work for a new construct. -- Jeff Carter "Why, the Mayflower was full of Fireflies, and a few horseflies, too. The Fireflies were on the upper deck, and the horseflies were on the Fireflies." Duck Soup 95 ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: confusion about message passing between the tasks 2014-10-27 0:46 ` Robert A Duff 2014-10-27 2:18 ` Jeffrey Carter @ 2014-10-27 7:51 ` J-P. Rosen 1 sibling, 0 replies; 38+ messages in thread From: J-P. Rosen @ 2014-10-27 7:51 UTC (permalink / raw) Le 27/10/2014 01:46, Robert A Duff a écrit : > That might seem like a nitpick, but imagine the thing (PO or task) > alternates between the two states, and clients depend on that fact. > In the passive-task case, we have this weird in-between state in > which neither entry is open. And that's unlikely to be caught > by testing, because it's rare. In the PO case, we know for sure that > if the above conditional entry call finds Entry_1 closed, then Entry_2 > must be open (at that time). However, Entry_2 can close any time between the test of Entry_1 and whatever you want to do with that information. So it seems to me that it's a red herring... -- J-P. Rosen Adalog 2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00 http://www.adalog.fr ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: confusion about message passing between the tasks 2014-10-26 20:31 ` Robert A Duff 2014-10-26 20:36 ` Jeffrey Carter @ 2014-10-27 7:44 ` J-P. Rosen 1 sibling, 0 replies; 38+ messages in thread From: J-P. Rosen @ 2014-10-27 7:44 UTC (permalink / raw) Le 26/10/2014 21:31, Robert A Duff a écrit : > Robert A Duff <bobduff@shell01.TheWorld.com> writes: > >> OK, then I'll make a stronger claim: Everything you can do with >> rendezvous you can do with (something like) protected objects, >> and do it just as cleanly, and sometimes even better. > > ...but the other way around isn't true. Here's Tucker's example that > convinced me that some sort of "pragma Passive(Buffer_Task);" wasn't > going to cut it. Write a PO a that is in one of two states, > "accepting calls to Entry_1" and "accepting calls to Entry_2", > never in both states at the same time, and never in neither state > (as observed by callers). Pretty easy. With rendezvous, not so > much. > > - Bob > Huh? type states is (state1, state2); Current_State : States; ... loop select when Current_State = State1 => accept RDV1 do... end RDV1; when Current_State = State2 => accept RDV2 do ... end RDV2; end select; end loop; -- J-P. Rosen Adalog 2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00 http://www.adalog.fr ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: confusion about message passing between the tasks 2014-10-26 20:27 ` Robert A Duff 2014-10-26 20:31 ` Robert A Duff @ 2014-10-26 20:42 ` Dmitry A. Kazakov 2014-10-26 21:15 ` Brad Moore 2014-10-26 22:20 ` Robert A Duff 2014-10-27 7:40 ` J-P. Rosen 2 siblings, 2 replies; 38+ messages in thread From: Dmitry A. Kazakov @ 2014-10-26 20:42 UTC (permalink / raw) On Sun, 26 Oct 2014 16:27:34 -0400, Robert A Duff wrote: > "J-P. Rosen" <rosen@adalog.fr> writes: > >> Le 26/10/2014 00:23, Robert A Duff a écrit : >>> I prefer protected objects. Less coupling: two tasks can communicate >>> with each other with neither one knowing the identity of the other -- >>> they both just know about the protected object. >>> >>> If I were redesigning Ada from scratch, I'd leave out rendezvous. >>> Everything you can do with rendezvous you can do with (something like) >>> protected objects. >> >> ... and everything you can do with structured statements you can do with >> if and goto. > > OK, then I'll make a stronger claim: Everything you can do with > rendezvous you can do with (something like) protected objects, > and do it just as cleanly, and sometimes even better. You cannot program in a procedural way with PO. You can implement equivalent semantics, possibly, but not the program structure. An extreme scenario (unfortunately not Ada's annex E), a distributed system could be decomposed around rendezvous between tasks running on physically distributed nodes. This cannot be done with PO. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: confusion about message passing between the tasks 2014-10-26 20:42 ` Dmitry A. Kazakov @ 2014-10-26 21:15 ` Brad Moore 2014-10-27 9:22 ` Dmitry A. Kazakov 2014-10-26 22:20 ` Robert A Duff 1 sibling, 1 reply; 38+ messages in thread From: Brad Moore @ 2014-10-26 21:15 UTC (permalink / raw) On 2014-10-26 2:42 PM, Dmitry A. Kazakov wrote: > An extreme scenario (unfortunately not Ada's annex E), a distributed system > could be decomposed around rendezvous between tasks running on physically > distributed nodes. This cannot be done with PO. > Why not with Ada's annex E? For instance, you can have a remote access to class-wide type that is an interfaces, including protected interfaces and task interfaces. I have some examples of Remote buffers that have task interfaces in the dequesterity project. For instance calling the Read or Write interface primitives can result in a rendezvous with a remote task object. The same can be done with remote protected interfaces, and I have working examples of that as well. eg. generic type Element_Type is private; pragma Preelaborable_Initialization (Element_Type); ... package Buffers is pragma Pure; ... type Remote_Buffer_Interface is limited interface; function Read (From : Remote_Buffer_Interface) return Element_Type is abstract; procedure Write (To : in out Remote_Buffer_Interface; Item : Element_Type) is abstract; ... end Buffers; ... package Buffers.Active is pragma Pure; pragma Remote_Types; -- Not needed since implied by pragma Pure task type Buffer (Maximum_Capacity : Count_Type; Task_Priority : System.Priority; Maximum_Read_Block : Timeout_In_Milliseconds_Type; Maximum_Write_Block : Timeout_In_Milliseconds_Type; Maximum_Exclusive_Lock_Time : Timeout_In_Microseconds_Type) is new Vectored_Buffer_Interface with pragma Priority (Task_Priority); overriding entry Read (Item : out Element_Type); overriding entry Write (Item : Element_Type); ... end Buffer; .... end Buffers.Active; Brad ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: confusion about message passing between the tasks 2014-10-26 21:15 ` Brad Moore @ 2014-10-27 9:22 ` Dmitry A. Kazakov 0 siblings, 0 replies; 38+ messages in thread From: Dmitry A. Kazakov @ 2014-10-27 9:22 UTC (permalink / raw) On Sun, 26 Oct 2014 15:15:29 -0600, Brad Moore wrote: > On 2014-10-26 2:42 PM, Dmitry A. Kazakov wrote: >> An extreme scenario (unfortunately not Ada's annex E), a distributed system >> could be decomposed around rendezvous between tasks running on physically >> distributed nodes. This cannot be done with PO. > > Why not with Ada's annex E? For instance, you can have a remote access > to class-wide type that is an interfaces, including protected interfaces > and task interfaces. Yes, but I meant explicit entry calls, e.g. a timed entry call to the remote task instead of RPC. But the point is about the difference between tasks and PO. PO is semantically a system-wide thing even if its scope is narrower. PO does not respect its scope. This is a problem with all OO stuff actually. Dispatching tables disrespect scopes as well. This is not a big problem unless you start crossing process and partition borders. On the contrary, tasks are scope-friendly. There are issues with regard to the environment, especially considering I/O, but generally you can move a properly designed "clean" task from scope to scope and you can communicate tasks across high context boundaries. Things you cannot do with PO, at least, not without introducing "distributed PO". -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: confusion about message passing between the tasks 2014-10-26 20:42 ` Dmitry A. Kazakov 2014-10-26 21:15 ` Brad Moore @ 2014-10-26 22:20 ` Robert A Duff 1 sibling, 0 replies; 38+ messages in thread From: Robert A Duff @ 2014-10-26 22:20 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes: > You cannot program in a procedural way with PO. You can implement > equivalent semantics, possibly, but not the program structure. > > An extreme scenario (unfortunately not Ada's annex E), a distributed system > could be decomposed around rendezvous between tasks running on physically > distributed nodes. This cannot be done with PO. I implemented such a system (distributed tasks) for Ada 83. The main problem is shared variables: In Ada, you can't tell which variables are shared. And shared variables across a distributed system either don't work, or are grossly inefficient. Annex E solves that problem: No shared variables across partitions (except in the special case of Shared_Passive, which presumes the partitions are on the same machine, so can map shared areas of memory). - Bob ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: confusion about message passing between the tasks 2014-10-26 20:27 ` Robert A Duff 2014-10-26 20:31 ` Robert A Duff 2014-10-26 20:42 ` Dmitry A. Kazakov @ 2014-10-27 7:40 ` J-P. Rosen 2 siblings, 0 replies; 38+ messages in thread From: J-P. Rosen @ 2014-10-27 7:40 UTC (permalink / raw) Le 26/10/2014 21:27, Robert A Duff a écrit : > In Ada 83, I found that in between every pair of communicating tasks, > I wanted to add a passive "buffer" task or some such. I'm happy > to use a PO there. This may be the core point where we disagree. Presumably, you are more "mailbox" oriented than "client-server" oriented. This is perfectly respectable, but not everybody sees things this way, and if you design with a client-server model, the rendezvous is much more appropriate. I don't argue that YOU need mainly POs; just that other designs need rendezvous, and Ada is supposed to support all programming methodologies. -- J-P. Rosen Adalog 2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00 http://www.adalog.fr ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: confusion about message passing between the tasks 2014-10-24 16:44 confusion about message passing between the tasks compguy45 ` (3 preceding siblings ...) 2014-10-25 17:25 ` Dennis Lee Bieber @ 2014-10-25 23:42 ` compguy45 2014-10-25 23:55 ` compguy45 4 siblings, 1 reply; 38+ messages in thread From: compguy45 @ 2014-10-25 23:42 UTC (permalink / raw) figured it out....sorry bad post ): ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: confusion about message passing between the tasks 2014-10-25 23:42 ` compguy45 @ 2014-10-25 23:55 ` compguy45 2014-10-26 0:24 ` Jeffrey Carter 2014-10-26 15:40 ` Simon Wright 0 siblings, 2 replies; 38+ messages in thread From: compguy45 @ 2014-10-25 23:55 UTC (permalink / raw) i am trying here to increase by 1 in accept block and execute until its 75... why variable k doesnt keep its increased value once accept block is done? 15 16 17 18 task body Counter_Task is 19 V : Integer := 0; 20 begin 21 loop 22 select 23 accept Get (Check : Integer ; Value : out Integer) do 24 -- put("Value of Check is "); put(Check);new_line; 25 V := Check; 26 V := V + 1; 27 Value := V; 28 put("Value V the accept block is ");put(V);new_line; 29 end Get; 30 or 31 terminate; 32 end select; 33 end loop; 34 end Counter_Task; 35 36 begin 37 i := 0; 38 k := 0; 39 delay 1.00; 40 while k /= 75 loop 41 p.Get(i,k); 42 put("Value at the end of the begin block is ");put(i);new_line; 43 44 end loop; 45 46 47 end strib1; ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: confusion about message passing between the tasks 2014-10-25 23:55 ` compguy45 @ 2014-10-26 0:24 ` Jeffrey Carter 2014-10-26 0:41 ` compguy45 2014-10-26 15:40 ` Simon Wright 1 sibling, 1 reply; 38+ messages in thread From: Jeffrey Carter @ 2014-10-26 0:24 UTC (permalink / raw) On 10/25/2014 04:55 PM, compguy45@gmail.com wrote: > i am trying here to increase by 1 in accept block and execute until its 75... > why variable k doesnt keep its increased value once accept block is done? > > 18 task body Counter_Task is > 19 V : Integer := 0; > 20 begin > 21 loop > 22 select > 23 accept Get (Check : Integer ; Value : out Integer) do > 24 -- put("Value of Check is "); put(Check);new_line; > 25 V := Check; > 26 V := V + 1; > 27 Value := V; > 28 put("Value V the accept block is ");put(V);new_line; > 29 end Get; > 30 or > 31 terminate; > 32 end select; > 33 end loop; > 34 end Counter_Task; > 36 begin > 37 i := 0; > 38 k := 0; > 39 delay 1.00; > 40 while k /= 75 loop > 41 p.Get(i,k); This effectively does K := I + 1; and I never changes. In another post: > 23 accept Get (Value : out Integer) do > 24 put("Value of parametar passed in is ");put(Value); > --Why am i getting zero printed??? Nothing is passed in. Value is an out parameter of a pass-by-copy type. It begins with an undefined value, and its value at the end of the accept is copied into the actual parameter. -- Jeff Carter "Your mother was a hamster and your father smelt of elderberries." Monty Python & the Holy Grail 06 ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: confusion about message passing between the tasks 2014-10-26 0:24 ` Jeffrey Carter @ 2014-10-26 0:41 ` compguy45 2014-10-26 11:30 ` Brian Drummond 0 siblings, 1 reply; 38+ messages in thread From: compguy45 @ 2014-10-26 0:41 UTC (permalink / raw) how do i modify it so it works? ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: confusion about message passing between the tasks 2014-10-26 0:41 ` compguy45 @ 2014-10-26 11:30 ` Brian Drummond 0 siblings, 0 replies; 38+ messages in thread From: Brian Drummond @ 2014-10-26 11:30 UTC (permalink / raw) On Sat, 25 Oct 2014 17:41:37 -0700, compguy45 wrote: > how do i modify it so it works? If you want to use the input value of an argument, declare as mode in. If you want to pass a value out via an argument, declare as mode out. If you want to do both, declare the argument as mode in out. - Brian ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: confusion about message passing between the tasks 2014-10-25 23:55 ` compguy45 2014-10-26 0:24 ` Jeffrey Carter @ 2014-10-26 15:40 ` Simon Wright 1 sibling, 0 replies; 38+ messages in thread From: Simon Wright @ 2014-10-26 15:40 UTC (permalink / raw) compguy45@gmail.com writes: > 22 select > 23 accept Get (Check : Integer ; Value : out Integer) do Make it "Value : in out Integer" (because you need to know the current value). > 24 -- put("Value of Check is "); put(Check);new_line; > 25 V := Check; Here is the nub of your problem: you always assign Check to V (and your calling code always has Check = 0). Delete this line. > 26 V := V + 1; And this line. And the declaration of V. > 27 Value := V; Make this line Value := Value + 1; > 28 put("Value V the accept block is ");put(V);new_line; And make this Put(Value). > 29 end Get; > ^ permalink raw reply [flat|nested] 38+ messages in thread
end of thread, other threads:[~2014-10-27 9:22 UTC | newest] Thread overview: 38+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2014-10-24 16:44 confusion about message passing between the tasks compguy45 2014-10-24 18:39 ` Ludovic Brenta 2014-10-25 1:51 ` compguy45 2014-10-25 7:13 ` Ludovic Brenta 2014-10-24 23:49 ` Stribor40 2014-10-25 7:03 ` Ludovic Brenta 2014-10-25 7:58 ` Simon Wright 2014-10-25 13:01 ` compguy45 2014-10-25 14:11 ` Simon Wright 2014-10-25 17:25 ` Dennis Lee Bieber 2014-10-25 17:54 ` Jeffrey Carter 2014-10-25 22:23 ` Robert A Duff 2014-10-25 23:26 ` compguy45 2014-10-26 4:50 ` Dennis Lee Bieber 2014-10-26 10:20 ` Georg Bauhaus 2014-10-26 5:37 ` J-P. Rosen 2014-10-26 8:14 ` Pascal Obry 2014-10-26 15:47 ` J-P. Rosen 2014-10-26 20:27 ` Robert A Duff 2014-10-26 20:31 ` Robert A Duff 2014-10-26 20:36 ` Jeffrey Carter 2014-10-26 22:27 ` Robert A Duff 2014-10-26 23:23 ` Jeffrey Carter 2014-10-27 0:46 ` Robert A Duff 2014-10-27 2:18 ` Jeffrey Carter 2014-10-27 7:51 ` J-P. Rosen 2014-10-27 7:44 ` J-P. Rosen 2014-10-26 20:42 ` Dmitry A. Kazakov 2014-10-26 21:15 ` Brad Moore 2014-10-27 9:22 ` Dmitry A. Kazakov 2014-10-26 22:20 ` Robert A Duff 2014-10-27 7:40 ` J-P. Rosen 2014-10-25 23:42 ` compguy45 2014-10-25 23:55 ` compguy45 2014-10-26 0:24 ` Jeffrey Carter 2014-10-26 0:41 ` compguy45 2014-10-26 11:30 ` Brian Drummond 2014-10-26 15:40 ` Simon Wright
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox