The normal way to deal with this is to use "Callback functions". You would tell libircpp about a function in your program that it can call when the JOIN reply arrives. Then, you call the join() function, which returns immediately. When the JOIN reply arrives, libircpp will "call back" the function you told it about. In the meantime, it is free to call other callback functions for any other messages that arrive.
Unfortunately, callback functions do not work so well in C++, because objects' member functions are shared between all objects belonging to that class. If libircpp just called that member function, the class would have no idea which object the call was for.
Boost signals solves this problem. libircpp emits signals for certain events, for example when a channel is joined, and you may connect these signals to any number of slots in your program, which may be member functions, or normal functions.
Signals have parameters and return values, which must match the functions they are connected to. For example, the session object's sig_join_msg signal, emitted when a channel is joined, has one parameter - a message object - and a return type of void. So to connect to it, you would need to create a function like this:
void channel_joined(const message& msg);And then connect the signal to it:
mysession->sig_join_msg.connect(channel_joined);Then, every time a JOIN message is received, your function channel_joined will be called.
Here are some other interesting messages emitted by the session object:
sig_connected | Emitted when the session object connects to an IRC server |
sig_disconnected | Emitted when the session object disconnects from an IRC server |
sig_join_msg | Emitted when a JOIN message is received (us, or someone else joining a channel) |
sig_privmsg_msg | Emitted when we receive a channel or private message |
sig_kick_msg | Emitted when someone is kicked from a channel |
In the next section, we'll see how to use these signals, by creating a simple bot that can op you on demand.
mysession->sig_join_msg.connect(channel_joined);You can also connect signals to objects' member functions, but the syntax is slightly more complicated:
mysession->sig_join_msg.connect(boost::bind(&myclass::my_member_function, &myobject, _1));You can see that we have replaced the function name "channel_joined" with the boost::bind macro:
boost::bind(&myclass::my_member_function, &myobject, _1)boost::bind packages up an object's member function so the signal can use it. It takes the following arguments:
boost::bind(&farmer::notice_handler, &fred, _1)The connect call would look like this:
mysession->sig_join_msg.connect(boost::bind(&farmer::notice_handler, &fred, _1));
mysession->sig_join_msg.connect(1, first_handler); mysession->sig_join_msg.connect(3, third_handler); mysession->sig_join_msg.connect(2, second_handler);Lower numbered slots will be called before higher numbered ones, and slots with the same number may be called in any order.