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.3 required=5.0 tests=BAYES_00,INVALID_MSGID autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,d1df6bc3799debed X-Google-Attributes: gid103376,public From: eachus@spectre.mitre.org (Robert I. Eachus) Subject: Re: Not intended for use in medical, Date: 1997/05/19 Message-ID: #1/1 X-Deja-AN: 243293885 References: <3.0.32.19970423164855.00746db8@mail.4dcomm.com><01bc6006$c13cf880$LocalHost@xhv46.dial.pipex.com><01bc6182$30e3a7c0$LocalHost@xhv46.dial.pipex.com> <01bc63a2$e3e1a940$LocalHost@xhv46.dial.pipex.com> Organization: The Mitre Corp., Bedford, MA. Newsgroups: comp.lang.ada Date: 1997-05-19T00:00:00+00:00 List-Id: In article mheaney@ni.net (Matthew Heaney) writes: > Funny you should bring that up. We just wrote a small application > with 10 tasks, where each one wakes up every 5 seconds to check a > randomly-generated temperature. In spite of the fact that each > task had its own generator, each one yielded the same value. This > was undoubtedly caused by the fact the each generator had been > (automatically) seeded with the same time. No. First read A.5.2(28). There is a single state which all generators are implicitly initialized to. This was really chosen on the assumption that any non-trivial user would use one of the Reset functions. An alternative would have been to have each new generator start in a state uncorrelated with any other, but as my previous message pointed out that is next to impossible for some generators. At this point, I think that the best idea would have been to require that the generators be set before being called by calling Reset and otherwise raising Program_Error. Read what I wrote in the previous article for one solution to this problem. Generate a seed from the clock--you can use the explicit generator that does this, but: Seed: Integer := Integer(Float(Seconds(Calendar.Clock) * 1000)) is probably enough. Now pass Seed, Seed+1, Seed+2, etc. to the appropriate version of Reset. Another solution is below: > Here's what we did to solve the problem, but it didn't work. > Instead of each task having its own generator, we made one > generator, and wrapped it in a protected object. When each task > woke up, it called a protected function that returned the random > value: > protected Generator is > function Random return Temperature; > private > G : Random_Temperatures.Generator; > end; > protected body Generator is > function Random return Temperature is > begin > return Random_Temperatures.Random (G); > end; > end; > I assumed each invokation of Generator.Random would return a > different random number (or at least random numbers evenly > distributed about the range of temperature), but this isn't so. > Every 5 seconds, all 10 tasks would wake up and call the protected > object. I thought that these 10 invokations would generate > different random values, but all 10 tasks received the same random > value. The value would change every 5 seconds, but all 10 tasks > would get that same value. Burned by the side effects of Random! The problem is that you have to access the generator from inside a protected procedure or entry since you can't afford to have several tasks accessing a function with side effects at the same time. Try: function Generator return Temperature; ... and in the body: protected Generator is procudure Protected_Random(Temp: out Temperature); private G : Random_Temperatures.Generator; end; function Random return Temperature is Temp: Temperature; begin Generator.Random(Temp); return Temp; end Random; protected body Generator is procedure Protected_Random(Temp: out Temperature) is begin Temp := Random_Temperatures.Random (G); return; end; end; -- Robert I. Eachus with Standard_Disclaimer; use Standard_Disclaimer; function Message (Text: in Clever_Ideas) return Better_Ideas is...