Reputation: 4578
I have the following problem to solve. I want to make a number of requests to a number of "remote" servers (actually, a server farm we control). The connection is very simple. Send a line, and then read lines back. Because of the number of requests and the number of servers, I use pthreads, one for each request.
The naive approach, using blocking sockets, does not work; very occasionally, I'll have a thread stuck in 'connect'. I cannot use SIGALRM because I am using pthreads. I tried converting the code to O_NONBLOCK but this vastly complicated the code to read single lines.
What are my options? I'm looking for the simplest solution that allows the following pseudocode:
// Inside a pthread
try {
req = connect(host, port);
req.writeln("request command");
while (line = req.readline()) {
// Process line
}
} catch TimeoutError {
// Bitch and complain
}
My code is in C++ and I'm using Boost. A quick look at Boost ASIO shows me that it probably isn't the correct approach, but I could be wrong. ACE is far, far too heavy-weight to solve this problem.
Upvotes: 1
Views: 2866
Reputation: 437
You mentioned this happens 'very occasionally'. Your 'connect' side should have the fault tolerance and error handling you are looking for but you should also consider the stability of your servers, DNS, network connections, etc.
The underlying protocols are very sturdy and work very well, so if you are experiencing these kind of problems that often then it might be worth checking.
Upvotes: 1
Reputation: 519
You may also be able close the socket from the other thread. That should cause the connect to fail.
Upvotes: 0
Reputation: 75496
Have you looked at libevent?
http://www.monkey.org/~provos/libevent/
It's totally different paradigm but the performance is so amazing.
memcached is built on top of libevent.
Upvotes: 6
Reputation: 5080
I saw the comments and i think you can use boost::asio with boost::asio::deadline_timer
Fragment of a code:
void restart_timer()
{
timer_.cancel();
timer_.expires_from_now(boost::posix_time::seconds(5));
timer_.async_wait(boost::bind(&handleTimeout,
MyClass::shared_from_this(), boost::asio::placeholders::error));
}
Where handleTimeout is a callback function, timer_
is boost::asio::deadline_timer
and MyClass is similar to
class Y: public enable_shared_from_this<Y>
{
public:
shared_ptr<Y> f()
{
return shared_from_this();
}
}
You can call restart_timer before connect ou read/write
More information about share_from_this()
Upvotes: 5