If I was at the point where I needed the information, I would wait for some specified amount of time. If it timesout I would kill the process and most likely die.
Could you expand upon the use of the handles, I can't say I have ever used this way of doing things.
Thanks.
| [reply] |
The point I've being trying to arrive at is that if, once you get to the point of needing the information, you have nothing else to do but wait for it to be available, then you do not need to do anything special.
The handles in this case are simply the thread handles:
my( $networkinfo ) = threads->create(
sub{ $remoteServer->getNetworkInfo() }
);
my( $sysLog ) = threads->create(
sub{ $remoteServer->getSystemLog() }
);
my( $scsiInfo ) = threads->create(
sub{ $remoteServer->getScsiInfo() }
);
... anything else that needs doing
## Now you're ready for the network info
my @networkinfo = $networkinfo->join;
...
## Now you're ready for the scsi info
my @scsiinfo = $scsiInfo->join;
...
## Now you're ready for the syslog
my @syslog = $sysLog->join;
There are 3 things to note here:
- Wrapping the method calls in subs on the thread create.
As you cannot take a reference to a method, you have to wrap the method call in a sub to create a closure.
In every other way, that method call should be exactly as it would be if no threading was involved.
- The scalars used to hold the thread handles returned by the threads->create() must be placed in parens if the method is to return a list.
This is to ensure that the method is called in a list context. Whatever context threads->create() is called in when the thread is started, is the context that will be transferred to thread when it starts.
- The join will return the results of the method called.
If the thread has completed when you call join, it will return teh results straight away. If it hasn't, it will block until it does.
If you want the commands to time out after some period of time, that should be done internally to the method itself. It can then choose to either log and die, or return undef or an exception object to indicate that the command failed to complete, just as it would have to do if called synchronously.
The trick with threading, is that your code, at each level, should operate synchronously first. Then asynchronously.
Depending upon the design of your library, you might also use a thread internally to achieve the timeout, but that is a separate issue from the main code. You should not conflate that timeout mechanism, however it is achieved, with the mechanism for running the methods asynchronously.
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] [select] |
This makes sense, thank you for your clear explanation and for sticking with me through all my questions.
I assume in the instances where I don't need the information, lets say for example I kick of some command blindly, then I can just not do a join for it. Is this correct?
Again thank you for your help, I will play with this more today, and post back my results and questions if I have any.
| [reply] |
As a followup, I have a separate issue that I think could be solved via threads as well.
In certain instances, a system call might be made which in turn requires some user input, this system call will essentially hang there until the underlying process waiting for the response is killed. What I was hoping of doing was to create an asynchronous thread and have it run the command, I would loop for some set amount of time checking to see if the thread is joinable, if it is then great, if it times out then exit or kill the thread.
I can't do the timeout in the function itself since there will be no response to the system call, that is why I am attempting to do it via thread that I can kill.
The issue I am seeing is that after I launch the thread, anytime I attempt to do anything with the thread, i.e. to get information on it, it hangs.
Any ideas? Thanks
my $queue1 = new Thread::Queue;
#Thread Timeout Test
my $command = 'diskpart';
#my ($thr) = threads->create(sub {return `$command`;});
my ($thr) = async{
my @resp1 :shared = `$command`;
$queue1->enqueue(\@resp1, undef);
return;
};
threads->list();
my $count = 60 * 1; #wait a min (testing)
while ($count and !$thr->is_joinable()) {
sleep(1);
count--;
}
if (!$thr->is_joinable()) {
threads->exit();
}
...
The threads->list() call hangs (so does any other thread related call. If I do $command = 'dir'; everything works as expected since it is not stuck waiting for user input.
| [reply] [d/l] |