Amiga.org
Operating System Specific Discussions => Amiga OS => Amiga OS -- Development => Topic started by: Jose on August 02, 2005, 06:40:20 PM
-
1- Hi. Is the NP_Entry tag for CreateNewProc() a BPTR ?
2- Also. Is is possible to pass arguments to a function I want to launch as a separate process without having them as global variables ?
3- Finally. I want to have a report to the result of my function's actions. I decided to have the report not done by the function itself since it could crash, or wait a long time. My doubt is: should I create separate process that launches the function as yet another process, and reports and finishes the report with an error (timeout or something) if a certain user set amount of time has passed ? Or should I let the main program do that, checking for the returned timerequestion with SetSignal() ? I take it that if the setSignal check is nothing compared to the main() loop in terms of code size it shouldn't hurt perfomance much ? What about the overload of creating a new process everytime I want a new action to be performed (wich sometimes can happend just a few times, other times plenty...)..
That all. 8-)
-
Hi,
1 - It is a C-style function pointer, NOT a BPTR.
2 - NO, the function prototype is: void(*)(void). But you could send a kind of startup-message to the messageport you get as result of the successfull CreateNewProc(). This message will be send to the new process's pr_MsgPort.
3 - I would program a timeout-timer and start the child process from your main program and I would create a public messageport for communication between the child process and your main program. The child would send a message to this public port when it has started successfully. Your main program has to Wait() for the signals of this public messageport and the timerequest after the child has been created. If the timerequest returns before the child has notified the success/result via the public messageport the child has failed.
Noster
-
@Noster
you could send a kind of startup-message to the messageport you get as result of the successfull CreateNewProc(). This message will be send to the new process's pr_MsgPort.
Small clarification:
CreateProc (ks 1.x+) returns struct MsgPort *
CreateNewProc (ks 2.x+) returns struct Process *
So with CreateNewProc you must send the message to newproc->pr_MsgPort
@Jose
2/3: It sure is possible to pass arguments, and even have the function report back "results". It's rather trivial really, you just need some messageport to send msgs and then wait for replies. If you need timeout, you can build it into the subproc: just abort the operation when timeout occurs, and return "timeout" error.
Here's a small framework of a subproc IPC: http://www.iki.fi/sintonen/src/ipc/ (http://www.iki.fi/sintonen/src/ipc/)
Note that the code uses seglists, but it could easily use NP_Entry instead.
-
you could send a kind of startup-message to the messageport
It's easier to pass AllocVec()'ed data in task->tc_UserData. NP_UserData should do the trick but I install it manually, with handshaking via signals. Tasks FreeVec()s the data when done with it.
-
@Dietmar
It's easier to pass AllocVec()'ed data in task->tc_UserData. NP_UserData should do the trick but I install it manually, with handshaking via signals. Tasks FreeVec()s the data when done with it.
This works, but you must be careful to Forbid() before CreateNewProc() and only Permit() after you've poked the tc_UserData, or you will get rather hard to track race condition.
-
This works, but you must be careful to Forbid() before CreateNewProc() and only Permit() after you've poked the tc_UserData, or you will get rather hard to track race condition.
That does not work because CreateNewProc() will in 99% of cases call code (like DOS functions) which may break Forbid state.
But if using signals for handshake that Forbid/Permit is not necessary anyway as he will do something like
maintask:
proc = CreateNewProc()
proc->pr_Task.tc_UserData = something;
Signal(proc->pr_Task, somesignal);
subtask:
Wait(somesignal);
look at proc->pr_Task.tc_UserData
With somesignal likely being something like SIGBREAKF_CTRL_F.
-
This works, but you must be careful to Forbid() before CreateNewProc() and only Permit() after you've poked the tc_UserData, or you will get rather hard to track race condition.
Nope: Just make the first line of the new task Wait(SIG_HANDSHAKE). The function filling in tc_UserData (after creating the task) can take all time it needs. It then raises SIG_HANDSHAKE via Signal(newtask, SIG_HANDSHAKE). For SIG_HANDSHAKE, use an existing standard signal. I use SIGF_SINGLE.
-
@Georg
CreateNewProc doesn't break forbid when both input and output handles are "NIL:", (and NULL path, currentdir, cli etc are requested). This is semi-documented, as the system must somehow launch the initial process before filesystems and disk I/O is available. The first process is launched from within a task. Obviously this only can happen if CreateNewProc works without any dos I/O calls. However, depending on this indeed is a bit hacky. The signal method is nicer, agreed.
@Dietmar
SIGF_SINGLE
SIGF_SINGLE might be dangerous to use, at least if there are any semaphores involved. IMO SIGBREAKF_CTRL_x is better.
If the subproc is supposed to return success/failure indicator, or if the subproc should handle possible multiple events, it might pay off to use full message based system. It can be done with pure signals and poking some variables, but IMO it's not as clean as messaging.
-
@All
Great, it's easy then :-) to pass messages without having to look for public ports etc...
@Noster
I want the main loop to launch the process and continue with it's own things, so I can't just Wait on the main loop. I could use SetSignal to check signals but that would be busy checking. But then again, the main loop is very big so this probably doesn't hurt.
:pint:
-
-
Hi,
@Dietmar
> It's easier to pass AllocVec()'ed data in task->tc_UserData. NP_UserData should do the trick but I install it manually, with handshaking via signals.
> Tasks FreeVec()s the data when done with it.
This is hacking and might not work in future releases of the AmigaOS (or if you wish to release a MorphOS or AROS version of your program)..
Noster
-
This is hacking and might not work in future releases of the AmigaOS
Maybe :) However, using a task's userdata field is not hacking, using signals is not hacking and passing memory blocks between tasks is not hacking (unless the Amiga API gets incompatible with itself and makes demands such as "owner must free memory"). SIGF_SINGLE signaling was apparently documented on a developer CD. I suppose I picked up its use for task handshaking via Olaf Barthel's Term source code. It had a funny comment: "Task termination and handshake signal. Note: don't try this at home kids, we are all trained professionals here!".
-
@Noster
This is hacking and might not work in future releases of the AmigaOS (or if you wish to release a MorphOS or AROS version of your program)..
It might be hacky, but we've been careful not to break it in MorphOS. Poking tc_UserData, using manual signal sync etc works just fine. It might not be pretty though...
@Dietmar
SIGF_SINGLE signaling was apparently documented on a developer CD. I suppose I picked up its use for task handshaking via Olaf Barthel's Term source code. It had a funny comment: "Task termination and handshake signal. Note: don't try this at home kids, we are all trained professionals here!".
Yeah SIGF_SINGLE is fine most of the time, but it can bite back. There are numerous cases where usage of SIGF_SINGLE has caused lots of grief (for example ramlib semaphore vs. library/device initcode). SIGF_SINGLE is used by the system itself, at least for semaphores.
It's much better idea to use the "user signals", SIGBREAKF_CTRL_F for example.
-
I was about to try it out this weekend but can't find NP_UserData tag Dietmar mentioned anywhere. I was supposing it's a tag for CreateNewProc() ? Is it an AOS3.9 only thing?
I was also about to use the process own port but the RKM's advise against using it, saying it's for exclusively use by DOS. I guess if I use it only in the beginning before using any dos function I'll be alright?
Anyway, I'd prefer that NP_UserData tag, it's more practical and I only need to send one message to the created process in the beginning, so no need for public port (Prefer not to use processes own port) allocation/deallocation and searching and waiting and geting messages and allocating deallocating them...
-
can't find NP_UserData tag Dietmar mentioned anywhere. I was supposing it's a tag for CreateNewProc() ? Is it an AOS3.9 only thing?
It's AROS/MorphOS thing. AmigaOS 3.x doesn't have it. No clue if AmigaOS 4 copied it.
I was also about to use the process own port but the RKM's advise against using it, saying it's for exclusively use by DOS. I guess if I use it only in the beginning before using any dos function I'll be alright?
Exactly.
Anyway, I'd prefer that NP_UserData tag, it's more practical
Too bad it's AROS/MorphOS thing.
-EDIT- MorphOS actually interherited the tag from AROS :-)
-
Too bad it's MorphOS thing.
I wouldn't bet about that ;-) (hint hint!)
-
Ahhh....Shame on 3.x for not having it... I'll use (struct Process *)->pr_MsgPort then...
[EDIT]
Actually I fell more tempted to poke tc_UserData.. :-)
-
@falemagn
Oh, hehe. Right :-)
Anyway, the tag rules indeed. You get rid of that nasty sync/poking crap. Nice idea.
-
Hi,
@Jose
Depending on the kind of data you want to pass you may pass them as string using NP_Arguments.
Poking tc_UserData is not much better code than using global variables in my opinion. Using messages protects from race conditions resp. you don't have to use Forbid()/Permit() (which should be avoided when ever possible).
Noster
-
Hi,
@Piru
> Anyway, the tag rules indeed. You get rid of that nasty sync/poking crap. Nice idea.
How is NP_UserData defined?
Noster