The operating system provides function calls that allow me to activate and switch processing to one of these pre-start jobs. Because the job is already running, it starts almost instantaneously. All of this stuff is C api's.
May I ask you for some API names you're using?
The pre-start jobs are something I've never looked into, and I'm still hoping you would share those APIs with us.
but that means that all the other threads are shut down until processing is completed for that thread.
No it doesn't. Serialized means that the one program or procedure can only be entered by One Thread at a time, for the job.
The other threads can continue doing whatever they want. But if they need to run that "Serialized" procedure, then they will have to wait their turn.
it is a whole lot simpler to write it in RPG and just do a spawn of another RPG job.
I agree, it is much easier to just run SBMJOB. But that's because we are all already well versed in the use of the Multi-Process techniques used by RPG and SBMJOB.
The "easy" button in RPG was to just add:
Ctl-Opt THREAD(*SERIALIZE);
That tells the system the program is Single Threaded, and the system will automatically generate the appropriate controls so that the Multi-Threaded program only runs that Serialized program on one thread at a time.
The real sweet spot comes in when you use:
Ctl-Opt THREAD(*CONCURRENT);
Which means your program can be multi-threaded.
You want to stay away from any cycle code and global everything.
And if you use global data you will want to wrap access either through a sub-procedure or using multi thread constructs like semaphores.
I've used it in Linear Main procedures easy enough.
"Ctl-Opt THREAD(*CONCURRENT);" is set Globally. Once that is set then the system assumes all subprocedures are threaded.
The easy way in RPG to control access to the global shared data is to use a Serialized sub procedure.
IBM added "SERIALIZE" to the Dcl-Proc spec.
Dcl-Proc SubProc_AccessSharedData Serialize;
Dcl-Pi *N;
End-pi;
// do something with shared global data or that needs to be Serialized.
End-proc;
That seems like a good RPG way to get away from using a semaphore or a mutex.
And running pthread is as easy as passing a procedure pointer.
/COPY QSYSINC/QRPGLESRC,PTHREAD
i=1;
parms(i).System = P_System;
rc = pthread_create(thread(i) : *OMIT : %paddr(POS19B_ShutdownListener) : %Addr(parms(i)));
i=2;
// parms(i).System = P_System;
rc = pthread_create(thread(i) : *OMIT : %paddr(POS19B_Processing) : %Addr(P_System));
// join on the POS19B_Processing thread.
rc = pthread_join (thread(i) : *OMIT);
There are a lot of things you can do with multi-threading. But most of those algorithms can be adjusted to be multi-process instead. And on the iSeries multi-process just means running another submitted job, which people tend to fall back to anyway.
Understanding the verbiage is somewhat important.
Spawn and Fork are terms used with Multi-Process.
In AS400 terms that means a new job is submitted to take care of whatever needed doing.
Those terms are not used with Multi-Threaded programs.
In Multi-Threaded programs you Create a new thread, then you Join it to wait for it to complete.
Chris Hiebert
Senior Programmer/Analyst
Disclaimer: Any views or opinions presented are solely those of the author and do not necessarily represent those of the company.
As an Amazon Associate we earn from qualifying purchases.