Hi Andreas,
I'm sorry to be resurrecting this thread but my mind often thinks about these things while trying to get to sleep. Anyway I hope my suggestions will be of value. I am presenting two similar suggestions. They both accept your desire to have the new process (or at least the block of the new process) wait to run until after the calling process can run and save the result of the #fork message. The first is closest to your suggestion. Instead of a helper process it wraps the block being forked in a block that delays running of the forked block until there are no processes ready to run for the same priority. I think this is equivalent to the helper process of a lower priority waiting to run. The second suggestion also wraps the block being forked in a block that delays running of the forked block but does so by pushing itself to the back of the ready to run list for its priority twice. This should be enough to insure the calling process has run and saved the result of the #fork message. I'm not looking for any kind of a fight/trouble, I just thought these might be an interesting alternative. Lou "Suggestion 1 from Lou" BlockContext>>forkAt: priority "Create and schedule a Process running the code in the receiver at the given priority. Answer the newly created process." | forkedProcess helperBlock | helperBlock := [ [(Processor waitingProcessesAt: priority) notEmpty] whileTrue: [Processor yield]. self value. ]. forkedProcess := Process forContext: helperBlock priority: priority. ^forkedProcess resume. "Suggestion 2 from Lou" BlockContext>>forkAt: priority "Create and schedule a Process running the code in the receiver at the given priority. Answer the newly created process." | forkedProcess helperBlock | helperBlock := [ Processor yield. Processor yield. self value. ]. forkedProcess := Process forContext: helperBlock priority: priority. ^forkedProcess resume. "Suggestion from Andreas" BlockContext>>forkAt: priority "Create and schedule a Process running the code in the receiver at the given priority. Answer the newly created process." | forkedProcess helperProcess | forkedProcess := self newProcess. forkedProcess priority: priority. priority = Processor activePriority ifTrue:[ helperProcess := [forkedProcess resume] newProcess. helperProcess priority: priority-1. helperProcess resume. ] ifFalse:[ forkedProcess resume ]. "Original code" BlockContext>>forkAt: priority "Create and schedule a Process running the code in the receiver at the given priority. Answer the newly created process." | forkedProcess | forkedProcess := self newProcess. forkedProcess priority: priority. ^ forkedProcess resume ----------------------------------------------------------- Louis LaBrunda Keystone Software Corp. SkypeMe callto://PhotonDemon mailto:[hidden email] http://www.Keystone-Software.com |
Allow me to add my suggestion, which i hope will let you sleep at nights :)
BlockContext>>forkAt: priority "Create and schedule a Process running the code in the receiver at the given priority. Answer nil." | forkedProcess | forkedProcess := self newProcess. forkedProcess priority: priority. forkedProcess resume. ^ nil BlockContext>>fork "Create and schedule a Process running the code in the receiver." self newProcess resume. ^ nil These changes will stop forks from being used in wrong manner and effectively eliminate the problem of "letting fork initiator process to run little bit more to assign returned value anywhere". -- Best regards, Igor Stasenko AKA sig. |
Oh.. and for those, who may wants use new process instance:
BlockContext>>forkAfterInitWith: aBlock | proc | proc := self newProcess. aBlock value: proc. proc resume. ^ nil --- so, you can write: [ ....] forkAfterInitWith: [:process | process priority: 100. process name: 'my forked process' ]. -- Best regards, Igor Stasenko AKA sig. |
In reply to this post by Igor Stasenko
> BlockContext>>fork > "Create and schedule a Process running the code in the receiver." > self newProcess resume. > ^ nil > > These changes will stop forks from being used in wrong manner and > effectively eliminate the problem of "letting fork initiator process > to run little bit more to assign returned value anywhere". I sort of agree (at least on the intent, of course this will break code). However, I will point out that problematic uses are only those who use the #fork return value in a different, already running process. For example, this code is tricky but not racy, because the second process isn't started until delayProcess is assigned: delayProcess := [ (Delay forMilliseconds: msec) wait. sema signal. Processor activeProcess suspend ] fork ]. [[aBlock value] ensure: [delayProcess terminate. sema signal]] fork. sema wait. but with the sort-of-proposed change to #fork the user could be tempted to write it like this: [ delayProcess := Processor activeProcess. (Delay forMilliseconds: msec) wait. sema signal. Processor activeProcess suspend ] fork ]. [[aBlock value] ensure: [delayProcess terminate. sema signal]] fork. sema wait. and the latter *is* racy. Paolo |
In reply to this post by Louis LaBrunda
Of course, #1 may never run the context if there is a process that only
tields and doesn't wait (via delay or semaphore)... [[true] whileTrue: [Processor yield]] fork. [(Processor waitingProcessesAt: Processor activeProcess priority) notEmpty] whileTrue: [Processor yield]. self inform: 'waiting ends' :-) Gary > > Lou > > "Suggestion 1 from Lou" > BlockContext>>forkAt: priority > "Create and schedule a Process running the code in the receiver > at the given priority. Answer the newly created process." > | forkedProcess helperBlock | > > helperBlock := [ > [(Processor waitingProcessesAt: priority) notEmpty] > whileTrue: [Processor > yield]. > self value. > ]. > forkedProcess := Process forContext: helperBlock priority: > priority. > ^forkedProcess resume. > > > |
In reply to this post by Paolo Bonzini-2
On 03/03/2008, Paolo Bonzini <[hidden email]> wrote:
> > > BlockContext>>fork > > "Create and schedule a Process running the code in the receiver." > > self newProcess resume. > > ^ nil > > > > These changes will stop forks from being used in wrong manner and > > effectively eliminate the problem of "letting fork initiator process > > to run little bit more to assign returned value anywhere". > > > I sort of agree (at least on the intent, of course this will break > code). However, I will point out that problematic uses are only those > who use the #fork return value in a different, already running process. > > For example, this code is tricky but not racy, because the second > process isn't started until delayProcess is assigned: > > delayProcess := [ > (Delay forMilliseconds: msec) wait. > sema signal. > Processor activeProcess suspend ] fork ]. > > [[aBlock value] ensure: [delayProcess terminate. sema signal]] fork. > sema wait. > > but with the sort-of-proposed change to #fork the user could be tempted > to write it like this: > > [ > delayProcess := Processor activeProcess. > (Delay forMilliseconds: msec) wait. > sema signal. > Processor activeProcess suspend ] fork ]. > > [[aBlock value] ensure: [delayProcess terminate. sema signal]] fork. > sema wait. > > and the latter *is* racy. > In this case, i would tell people to read something about Concurrent Programming before try any coding. Oh, i giving up. All these patches failing into category: 'selling 2 wheeled bike with 3rd wheel mounted for safety'. There is little you can do to help people writing good concurrent code by providing such patches which hiding problems under the hood. Programmer is not a baby who needs to wear Pampers. > > Paolo > > -- Best regards, Igor Stasenko AKA sig. |
Then, maybe we should go another way,
by modifying compiler and if it finds selectors #fork, #forkAt: used in code, then it shows a big red warning which says: - this method using forks, please check your code twice against concurrency issues before submitting code. Presse 'yes' to continue and after user pressing 'yes', shows another: - are you sure you still want to accept code which using forks? Press 'yes' to not accept this code. :) -- Best regards, Igor Stasenko AKA sig. |
On Mar 3, 2008, at 11:53 , Igor Stasenko wrote: > Then, maybe we should go another way, > by modifying compiler and if it finds selectors #fork, #forkAt: used > in code, then > it shows a big red warning which says: > - this method using forks, please check your code twice against > concurrency issues before submitting code. Presse 'yes' to continue > > and after user pressing 'yes', shows another: > > - are you sure you still want to accept code which using forks? Press > 'yes' to not accept this code. > > :) Nah, it should simply analyze the code and fix up any potential bugs. - Bert - |
On Mon, 03 Mar 2008 12:12:20 +0100, Bert Freudenberg wrote:
> > On Mar 3, 2008, at 11:53 , Igor Stasenko wrote: > >> Then, maybe we should go another way, >> by modifying compiler and if it finds selectors #fork, #forkAt: used >> in code, then >> it shows a big red warning which says: >> - this method using forks, please check your code twice against >> concurrency issues before submitting code. Presse 'yes' to continue >> >> and after user pressing 'yes', shows another: >> >> - are you sure you still want to accept code which using forks? Press >> 'yes' to not accept this code. >> >> :) > > Nah, it should simply analyze the code and fix up any potential bugs. And while it's at it, also solve all the performance problems in the code. /Klaus > - Bert - > > > > |
In reply to this post by Igor Stasenko
> In this case, i would tell people to read something about Concurrent > Programming before try any coding. Yes, and that's why I was against Andreas' patch in the first place. :-( Paolo |
In reply to this post by Igor Stasenko
Hi Igor,
On Sun, 2 Mar 2008 21:09:59 +0200, "Igor Stasenko" <[hidden email]> wrote: >snip >These changes will stop forks from being used in wrong manner and >effectively eliminate the problem of "letting fork initiator process >to run little bit more to assign returned value anywhere". I agree in part. I actually think fork shouldn't be changed at all. There is nothing wrong with fork returning the resulting process. The calling process and the new process shouldn't assume anything about the other having been run or not. I only came up with my alternative because I couldn't sleep. I wasn't losing sleeping trying to fine an alternative. Lou ----------------------------------------------------------- Louis LaBrunda Keystone Software Corp. SkypeMe callto://PhotonDemon mailto:[hidden email] http://www.Keystone-Software.com |
In reply to this post by Gary Chambers-4
Hi Gary,
On Mon, 3 Mar 2008 10:17:53 -0000, "Gary Chambers" <[hidden email]> wrote: >Of course, #1 may never run the context if there is a process that only >tields and doesn't wait (via delay or semaphore)... > >[[true] whileTrue: [Processor yield]] fork. >[(Processor waitingProcessesAt: Processor activeProcess priority) notEmpty] >whileTrue: [Processor >yield]. self inform: 'waiting ends' > >:-) >Gary Yes, and I think Andreas' solution would suffer the same problem. And would any code with a lower priority ever run. Lou ----------------------------------------------------------- Louis LaBrunda Keystone Software Corp. SkypeMe callto://PhotonDemon mailto:[hidden email] http://www.Keystone-Software.com |
Free forum by Nabble | Edit this page |