1. windows threads work!!

In the past I tested threads in euphoria without any success. At my first try
and didn't insist because At that time i thought it was a limitation of euphoria
interpreter.
But this morning reading "windows internals" I learned that windows create a new
stack for each thread a process create. if so multithread should in euphoria!
I decided to revisit it and IT WORKED!!

-- testing windows system threads in euphoria

without warning

include misc.e
include machine.e
include dll.e

constant kernel32=open_dll("kernel32.dll")

if kernel32 = -1 then 
  puts(1,"failed to open kernel32.dll\n")
  abort(1)
end if

constant
iCreateThread=define_c_func(kernel32,"CreateThread",{C_POINTER,C_UINT,C_POINTER,C_POINTER,C_UINT,C_POINTER},C_UINT),
  iSleep=define_c_proc(kernel32,"Sleep",{C_UINT}),
  iCloseHandle = define_c_func(kernel32,"CloseHandle",{C_UINT},C_UINT)
  
global function CreateThread(atom lpThreadAttributes,
atom dwStackSize,  -- initial thread stack size, in
                            bytes
atom lpStartAddress,      -- pointer to thread
                            function
                            atom lpParameter, -- argument for new thread 
                            atom dwCreationFlags,      -- creation flags 
atom lpThreadId  -- pointer to returned thread
                            identifier
                            )
return
  c_func(iCreateThread,{lpThreadAttributes,dwStackSize,lpStartAddress,lpParameter,dwCreationFlags,lpThreadId})
end function --CreateThread()

global function CloseHandle(atom handle)
  return c_func(iCloseHandle,{handle})
end function -- CloseHandle()

global procedure Sleep(integer ms)
  c_proc(iSleep,{ms})
end procedure


object fnVal
atom counter, spinlock

counter = 0
spinlock = 0


function IncCounter(atom param)-- the thread function
while 1 do
  if spinlock = 1 then
    counter +=1
    if counter = 10 then spinlock = 2 return 0 end if
    spinlock = 0
  else
    --sleep(500)  this does not work
    Sleep(500)
  end if
end while
end function

atom lpStartAddress   lpStartAddress = call_back(routine_id("IncCounter")) 
atom lpThreadId  lpThreadId = allocate(4)
atom lpParam   lpParam = allocate(4)  poke4(lpParam,0)
atom hThread

hThread = CreateThread(0,0,lpStartAddress,lpParam,0,lpThreadId)
printf(1,"thread handle\n", hThread)
if not hThread then  puts(1, "echec creation thread\n") abort(0) end if

while spinlock < 2 do
 if not spinlock then
   ? counter
   spinlock = 1 
 end if
end while

fnVal = CloseHandle(hThread)


Regards,
Jacques Deschênes

new topic     » topic index » view message » categorize

2. Re: windows threads work!!

