the following code:
/***************************************************************************/
boost::mutex m;
struct func {
func(int v):n(v) {}
void operator()() {
{ boost::mutex::scoped_lock l(m);
std::cout << "run function " << n << std::endl;
}
for ( int idx = 0; idx < 4; ++idx ) {
{ boost::mutex::scoped_lock l(m);
std::cout << "function " << n << ", ping " << idx << std::endl;
}
sleep(1);
}
}
private:
int n;
};
/***************************************************************************/
int main(int argv, const char** argc) {
boost::asio::io_service io;
for ( int idx = 0; idx < 4; ++idx ) {
io.post(func(idx));
}
std::cout << "before run" << std::endl;
io.poll();
std::cout << "after run" << std::endl;
std::cin.get();
return 0;
}
/***************************************************************************/
gives such an output:
**before run**
run function 0
function 0, ping 0
function 0, ping 1
function 0, ping 2
function 0, ping 3
run function 1
function 1, ping 0
function 1, ping 1
function 1, ping 2
function 1, ping 3
run function 2
function 2, ping 0
function 2, ping 1
function 2, ping 2
function 2, ping 3
run function 3
function 3, ping 0
function 3, ping 1
function 3, ping 2
function 3, ping 3
**after run**
but, according to the documentation:
The poll() function runs handlers that
are ready to run, without blocking,
until the io_service has been stopped
or there are no more ready handlers.
poll() - is a non-blocking method.
what's the problem?
and the second question:
in documentation it is said that:
return The number of handlers that
were executed.
if it is non-blocking, what value it will return? - the number of objects in the queue? - but this is not the same thing as "that were executed".
This is an old question but you never really got an answer about run vs poll.
io_service::run will keep running as long as there is something to do, such as waiting on a deadline timer or IO completion notification, etc. This is why there is the work object to keep run from exiting.
io_service::poll will only execute ready handlers, and will not return until there are no more handlers ready to be dispatched.
The difference in other words is that run will wait for a pending handler to be ready, like a timer or IO completion notification, while poll will return in that situation.
This behavior is useful if you want to perform some idle processing.
Non-blocking is not the same as asynchronous. pool synchronously runs handlers that are ready to run, and returns without blocking and waiting for another handlers.
Additional explanation.
Blocking input operation is operation which starts endless wait if no input data found. Consider Read operation which is supposed to read one byte from some port, but there is no incoming data. In this case Read call hangs, and returns only when byte is received. Non-blocking read operation returns immediately, if there is no input information.
pool operation is non-blocking. It synchronously executes all pending requests and returns. If there are no incoming requests, poll returns immediately.
Related
I am using version 1.23.1 of the GRPC library.
I have an asynchronous RPC c++ Client class, which initiates each RPC with the following method:
void Client::SendTaskAsync(const Task& task) {
unique_lock<mutex> lock(mtx_);
cout << "Sending task with id " << task.id() << endl;
ClientContext context;
Status status;
unique_ptr<ClientAsyncResponseReader<Result>> rpc(
stub_->PrepareAsyncSendTask(&context, task, &queue_));
rpc->StartCall();
// Allocating memory to store result from RPC
Result* result = &results_.emplace_back();
int* tag = new int(results_.size() - 1);
rpc->Finish(result, &status, static_cast<void*>(tag));
}
In the main thread I call SendTaskAsync five times in a loop.
The Client class has a background thread informing when each RPC has returned a Result:
while (true) {
void* tag;
bool ok = false;
{
unique_lock<mutex> lock(mtx_);
cout << "Waiting the for next result" << endl;
const time_point<system_clock> deadline =
system_clock::now() + milliseconds(1000);
// SEGFAULT HERE, WHY?
GPR_ASSERT(queue_.AsyncNext(&tag, &ok, deadline));
}
if (ok) {
int index = *static_cast<int*>(tag);
cout << "Got result with tag " << index << endl;
} else {
cout << "Sleeping" << endl;
sleep_for(milliseconds(1000));
}
}
If I start my client, the following log is observed:
BACKGROUND: Waiting for the next result
MAIN THREAD: Sending task with id 0
BACKGROUND: Sleeping
MAIN THREAD: Sending task with id 1
MAIN THREAD: Sending task with id 2
MAIN THREAD: Sending task with id 3
MAIN THREAD: Sending task with id 4
BACKGROUND: Waiting for the next result
BACKGROUND: Segmentation fault (core dumped)
What happens is that
Background thread checks if a queue_ contains a result, there is none yet, so it goes to sleep;
Main thread makes 5 RPC that at the end should populate the queue_ with results;
Background thread wakes up and checks if a queue_ contains a result, AND CRASHES.
Any ideas why?
The code in the question is written according to this tutorial, which sends only one request and waits for a reply in the same thread.
If you want to use multiple threads, follow the client example here.
I am developing C++ class with calls to Windows API C libraries.
I am using the Semaphores for a task, let's say I have two processes:
ProcessA has two semaphores:
Global\processA_receiving_semaphore
Global\processA_waiting_semaphore
ProcessB has two semaphores:
Global\processB_receiving_semaphore
Global\processB_waiting_semaphore
I have two threads in each process:
Sending thread in processA:
Wait on "Global\processB_waiting_semaphore"
// do something
Signal "Global\processB_receiving_semaphore"
Receiving thread on processB:
Wait on "Global\processB_receiving_semaphore"
// do something
Signal "Global\processB_waiting_semaphore
I removed ALL code that Releases "Global\processB_waiting_semaphore" but it can still be acquired. Calling WaitForSingleObject on that semaphore always returns successful wait and immediately. I tried setting the timeout period to 0 and it still acquires the semaphore while NOTHING is releasing it.
The receiving semaphore has initial count = 0 and max count = 1 while the waiting semaphore has initial count = 1 and max count = 1.
Calling WaitForSingleObject on the receiving semaphore works great and blocks until it is released by the other process. The problem is with the waiting semaphore and I cannot figure out why. The code is very big and I have made sure the names of the semaphores are set correctly.
Is this a common issue? If you need more explanation please comment and I will modify the post.
EDIT: CODE ADDED:
Receiver semaphores:
bool intr_process_comm::create_rcvr_semaphores()
{
std::cout << "\n Creating semaphore: " << "Global\\" << this_name << "_rcvr_sem";
rcvr_sem = CreateSemaphore(NULL, 0, 1, ("Global\\" + this_name + "_rcvr_sem").c_str());
std::cout << "\n Creating semaphore: " << "Global\\" << this_name << "_wait_sem";
wait_sem = CreateSemaphore(NULL, 1, 1, ("Global\\" + this_name + "_wait_sem").c_str());
return (rcvr_sem && wait_sem);
}
Sender semaphores:
// this sender connects to the wait semaphore in the target process
sndr_sem = OpenSemaphore(SEMAPHORE_MODIFY_STATE, FALSE, ("Global\\" + target_name + "_wait_sem").c_str());
// this target connects to the receiver semaphore in the target process
trgt_sem = OpenSemaphore(SEMAPHORE_MODIFY_STATE, FALSE, ("Global\\" + target_name + "_rcvr_sem").c_str());
DWORD intr_process_locking::wait(unsigned long period)
{
return WaitForSingleObject(sndr_sem, period);
}
void intr_process_locking::signal()
{
ReleaseSemaphore(trgt_sem, 1, 0);
}
Receiving thread function:
void intr_process_comm::rcvr_thread_proc()
{
while (conn_state == intr_process_comm::opened) {
try {
// wait on rcvr_semaphore for an infinite time
WaitForSingleObject(rcvr_sem, INFINITE);
if (inner_release) // if the semaphore was released within this process
return;
// once signaled by another process, get the message
std::string msg_str((LPCSTR)hmf_mapview);
// signal one of the waiters that want to put messages
// in this process's memory area
//
// this doesn't change ANYTHING in execution, commented or not..
//ReleaseSemaphore(wait_sem, 1, 0);
// put this message in this process's queue
Msg msg = Msg::from_xml(msg_str);
if (msg.command == "connection")
process_connection_message(msg);
in_messages.enQ(msg);
//std::cout << "\n Message: \n"<< msg << "\n";
}
catch (std::exception e) {
std::cout << "\n Ran into trouble getting the message. Details: " << e.what();
}
}
}
Sending thread function:
void intr_process_comm::sndr_thread_proc()
{
while (conn_state == intr_process_comm::opened ||
(conn_state == intr_process_comm::closing && out_messages.size() > 0)
) {
// pull a message out of the queue
Msg msg = out_messages.deQ();
if (connections.find(msg.destination) == connections.end())
connections[msg.destination].connect(msg.destination);
if (connections[msg.destination].connect(msg.destination)
!= intr_process_locking::state::opened) {
blocked_messages[msg.destination].push_back(msg);
continue;
}
// THIS ALWAYS GETS GETS WAIT_OBJECT_0 RESULT
DWORD wait_result = connections[msg.destination].wait(wait_timeout);
if (wait_result == WAIT_TIMEOUT) { // <---- THIS IS NEVER TRUE
out_messages.enQ(msg);
continue;
}
// do things here
// release the receiver semaphore in the other process
connections[msg.destination].signal();
}
}
To clarify some things:
trgt_sem in a sender is the rcvr_sem in the receiver.
`sndr_sem' in the sender is the 'wait_sem" in the receiver.
for call WaitForSingleObject with some handle:
The handle must have the SYNCHRONIZE access right.
but you open semaphore with SEMAPHORE_MODIFY_STATE access only. with this access possible call ReleaseSemaphore (This handle must have the SEMAPHORE_MODIFY_STATE access right) but call to WaitForSingleObject fail with result WAIT_FAILED. call to GetLastError() after this must return ERROR_ACCESS_DENIED.
so if we want call both ReleaseSemaphore and any wait function - we need have SEMAPHORE_MODIFY_STATE | SYNCHRONIZE access on handle. so need open with code
OpenSemaphore(SEMAPHORE_MODIFY_STATE|SYNCHRONIZE, )
and of course always checking api return values and error codes can save a lot of time
If you set the timeout to 0 WaitForSingleObject will always return immediately, a successful WaitForSingleObject will return WAIT_OBJECT_0 (which happens to have the value 0), WFSO is not like most APIs where success is indicated by a non-zero return.
I try to run a asynchronous timer and a synchronous timer :
Here is my code :
boost::asio::io_service io;
boost::asio::steady_timer t1(io);
boost::asio::steady_timer t2(io);
void callback(boost::system::error_code const&)
{
std::cout << "foo" << std::endl;
t1.expires_from_now(boost::chrono::seconds(1));
t1.async_wait(&callback);
}
int main(int argc, char **argv)
{
t1.expires_from_now(boost::chrono::seconds(1));
t1.async_wait(&callback);
io.run();
t2.expires_from_now(boost::chrono::seconds(5));
t2.wait();
io.run();
std::cout << "finish" << std::endl;
return EXIT_SUCCESS;
}
I would like foo to printed 5 times, and finish printed.
In this code, foo is printed every 1 second and finish is never reached.
How to achieve what I want ?
Thanks
According to the documentation of io_service::run:
The run() function blocks until all work has finished and there are no more handlers to be dispatched, or until the io_service has been stopped.
Since run blocks until there are no more handlers to be dispatched, it will block until callback has finished. However, callback registers another callback handler and run will keep blocking until it's finished... ad infinitum
If you want the callback to repeat only five times, then you need to not schedule a new callback after the fifth time.You can use a simple counter and a branch for that.
As said in user2079303's answer, your first io.run() call never returns since callback registers itself.
To achieve what you want to do, you can just modify your callback function as followed:
void callback(boost::system::error_code const&)
{
static int i = 0;
std::cout << "foo" << std::endl;
t1.expires_from_now(boost::chrono::seconds(1));
if (++i < 5) {
t1.async_wait(&callback);
} else {
i = 0; // Reset i if you want to reuse callback later with the same behaviour
}
}
I am trying to use boost::asio deadline timer for delayed function call as follows
#include <boost/asio.hpp>
#include "boost/thread.hpp"
#include <iostream>
class MyTest {
public:
MyTest()
:_invokeCount(0),
_handleCount(0)
{}
void handler(int i)
{
std::cout<<"\t\tHandled " <<i << std::endl;
++_handleCount;
}
void RunIOService()
{
std::cout<<"\tStarted :"<< _invokeCount<< std::endl;
_ios.run();
std::cout<<"\tFinished "<< _invokeCount << std::endl;
}
void invokeTimer()
{
std::cout<<"invoked " << ++_invokeCount << std::endl;
boost::asio::deadline_timer t(_ios, boost::posix_time::milliseconds(5));
t.async_wait(boost::bind(&MyTest::handler, this, _invokeCount));
boost::thread th = boost::thread(boost::bind(&MyTest::RunIOService, this));
}
void PrintCount()
{
std::cout<<"Count = "<< _invokeCount << std::endl;
}
void Wait()
{
while (_invokeCount > _handleCount) {
std::cout<<"X ";
Sleep(1000);
}
}
private:
int _invokeCount;
int _handleCount;
boost::asio::io_service _ios;
};
int main(int argc, char* argv[])
{
MyTest test;
for (int k=0; k<5; ++k) {
test.invokeTimer();
Sleep(40);
}
test.Wait();
test.PrintCount();
return EXIT_SUCCESS;
}
The output of this application is not as I expected:-
invoked 1
Started :1
Handled 1
Finished 1
invoked 2
Started :2
Finished 2
invoked 3
Started :3
Handled 2
Finished 3
invoked 4
Started :4
Handled 3
Finished 4
invoked 5
Started :5
Handled 4
Finished 5
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
I expected every handler to be called before ios_service::run returns and it doesn't seem so from the output ( missing output between Started:2 and Finished:2). Also, the application never exits. i.e the 5th handler never gets invoked.
What am I missing?
Thanks!
A couple of things:
You probably don't need 5 threads. Why don't you create a single thread and fire the events into that single ioservice instance running in the thread
Try using io_service::work in the thread run function to keep the io_service in scope while all your requests are handled.
When your wait finishes, stop your io_service, join your thread and let your program exit
Read here about io_service::work: http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/reference/io_service.html
I added ios_service::reset() after each ios_service::run() and it worked as expected.
boost::asio::ioservice::reset() should be called before later set of invocations of the run().
as the boost doc say:
This function must be called prior to any second or later set of invocations of the run(), run_one(), poll() or poll_one() functions when a previous invocation of these functions returned due to the io_service being stopped or running out of work. This function allows the io_service to reset any internal state, such as a "stopped" flag.
This function must not be called while there are any unfinished calls to the run(), run_one(), poll() or poll_one() functions.
I'm trying to create a UDP broadcast program to check for local game servers, but I'm having some trouble with the receiving end. Since the amount of servers alive is unknown at all times, you must have a loop that only exits when you stop it. So in this bit of code here:
while(1) // start a while loop
{
if(recvfrom(sd,buff,BUFFSZ,0,(struct sockaddr *)&peer,&psz) < 0) // recvfrom() function call
{
cout << red << "Fatal: Failed to receive data" << white << endl;
return;
}
else
{
cout << green << "Found Server :: " << white;
cout << yellow << inet_ntoa(peer.sin_addr), htons(peer.sin_port);
cout << endl;
}
}
I wish to run this recvfrom() function until I press Ctrl + C. I've tried setting up handlers and such (from related questions), but they're all either too complicated for me, or it's a simple function that just exits the program as a demonstration. Here's my problem:
The program hangs on recvfrom until it receives a connection (my guess), so, there's never a chance for it to specifically wait for input. How can I set up an event that will work into this nicely?
Thanks!
In the CTRL-C handler, set a flag, and use that flag as condition in the while loop.
Oh, and if you're not on a POSIX systems where system-calls can be interrupted by signals, you might want to make the socket non-blocking and use e.g. select (with a small timeout) to poll for data.
Windows have a couple of problems with a scheme like this. The major problem is that functions calls can not be interrupted by the CTRL-C handler. Instead you have to poll if there is anything to receive in the loop, while also checking the "exit loop" flag.
It could be done something like this:
bool ExitRecvLoop = false;
BOOL CtrlHandler(DWORD type)
{
if (type == CTRL_C_EVENT)
{
ExitRecvLoop = true;
return TRUE;
}
return FALSE; // Call next handler
}
// ...
SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE);
while (!ExitRecvLoop)
{
fd_set rs;
FD_ZERO(&rs);
FD_SET(sd, &rs);
timeval timeout = { 0, 1000 }; // One millisecond
if (select(sd + 1, &rs, NULL, NULL, &timeout) < 0)
{
// Handle error
}
else
{
if (FD_ISSET(sd, &rs))
{
// Data to receive, call `recvfrom`
}
}
}
You might have to make the socket non-blocking for this to work (see the ioctlsocket function for how to).
Thread off your recvFrom() loop so that your main thread can wait for user input. When user requests stop, close the fd from the main thread and the recvFrom() will return immediately with an error, so allowing your recvFrom() thread to exit.