Jon:
here is the code of two programs that you should save (watch for
line-breaks).
The first program should be named "server.rex", the second
"useServer.rex". Invoke as
rexx useServer.rex [nrClients [useReplyInClientToo]]
... nrClients: if not given defaults to '1'
...useReplyInClientToo: if set to '1' (true), then the client
method 'requestCommand' won't wait for the completion of the request
but return using reply, adding additional Rexx threads of execution
If you have questions, then please ask. It should be fairly "easy" to
adapt the server code to your SQL-needs and using one instance of a
server from all parts of your ooDialog programs.
Regards
---rony
server-rexx-program:
------------------------------- "server.rex" (begin)
-------------------------------------
-- rgf, 2010-05-31, demonstrate a server that does its work on a separate thread
/* ****************************************************************************
*/
::class server public
::method init
expose busy requests stop nrOfProcessedRequests
busy=.false
requests=.queue~new
stop=.false
nrOfProcessedRequests=0
::attribute stop -- if set to .true, then "doTheWork" will stop working
::attribute busy -- indicates worker is busyly working
::attribute requests -- queue of command objects
::attribute nrOfProcessedRequests -- accumulator counting nr of processed
requests
::method string
expose busy
return self~objectName"@"self~identityHash"@TID:"getTId()"/busy="pp(busy)
::method startToWork unguarded -- worker method, runs on its own thred
expose busy requests stop nrOfProcessedRequests
say self", doTheWork() starting out on thread:" getTID() -- show TID this
runs
reply -- return to caller, start a new thread
say self", doTheWork(), after reply now running on thread:" getTID() -- show
TID this runs
self~setup -- e.g. create a database connection
do forever
say self": waiting for requests or stop ..."
guard on when requests~items>0 | stop=.true
say self": now running again, requests or stop occurred..."
if stop=.true then
do
say self": stop occurred, shutting down server..."
leave
end
busy=.true
do while requests~items>0 -- process all pending requests
workItem=requests~pull -- pull workItem object
self~processWorkItem(workItem) -- do whatever work has to be done
nrOfProcessedRequests+=1 -- increment counter
end
busy=.false
guard off
end
self~shutdown -- e.g. release a database connection
::method stopToWork -- cause the worker method to stop
expose stop
stop=.true
::method setup -- setup whatever the worker needs
say self": in method setup() ..."
::method shutdown -- shutdown whatever the worker has initiated
say self": in method shutdown() ..."
::method processWorkItem
use arg workItem
say self": in method processWorkItem(), workItem="pp(workItem) "..."
workItem~completed=.true -- indicate that work has completed on this workItem
/* ****************************************************************************
*/
::class WorkItem public
::method init
expose commandName arguments completed
use arg commandName, arguments
completed=.false
::attribute commandName -- any command the server understands
::attribute arguments -- any arguments to be processed in the command
::attribute completed -- indicate whether processing has completed
::method string
expose commandName arguments completed
return
self~objectName":commandName="commandName",arguments="arguments",completed="completed
/* ****************************************************************************
*/
::routine getTID public -- works only under Windows
if SysVersion()~left(1)="W" then
return SysQueryProcess("TID")
return "TID:n/a"
::routine pp public -- enclose string value in square brackets
parse arg val
return "["val"]"
------------------------------- "server.rex" (end)
---------------------------------------
client-rexx-program:
------------------------------- "useServer.rex" (begin)
-------------------------------------
-- rgf, 2010-05-31, demonstrate using a server that does its work on a separate
thread
parse arg maxClients useReply
if maxClients=""|\datatype(maxClients,"W") then
maxClients=1 -- default to one client
useReply=(useReply=.true)
parse source s
say "client-program:" s"/TID:"getTID()
say "client-program: using REPLY on the client object's
'requestCommand'-method?" pp(useReply)
say "--- client-program: creating and starting server..."
server=.server~new -- create one server
server~startToWork
say "--- client-program: creating" pp(maxClients) "clients using the server..."
clientArray=.array~new
do i=1 to maxClients
o=.client~new(server, useReply) -- create a client, supply server to use
clientArray~append(o) -- save it in the array
say o
o~requestCommand("sleep", "i-"random()) -- send a command
end
sleepTime=1
say "--- client-program: sleeping" sleepTime "sec"
call sysSleep sleepTime
say "--- client-program: after sleeping all client's requests should be
processed ..."
do o over clientArray
say o
end
say
say "--- client-program: stopping server..."
server~stopToWork
say "--- client-program: finished."
::requires server.rex
::class client public -- each client works on its own thread
::method init
expose server useReply
use arg server, useReply
::attribute server -- our single server
::method string
expose server
return
self~objectName"@"self~identityHash"@TID:"getTId()"/server~nrOfProcessedRequests="pp(server~nrOfProcessedRequests)
::method requestCommand -- request a service from the server
expose server useReply
if useReply then
reply -- we could also add multithreading here
use arg command, arguments
workItem=.WorkItem~new(command,arguments)
server~requests~queue(workItem)
-- say "workItem="pp(workItem) "requests in queue:" pp(server~requests~items)
say self": just added" pp(workItem)", now requests in queue:"
pp(server~requests~items)
------------------------------- "useServer.rex" (end)
---------------------------------------
------------------------------------------------------------------------------
_______________________________________________
Oorexx-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/oorexx-devel