I have successfully incorporated an UDPreceive function into my application. HOWEVER! I can not figure out how to stop UDP listener from running infinitely. The OSCPack library has a Break() and AsynchronousBreak() built into it, but I have been unable to implement these.
in the udpSocket.cpp file within oscpack:
void Run() //the listener function (WORKING!)
{
break_ = false;
//UDP Listener Code
void Break()
{
break_ = true;
}
void AsynchronousBreak()
{
break_ = true;
// Send a termination message to the asynchronous break pipe, so select() will return
write( breakPipe_[1], "!", 1 );
}
}
My attempt to call Break() from the packet Listener class doesn't appear to do anything, despite the compiler suggesting that everything is being called correctly:
SocketReceiveMultiplexer s;
s.Break();
Another method that I have tried was to raise an interrupt flag in accordance with the RunUntilSigInt() function. Within the packet listener class:
raise(SIGINT);
but this terminates the whole program, rather than just breaking from the UDPListener. For reference, here is the RunUntilSigInt() code within udpSocket.cpp:
void SocketReceiveMultiplexer::RunUntilSigInt()
{
assert( multiplexerInstanceToAbortWithSigInt_ == 0 ); /* at present we support only one multiplexer instance running until sig int */
multiplexerInstanceToAbortWithSigInt_ = this;
signal( SIGINT, InterruptSignalHandler );
impl_->Run();
signal( SIGINT, SIG_DFL );
multiplexerInstanceToAbortWithSigInt_ = 0;
}
I'm completely stuck on this one, any help/advice will be greatly appreciated.
Thanks, Tom
I know this is a somewhat old question, but I had to overcome this recently and didn't find a good answer online. The model used by oscpack seems to be that they control the infinite Run
loop, and you implement everything you want to do inside a class derived from OscPacketListener. If you don't want to do things that way, you need to run the Run
loop in a separate thread. It seems in the oscpack 1.1.0 release, there is no internal support for threading anymore. They explain in the CHANGES file for that release that you would need to implement your own threading solution. The Run
routine in SocketReceiveMultiplexer
never returns, so any code after that call is unreachable. The various Break
routines are for controlling the execution of the Run
loop from a different thread. In the below example I'm using c++11 <threads>
but you can use any threading library you choose to accomplish something similar. In my example, you'll have to
#include <threads>
#include <mutex>
and compile your code with a c++11 compatible compiler. In g++ you would need the -std=c++11
command line argument.
If you start with the receiver example (parsing single messages example) in the SVN, you could change the main()
function to be something like
void ListnerThread()
{
PacketListener listener;
UdpListeningReceiveSocket s(
IpEndpointName( IpEndpointName::ANY_ADDRESS, PORT ),
&listener );
s.Run();
}
Somewhere else in your code, make a call like
std::thread lt(ListnerThread);
in order to start the listener running. You'll have to create some means of sharing information between your main thread and the listener thread. One simple method is to use a global variable surrounded by a mutex (also global). There are certainly other (better?) ways but this is very easy. Declare these globally (following their example) instead of within the ProcessMessage
function:
std::mutex oscMutex;
bool a1;
osc::int32 a2;
float a3;
const char *a4;
Inside the ExamplePacketListener
, where they set the variables from the args
stream and then make a call to cout
you would do something like
oscMutex.lock();
args >> a1 >> a2 >> a3 >> a4 >> osc::EndMessage;
oscMutex.unlock();
Just be sure to also lock()
and unlock()
the mutex in the same way wherever you access those variables elsewhere in your code.
This is old, but this is the only page on the web about this issue. In case someone needs oit
Using raise(SIGINT)
when i run the listener with RunUntilSigInt()
function does the trick for me. It's a quick hack and it is ugly but it goes like this:
if (std::strcmp(m.AddressPattern(), "/test1") == 0) {
osc::ReceivedMessageArgumentStream args = m.ArgumentStream();
osc::int32 a1, a2, a3;
const char *a4;
args >> a1 >> a2 >> a3 >> a4 >> osc::EndMessage;
raise(SIGINT);
}
In this case, i stop the listener when i receive one pack, but you can modify it as you wish.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With