Author | Topic: :InitClass() is not a sync method, it's a sync function | |
---|---|---|
Michael Hoffmann | :InitClass() is not a sync method, it's a sync function on Fri, 20 Jan 2012 11:12:01 +0100 Hello Alaskans, the following code has added some gray hair to my exquisit collection. It shows, that :InitClass() is not synchronized on class level but on program level. That means only one thread may execute :InitClass() code at one time in a program. Hence an :InitClass() that waits for an :Initclass() to be completed in another thread will lead to a deadlock. STATIC b_ready := .F. CLASS A EXPORTED: CLASS METHOD InitClass ENDCLASS CLASS METHOD A:InitClass ? "In A:InitCLass()" Thread():New():Start({||B()}) DO WHILE .NOT. b_ready Sleep(100) ENDDO RETURN self CLASS B EXPORTED: CLASS METHOD InitClass ENDCLASS CLASS METHOD B:InitClass ? "In B:InitCLass()" b_ready := .T. RETURN self FUNCTION Main A() ? "Done!" Inkey(0) RETURN NIL | |
Michael Hoffmann | Re: :InitClass() is not a sync method, it's a sync function on Fri, 20 Jan 2012 15:31:24 +0100 ... even more gray hair. Calling a class function collides with any :InitClass() in any other thread. Bottom line: If you have an :InitClass() that takes a little longer, every other thread will cease to run when it tries to access any other class, e.g. to create an instance, until the lengthy :InitClass() is done. Here's the code to illustrate the situation... STATIC b_ready := .F. CLASS A EXPORTED: CLASS METHOD InitClass ENDCLASS CLASS METHOD A:InitClass ? "In A:InitCLass()" Thread():New():Start({||B(),b_ready := .T.}) DO WHILE .NOT. b_ready Sleep(100) ENDDO RETURN self CLASS B EXPORTED: CLASS METHOD InitClass ENDCLASS CLASS METHOD B:InitClass ? "In B:InitCLass()" RETURN self FUNCTION Main B() A() ? "Done!" Inkey(0) RETURN NIL | |
Jorge L | Re: :InitClass() is not a sync method, it's a sync function on Fri, 20 Jan 2012 12:29:26 -0300 Hi Michael You should not to use the clause SYNC in your method ? "Michael Hoffmann" escribió en el mensaje de noticias:1d19c00b$38a20e2f$b069e@news.alaska-software.com... ... even more gray hair. Calling a class function collides with any :InitClass() in any other thread. Bottom line: If you have an :InitClass() that takes a little longer, every other thread will cease to run when it tries to access any other class, e.g. to create an instance, until the lengthy :InitClass() is done. Here's the code to illustrate the situation... STATIC b_ready := .F. CLASS A EXPORTED: CLASS METHOD InitClass ENDCLASS CLASS METHOD A:InitClass ? "In A:InitCLass()" Thread():New():Start({||B(),b_ready := .T.}) DO WHILE .NOT. b_ready Sleep(100) ENDDO RETURN self CLASS B EXPORTED: CLASS METHOD InitClass ENDCLASS CLASS METHOD B:InitClass ? "In B:InitCLass()" RETURN self FUNCTION Main B() A() ? "Done!" Inkey(0) RETURN NIL | |
Jorge L | Re: :InitClass() is not a sync method, it's a sync function on Fri, 20 Jan 2012 12:55:57 -0300 HI again What i want to say..., if it is not better to initialize the thread first and then to use sync method regards "Michael Hoffmann" escribió en el mensaje de noticias:1d19c00b$38a20e2f$b069e@news.alaska-software.com... ... even more gray hair. Calling a class function collides with any :InitClass() in any other thread. Bottom line: If you have an :InitClass() that takes a little longer, every other thread will cease to run when it tries to access any other class, e.g. to create an instance, until the lengthy :InitClass() is done. Here's the code to illustrate the situation... STATIC b_ready := .F. CLASS A EXPORTED: CLASS METHOD InitClass ENDCLASS CLASS METHOD A:InitClass ? "In A:InitCLass()" Thread():New():Start({||B(),b_ready := .T.}) DO WHILE .NOT. b_ready Sleep(100) ENDDO RETURN self CLASS B EXPORTED: CLASS METHOD InitClass ENDCLASS CLASS METHOD B:InitClass ? "In B:InitCLass()" RETURN self FUNCTION Main B() A() ? "Done!" Inkey(0) RETURN NIL | |
Michael Hoffmann | Re: :InitClass() is not a sync method, it's a sync function on Fri, 20 Jan 2012 17:41:27 +0100 Hello Jorge, :InitClass() works very much like a sync class method in case the class function is called on multiple threads at the same time. One thread must "win" in this siutation, create the class object and run the :InitClass() method for the class object. The call to the class function on the other thread will then return the same (already initialized) class object. Hence :InitClass() is very much like a sync method. However, according to my second example, the class function appears to be the synced code, which is even worse, because even if the class has already been initialized, the call to the class function will lead to a standstill of the calling thread in case any other thread is executing :InitClass() code. Run the program and try to understand the implications. Any :InitClass() code running? => No class objects can be created and every call to the class function (e.g. MyClass():New()) in any other thread freze your program for this time. Best regards, Michael | |
Jorge L | Re: :InitClass() is not a sync method, it's a sync function on Fri, 20 Jan 2012 19:56:29 -0300 Hi Michael, thanks for the explanation It would not throw the class directly, but his reference CLASS METHOD A:InitClass Local K1 ? "In A:InitCLass()" K1 := B() take the reference Thread():New():Start({|| K1 }, b_ready := .T. ) DO WHILE .NOT. b_ready Sleep(100) ENDDO RETURN self "Michael Hoffmann" escribió en el mensaje de noticias:2c020941$21ecffc6$bf384@news.alaska-software.com... Hello Jorge, :InitClass() works very much like a sync class method in case the class function is called on multiple threads at the same time. One thread must "win" in this siutation, create the class object and run the :InitClass() method for the class object. The call to the class function on the other thread will then return the same (already initialized) class object. Hence :InitClass() is very much like a sync method. However, according to my second example, the class function appears to be the synced code, which is even worse, because even if the class has already been initialized, the call to the class function will lead to a standstill of the calling thread in case any other thread is executing :InitClass() code. Run the program and try to understand the implications. Any :InitClass() code running? => No class objects can be created and every call to the class function (e.g. MyClass():New()) in any other thread freze your program for this time. Best regards, Michael | |
Michael Hoffmann | Re: :InitClass() is not a sync method, it's a sync function on Sat, 21 Jan 2012 12:00:12 +0100 Hello Jorge, thanks for your help. I know how to fix this particular problem, the code I posted was oversimplified to illustrate the problem. In reality your problem won''t be as simple as that and you will be wondering why your program stops to run because some background thread is stuck doing an InitClass on a class completely unrelated to the rest of your program. This is like parachute jumping next to an alligator farm: Trouble waiting to happen. Consider this: As long as my A:InitClass() is running on one thread (and that might take some time, because it must wait for B to be ready), you won't be able to call the class function on any other class on any other thread in your program, which would mean that this will stop your program when it does this: a := MyClass():New() or maybe xbp := XbpStatic():New(). In other words: Why should anything I do with class A influence anything I do with class B when they are otherwise unrelated? Best regards, Michael "Jorge L" <jlborlando@way.com.ar> wrote in message news:5a6bf3c2$35ffb48a$c8029@news.alaska-software.com... > Hi Michael, thanks for the explanation > > It would not throw the class directly, but his reference > > CLASS METHOD A:InitClass > Local K1 > ? "In A:InitCLass()" > K1 := B() take the reference > Thread():New():Start({|| K1 }, b_ready := .T. ) > DO WHILE .NOT. b_ready > Sleep(100) > ENDDO > RETURN self > > > > > "Michael Hoffmann" escribi en el mensaje de > noticias:2c020941$21ecffc6$bf384@news.alaska-software.com... > > Hello Jorge, > > :InitClass() works very much like a sync class method in case the class > function is called on multiple threads at the same time. One thread must > "win" in this siutation, create the class object and run the :InitClass() > method for the class object. The call to the class function on the other > thread will then return the same (already initialized) class object. Hence > :InitClass() is very much like a sync method. However, according to my > second example, the class function appears to be the synced code, which is > even worse, because even if the class has already been initialized, the > call > to the class function will lead to a standstill of the calling thread in > case any other thread is executing :InitClass() code. > > Run the program and try to understand the implications. Any :InitClass() > code running? => No class objects can be created and every call to the > class > function (e.g. MyClass():New()) in any other thread freze your program for > this time. > > Best regards, > Michael > |