jacques deschênes wrote:
> 
> 
> In the past I tested threads in euphoria without any success. At my first try
> and didn't insist because At that time i thought it was a limitation of
> euphoria
> interpreter.
> But this morning reading "windows internals" I learned that windows create a
> new stack for each thread a process create. if so multithread should in
> euphoria!
> I decided to revisit it and IT WORKED!!
> 
> }}}
<eucode>
> -- testing windows system threads in euphoria
> 
> without warning
> 
> include misc.e
> include machine.e
> include dll.e
> 
> constant kernel32=open_dll("kernel32.dll")
> 
> if kernel32 = -1 then 
>   puts(1,"failed to open kernel32.dll\n")
>   abort(1)
> end if
> 
> constant
>  
>   iCreateThread=define_c_func(kernel32,"CreateThread",{C_POINTER,C_UINT,C_POINTER,C_POINTER,C_UINT,C_POINTER},C_UINT),
>   iSleep=define_c_proc(kernel32,"Sleep",{C_UINT}),
>   iCloseHandle = define_c_func(kernel32,"CloseHandle",{C_UINT},C_UINT)
>   
> global function CreateThread(atom lpThreadAttributes,
>                             atom dwStackSize,  -- initial thread stack size,
>                             in bytes
>                             atom lpStartAddress,      -- pointer to thread
>                             function
>                             atom lpParameter, -- argument for new thread 
>                             atom dwCreationFlags,      -- creation flags 
>                             atom lpThreadId  -- pointer to returned thread
>                             identifier
>                             )
>   return
>   c_func(iCreateThread,{lpThreadAttributes,dwStackSize,lpStartAddress,lpParameter,dwCreationFlags,lpThreadId})
> end function --CreateThread()
> 
> global function CloseHandle(atom handle)
>   return c_func(iCloseHandle,{handle})
> end function -- CloseHandle()
> 
> global procedure Sleep(integer ms)
>   c_proc(iSleep,{ms})
> end procedure
> 
> 
> object fnVal
> atom counter, spinlock
> 
> counter = 0
> spinlock = 0
> 
> 
> function IncCounter(atom param)-- the thread function
> while 1 do
>   if spinlock = 1 then
>     counter +=1
>     if counter = 10 then spinlock = 2 return 0 end if
>     spinlock = 0
>   else
>     --sleep(500)  this does not work
>     Sleep(500)
>   end if
> end while
> end function
> 
> atom lpStartAddress   lpStartAddress = call_back(routine_id("IncCounter")) 
> atom lpThreadId  lpThreadId = allocate(4)
> atom lpParam   lpParam = allocate(4)  poke4(lpParam,0)
> atom hThread
> 
> hThread = CreateThread(0,0,lpStartAddress,lpParam,0,lpThreadId)
> printf(1,"thread handle\n", hThread)
> if not hThread then  puts(1, "echec creation thread\n") abort(0) end if
> 
> while spinlock < 2 do
>  if not spinlock then
>    ? counter
>    spinlock = 1 
>  end if
> end while
> 
> fnVal = CloseHandle(hThread)
> </eucode>
{{{

> 
> Regards,
> Jacques Deschênes

Hi Jacques,

I tried using threads a long time ago too with Euphoria without 
success, so i decided to try you new version here, but it didnt
work for me (WinXP SP1).  I got an error:
 "EXW had a problem and had to close".
Any ideas what might be wrong?
Also, what op sys are you using, 95,98,2000, or XP ?


Take care,
Al

E boa sorte com sua programacao Euphoria!


My bumper sticker: "I brake for LED's"

 From "Black Knight":
"I can live with losing the good fight,
 but i can not live without fighting it".
"Well on second thought, maybe not."

new topic     » goto parent     » topic index » view message » categorize

3. Re: windows threads work!!

On Mon, 10 Jul 2006 07:00:41 -0700, jacques desch=EAnes
<guest at RapidEuphoria.com> wrote:

>In the past I tested threads in euphoria without any success. At my
>first try and didn't insist because At that time i thought it was a
>limitation of euphoria interpreter.
It is. Btw, your example does not run on 2.4.
>But this morning reading "windows internals" I learned that windows
>create a new stack for each thread a process create. if so multithread
>should in euphoria!
>I decided to revisit it and IT WORKED!!
If you use Eu to create pure windows/c_func threads then all will be
fine. However Eu vars are not held on the windows stack, so using Eu
code will fail; eg in function IncCounter after while 1 do add:
if not equal(lower("AAA"),"aaa") then
    puts(1,"lower(AAA)!=aaa\n")
    if getc(0) then end if
    abort(0)
 end if

and after while spinlock < 2 do add:
if not equal(lower("BBB"),"bbb") then
    puts(1,"lower(BBB)!=bbb\n")
    if getc(0) then end if
    abort(0)
 end if

Also, replace Sleep(500) with c_proc(iSleep,{500}) to avoid an almost
inevitable type check on ms.
The resulting program will fail or crash at random.

TDLL in the archives shows how you can multi-OS-thread C/asm code from
Eu, but you cannot multi-OS-thread Eu code, not without doing
something like converting it to a dll first.

Regards,
Pete
PS It is also not as simple as two threads calling the same routine
(lower) simultaneously; the glitch in Sleep() shows it is re-using
internal temporaries or something; if you comment out the lower call
inside IncCounter, it works until the end, but the 'return 0' seems to
spanner the last lower call from the main pgm.

PPS Al: the example did not work for me at all on Eu 2.4 but did on Eu
2.5 (on win98), until as above I replaced Sleep() with c_func and then
2.4 nearly got to the end before crashing blink)

new topic     » goto parent     » topic index » view message » categorize

4. Re: windows threads work!!

Hi Al,
I use windows xp pro with sp2. And run it many times on it without any problem.
So I can't  say why it work on my computer and not yours.

regards,
Jacques Deschênes

new topic     » goto parent     » topic index » view message » categorize

5. Re: windows threads work!!

Hi Pete,
I modified my sample code adding the code you suggested but don't get any crash.
But the line puts(1,"lower(AAA)!=aaa\n") doesn't print anything.
Further reading form MSDN learned me that C run time library (CRT) must be a
multi-threaded version for a program using multi-thread with CRT functions to
work properly.
I think that those functions of euphoria that fails are those that call crt
functions and I guess
that exwc.exe version 2.5 is not linked with a multi-threaded version of CRT.

Concerning euphoria variables not being accesible by the thread function, its
wrong.  A thread function is a callback function like any windows functions and
it can access all euphoria object.
In my example spinlock and counter are euphoria global variables and
IncCounter() access them successfully.

In fact the only problem here is the fact that the euphoria interpreter is not
linked with a multi-threaded version of CRT.
By the way it work without any crash on my machine because all CRT dll that
comes with windows xp are multi-threaded versions.
But it fail with crt functions that are statically linked with exwc.exe

Maybe Robert Craig could confirm my hypothesis about static linkage of CRT in
exwc.exe

Regards,
Jacques Deschênes


Pete Lomax wrote:
> 
> On Mon, 10 Jul 2006 07:00:41 -0700, jacques desch=EAnes
> <guest at RapidEuphoria.com> wrote:
> 
> >In the past I tested threads in euphoria without any success. At my
> >first try and didn't insist because At that time i thought it was a
> >limitation of euphoria interpreter.
> It is. Btw, your example does not run on 2.4.
> >But this morning reading "windows internals" I learned that windows
> >create a new stack for each thread a process create. if so multithread
> >should in euphoria!
> >I decided to revisit it and IT WORKED!!
> If you use Eu to create pure windows/c_func threads then all will be
> fine. However Eu vars are not held on the windows stack, so using Eu
> code will fail; eg in function IncCounter after while 1 do add:
> }}}
<eucode>
>  if not equal(lower("AAA"),"aaa") then
>     puts(1,"lower(AAA)!=aaa\n")
>     if getc(0) then end if
>     abort(0)
>  end if
> </eucode>
{{{

> and after while spinlock < 2 do add:
> }}}
<eucode>
>  if not equal(lower("BBB"),"bbb") then
>     puts(1,"lower(BBB)!=bbb\n")
>     if getc(0) then end if
>     abort(0)
>  end if
> </eucode>
{{{

> Also, replace Sleep(500) with c_proc(iSleep,{500}) to avoid an almost
> inevitable type check on ms.
> The resulting program will fail or crash at random.
> 
> TDLL in the archives shows how you can multi-OS-thread C/asm code from
> Eu, but you cannot multi-OS-thread Eu code, not without doing
> something like converting it to a dll first.
> 
> Regards,
> Pete
> PS It is also not as simple as two threads calling the same routine
> (lower) simultaneously; the glitch in Sleep() shows it is re-using
> internal temporaries or something; if you comment out the lower call
> inside IncCounter, it works until the end, but the 'return 0' seems to
> spanner the last lower call from the main pgm.
> 
> PPS Al: the example did not work for me at all on Eu 2.4 but did on Eu
> 2.5 (on win98), until as above I replaced Sleep() with c_func and then
> 2.4 nearly got to the end before crashing blink)
> 
>

new topic     » goto parent     » topic index » view message » categorize

6. Re: windows threads work!!

jacques deschênes wrote:
> Maybe Robert Craig could confirm my hypothesis about static linkage of CRT in
> exwc.exe

exwc.exe (and exw.exe) are compiled with Watcom C, 
and they statically link with Watcom's standard C library.

You might be able to get O/S threads working in a few 
small programs, but there are some major problems
that will prevent operating system pre-emptive threads
from working *reliably*. As you are aware, the C run-time
library needs to be thread-safe, but Watcom's library is not.
On top of that, Euphoria's run-time routines are not thread
safe. For instance, Ref() and DeRef() operations are performed
all over the interpreter. If the O/S were to pre-emptively
switch to another thread in the middle of a Ref or DeRef,
the reference count on an object could get messed up, eventually
leading to a storage leak or a crash. A program might run
a hundred times successfully before crashing mysteriously on
the hundred and first run. I'd probably have to abandon 
reference counting, and go to garbage collection, as one step 
in supporting preemptive O/S threads. (Remember that Euphoria 3.0
pre-alpha already supports *cooperative* threads (tasks)).

Regards,
   Rob Craig
   Rapid Deployment Software
   http://www.RapidEuphoria.com

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu