|
ReedN Wizard
Joined: 04 Jan 2006 Posts: 1279 Location: Portland, Oregon
|
Posted: Tue Jan 15, 2008 8:53 pm
Some questions with threads |
I'm getting set to use threads for the first time in my code and I have a few questions I wanted to bounce off people before I tried it.
Question 1: If I know that everything in a certain class can be in a separate thread, do I need to go through each alias/trigger and use the #thread command, or is there some way to place an entire class in a separate thread?
Question 2: Assuming there is no way to put the entire class in a thread and I use #thread for each alias/trigger, should I name all the threads the same thing or should I make all the thread names unique within that class?
Question 3: What happens if you have a thread with name1 running and you use #thread again and name the new thread the same name (name1)? |
|
|
|
Vijilante SubAdmin
Joined: 18 Nov 2001 Posts: 5182
|
Posted: Tue Jan 15, 2008 10:23 pm |
Threading is not something to be done lightly. You really need to have a very thorough understanding not just what the code does, but also all the other inputs the program will be getting. Threading is mostly a mechanism to respond to specific inputs, rather like triggers. Unless you need the response mechanism to release the main interface there is no reason to use a thread. Specific answers to your questions aren't actually that easy.
1. You don't actually ever have to use the #THREAD command. Usage of #WAIT by itself or other of the #WAITxxx group of commands will cause the current execution block to pause momentarily while a new thread is spoawned and the main interface becomes attached to the new thread. Without specific knowledge of what you want to do, need to do, and imagine doing I can't specifically answer.
2. See answer 1.
3. Multiple threads can be named the same. This might cause you some problems with #WAITTHREAD as that locates the first thread with a matching name and locks onto that one as the one it is waiting on. Also if you use #STOP, #SUSPEND, #RESUME, %threadname, etc. they all have that same behavior. The first thread that matches the name will be the one they work with. |
|
_________________ The only good questions are the ones we have never answered before.
Search the Forums |
|
|
|
ReedN Wizard
Joined: 04 Jan 2006 Posts: 1279 Location: Portland, Oregon
|
Posted: Tue Jan 15, 2008 10:51 pm |
The item that I'm looking at threading is a self contained Mud clock. It doesn't interact with anything outside the class and so I thought it would be a great place to start. The clock updates itself every 2.5 seconds doing a bit of variable and math work to update the time. I thought threads would be a great way of keeping this out of the critical execution path. The clock can either be updated from input from the Mud as when messages are sent out saying that we've reached certain points in the day or it will be updated every 2.5 seconds from my #alarm statement. I was thinking of putting each of the updating aliases/triggers in a separate thread but I was unsure if there was a better way to do it than going into each alias/trigger and creating a separate thread for each.
There are only a handful of aliases/triggers that can update the time variables so I will create a unique thread for each of them and protect the update of the variables with the #section command. Does that sound about right, or is there a slicker way to do this?
Also, can I assume that any alias called within an alias in thread A, will also execute in thread A? |
|
|
|
Zugg MASTER
Joined: 25 Sep 2000 Posts: 23379 Location: Colorado, USA
|
Posted: Tue Jan 15, 2008 11:22 pm |
Just create a normal alarm with an interval of 2.5 seconds, and then put the #WAIT command as the first command of your script (with no arguments). This will send your script into the background so that it doesn't block execution. Just make sure that your alarm is thread-safe and doesn't write to any variables that might be accessed at the same time by some other script (or use the #SECTION command as you mentioned).
In general, it's better to use the #WAIT command to put something into the background rather than using the #THREAD command to create a separate thread.
And yes, if you call an alias from a thread, it executes within that thread. |
|
|
|
ReedN Wizard
Joined: 04 Jan 2006 Posts: 1279 Location: Portland, Oregon
|
Posted: Tue Jan 15, 2008 11:31 pm |
Could you elaborate on why it's better to use #wait intead of #thread?
|
|
|
|
Zugg MASTER
Joined: 25 Sep 2000 Posts: 23379 Location: Colorado, USA
|
Posted: Tue Jan 15, 2008 11:44 pm |
They are mostly equivalent, but using #WAIT allows CMUD to reuse a thread from it's internal pool, whereas #THREAD forces a new thread to be created each time. So in theory, using #WAIT should be a bit faster in most cases. It's also a bit easier to debug since the #THREAD command (no arguments) to list the running threads can display the script text associated with your alarm if you use #WAIT. When you use #THREAD, the thread only gets passed the compiled code and doesn't have access to the original script text, so the #THREAD list won't be as helpful. It will just show as a "compiled #THREAD command". Same in the Debugger window.
|
|
|
|
ReedN Wizard
Joined: 04 Jan 2006 Posts: 1279 Location: Portland, Oregon
|
Posted: Wed Jan 16, 2008 1:12 am |
One item that I had a question on as I was coding this. What should you do if you need to protect variables needed to call an alias that is itself protected?
Here's an example:
#section myVar {
@var = 5
myalias @var
}
alias myalias:
#section myVar {
#say @myVar
}
The section around the call of myalias is protected because I don't want the value changing as I call the alias and the alias needs to be protected as so I print the proper value. But it seems as if the section from the first code won't have ended at that point and so you would have a stalemate between the calling and called function because the calling function's section can't end because of the new section.
I think the answer will be that the section is still active during calls to other aliases and so to fix this I now put my section statements at the locations where execution may begin. So I have a section statement in the alarm and in all the triggers for time updating. So effectively I can only do one type of update at a time. If I'm doing an alarm update it will have to wait to do a trigger update and vice-versa. |
|
Last edited by ReedN on Wed Jan 16, 2008 2:10 am; edited 1 time in total |
|
|
|
Fang Xianfu GURU
Joined: 26 Jan 2004 Posts: 5155 Location: United Kingdom
|
Posted: Wed Jan 16, 2008 1:23 am |
You shouldn't need to section the alias because it's a reference to a variable local to the alias, presumably the first parameter. Only references to the global @var would need sectioning.
|
|
|
|
ReedN Wizard
Joined: 04 Jan 2006 Posts: 1279 Location: Portland, Oregon
|
Posted: Wed Jan 16, 2008 2:11 am |
That was a typo, I've corrected it in the original post. It was meant to be the same global variable.
|
|
|
|
Fang Xianfu GURU
Joined: 26 Jan 2004 Posts: 5155 Location: United Kingdom
|
Posted: Wed Jan 16, 2008 2:26 am |
Then it's still typoed ;)
But you're right, that thread would never finish because the alias would be waiting for itself to finish executing. You could perhaps use two versions of the alias, one that's unsectioned, for use in sections, and one that's not, for use outside them, or perhaps give it a parameter that's 1 for sectioned and 0 for unsectioned that does:
Code: |
#if (%2) {#section myVar {#show @myVar}} {#show @myVar} |
Really, though, your example isn't a situation that'll come up. Either you're passing the variable's value to the alias, as in your first example, and the alias needn't contain a #section because it can just refer to %1, or it'll refer to the value of the global variable and needn't be called from inside a separate section because the actual call to myalias wouldn't contain a reference to @myVar. You'd have one of these two situations:
Code: |
1) myalias: #section myVar {#show @myVar}
calling it: #section myVar {myVar=5};myalias
or
2) myalias: #show %1
calling it: #section myVar {myVar=5;myalias @myVar} |
But yes, you're right, and these are things you need to consider very carefully when you start implementing sections. |
|
|
|
|
|