Event-Driven Client/Server Design with C++ - c++

I am designing a game server with scripting capabilities. The general design goes like this:
Client connects to Server,
Server initializes Client,
Server sends Client to EventManager (separate thread, uses libevent),
EventManager receives receive Event from Client socket,
Client manages what it received via callbacks.
Now the last part is what's the most tricky for me now.
Currently my design allows me for a class which inherits Client to create callbacks to specific received events. These callbacks are managed in a list and the received buffer goes through a parsing process each time something is received. If the buffer is valid, the callback is called where it is act upon what is in the buffer. One thing to note is that the callbacks can go down to the scripting engine, at which point nothing is sure what can happen.
Each time a callback finishes, the current receive buffer has to be reset etc. Callbacks currently have no capability of returning a value, because as stated before, anything can happen.
What happens is that when somewhere in the callback something says this->disconnect(), I want to immediately disconnect the Client, remove it from the EventManager, and lastly remove it from the Server, where it also should get finally destructed and free memory. However, I still have some Code running after the callback finishes in the Client, thus I can't free memory.
What should I change in the design? Should I have some timed event in the Server which checks which Clients are free to destroy? Would that create additional overhead I don't need? Would it still be okay after the callback finishes to run minimal code on the stack (return -1;) or not?
I have no idea what to do, but I am open for complete design revamps.
Thanks in advance.

You can use a reference counted pointer like boost::shared_ptr<> to simplify memory management. If the manager's client list uses shared_ptrs and the code that calls the callbacks creates a local copy of the shared_ptr the callback is called on, the object will stay alive until it is removed from the manager and the callback function is complete:
class EventManager {
std::vector< boost::shared_ptr<Client> > clients;
void handle_event(Event &event) {
// local |handler| pointer keeps object alive until end of function, even
// if it removes itselfe from |clients|
boost::shared_ptr<Client> handler = ...;
handler->process(event);
}
};
class Client {
void process(Event &event) {
manager->disconnect(this);
// the caller still holds a reference, so the object lives on
}
}
The Client object will automatically be deleted once the last shared_ptr to it goes out of scope, but not before. So creating a local copy of the shared_ptr before a function call makes sure the object is not deleted unexpectedly.

You should consider having an object like "Session" which will track particular message flow from start to finish (from 1 client).
This object should also take care of current state: primarily the buffers and processing.
Each event which triggers a callback MUST update the state of corresponding session.
Libevent is capable of providing you with any result of scheduled event: success, failure, timeout. Each of this types should be reflected with your logic.
In general, when working with events, consider your processing logic to be an automaton with a state.
http://en.wikipedia.org/wiki/Reactor_pattern may be a good resource for your task.

Let the Client::disconnect() function send an event to the EventManager (or Server) class. This means that you need some sort of event handling in EventManager (or Server), an event loop for instance.
My general idea is that Client::disconnect() does not disconnect the Client immediately, but only after the callback finished executing. Instead, it just posts an event to the EventManager (or Server) class.
One could argue that the Client::disconnect() method is on the wrong class. Maybe it should be Server::disconnect( Client *c ). That would be more in-line with the idea that the Server 'owns' the Client and it's the Server which disconnects Clients (and then updates some internal bookkeeping).

Related

When can I expect OSAction::Cancel handler to be called?

I have a Driverkit driver that takes care of a USB device. The driver unpacks data in the USB packets, and writes the data to buffers that are shared between the app and the driver. The shared buffers are created by the app with IOConnectCallAsyncMethod. When a buffer is ready to be consumed by the app, the driver calls IOUserClient::AsyncCompletion with an OSAction object. The OSAction object is also created as a result of the call to IOConnectCallAsyncMethod by the app. There is one OSAction object per shared buffer.
In case of an error in the mechanism that takes care of the events in the app I tell the driver to stop calling the OSAction objects, and the thread that takes care of the events in the app is stopped. At this point I cannot be sure that I have handled all the events in the app, and when I send a message to the driver to start again, I want to be sure that no events from before stopping is in the queue to be handled by the app.
I have looked at OSAction::Cancel, which lets you pass a handler that should be invoked when the callback is cancelled. The documentation for this method says A handler block for the system to call after any in-flight callbacks finish executing.
What does an "in-flight" callback mean?
I call Cancel for all OSAction objects, and decrement a counter for each OSAction object to keep track of the cancellation completion (similar to this example project from Apple). Problem is that I can't see that the block is invoked.
When can I expect the block to be invoked? Some different situations that I can think of is:
An OSAction that was never passed to AsyncCompletion.
An OSAction that was passed to AsyncCompletion but the app did not handle the event.
An OSAction that was passed to AsyncCompletion, the app started to handle the event, but the app is not yet done with the event.
I am also wondering about which dispatch queue in the driver that will be used to call the block.

Remove particular class's completion handler from array

I have implemented one method of completion handler which fetch data from server.
While one request is in progress, this method may be called multiple time by any other class and I want to notify all once data is received from server without sending multiple request.
To achieve this I am adding up completion handlers in thread safe array.
But I want to remove particular completion handler if caller class doesn't exists in memory when data is received from server.
Ex - If controller's viewDidDisAppear() gets called. I want to removed its handler.
How to achieve this?

OOP COM Server Updates clients

I have an out of process ATL COM server (exe). When it is started by a Client the server spawns a worker thread which polls for some data. Every time the data is updated I want to notify all of the clients with the updated value.
I have created a COM Client, which connects via CoCreateInstanceEx, creates its Sink object, gets the connection point and calls Advise, all without error. However, When the server tries to Fire_event, it's IConnectionPointImpl::m_vec is empty and no clients are ever notified.
I assume this is because the server creates its own object, so I end up with two instances of IConnectionPointImpl::m_vec, one from the server and one from the client when it calls Advise. How can I get the server data to the clients?
I'd recommend this approach. Create a plain vanilla C++ singleton (not a COM object) - let's call it S. S would hold a list of weak, non-AddRef'ed references to all outstanding COM objects (a C++ class pointer, rather than a COM interface pointer, would be convenient). Your COM objects would register themselves with S in their constructor, and deregister in destructor.
When something interesting happens, your worker thread would notify (call a method on) S, which would notify all registered COM objects, which would call Fire_event on themselves.
Be careful when firing events from a worker thread. This is illegal, unless both your main thread and worker thread enter MTA. See http://vcfaq.mvps.org/com/1.htm for details and some workarounds.

Making an Qt HTTP request and receiving the response in a single function call

I'm attempting to create a library whose API will be used in the following way:
WebService *service = new WebService( username, password );
User *user = service->getAuthenticatedUser();
UserAssets *assets = user->assets();
// And so on
Neither the authenticated user, nor their assets, will be downloaded when the WebServer instance is created, rather they will only be retrieved if explicitly requested.
Whenever I've had to retrieve data from the network before using Qt, I've followed the standard pattern of connection the finished() signal of the QNetworkReply to the appropriate slot and using that slot to handle the returned data.
My problem here is that pattern does not seem to accommodate my desired use-case. I would like the users of my library (other developers) to be able to use a single line to request and receive the data they desire, but the 'Qt way' seems, at least from my point of view, to require them to initiate the request on one line, and then connect some signal to some other slot to get the data back, which is not the experience I would like them to have.
I'm new to network programming, both in general and with Qt, but I've used libraries written in Python, communicating with the exact same service, that are able to achieve this, so it does seem to be possible.
Is it possible to perform the full lifecycle of a HTTP request with Qt with a single function call?
Your best bet is probably to use a QEventLoop. This would allow you to 1) initiate the HTTP connection and, from your caller's perspective, 2) effectively block until you get a response.
For example:
QNetworkReply wait for finished
As already other have mentioned you could use QEventLoop to wait for finished() or error() signals, and the quitting event loop. This solution while working, have some serious disadvantages.
If it takes longer to download given address, then you might be stuck in your event loop for quite a while. The event loop is processing events nicely, so your app doesn't frezze, but there are some quirks connected to it anyway. Imagine that user is waiting for load, and then presses another button, to load something else. Then you will have multiple loop-in-loop, and first file will have to wait for the second to finish downloading.
Doing things in single call suggest to many programmers, that this will happen at one instant. But your function is processing events internally, so this might not hold. Imagine a code like
// some pointer accessible to many functions/methods (eg. member, global)
MyData* myData=0;
Then a code calling your function:
if (myData){
QNetworkReply* reply = getMyWobsite(whatever);
myData->modify(reply);
}
Seems fine, but what if some other slot happens to call
myData=0;
If this slot will be executed while waiting for request, application will crash. If you decide to use QEventLoop in your function, be sure to mention it in function documentation, so programmers using it will be able to avoid such problems.
If you are not using qt for anything else, you might even consider some alternative libraries (eg. libcurl) that might have what you need already implemented.

How can I make socket access behave 'asynchronously' without requiring a message loop?

My program uses a NetworkOutput object which can be used to write data to a remote server. The semantic is that in case the object is currently connected (because there is a remote server), then the data is actually sent over the socket. Otherwise, it's silently discarded. Some code sketch:
class NetworkOutput
{
public:
/* Constructs a NetworkOutput object; this constructor should not block, but it
* should start attempting to the given host/port in the background.
*
* In case the connection gets closed for some reason, the object should immediately
* try reconnecting.
*/
NetworkOutput( const std::string &hostName, unsigned short port );
/* Tells whether there is a remote client connected to this NetworkOutput object.
* Clients can use this function to determine whether they need to both serializing
* any data at all before calling the write() function below.
*/
bool isConnected() const;
/* Write data to the remote client, if any. In case this object is not connected
* yet, the function should return immediately. Otherwise it should block until
* all data has been written.
*
* This function must be thread-safe.
*/
void write( const std::vector<char> &data );
};
Right now, I have this implemented using nonblocking sockets. I'n the NetworkOutput constructor, I'm creating a TCP socket as well as an internal helper window. I then do a WSAAsyncSelect call on the socket. This makes the socket nonblocking, and it will cause a magic window message (which I registered myself) to be sent to the internal helper window in case any interesting event (such as 'connection established' or 'connection closed') happens on the socket. Finally, I start a connection attempt using WSAConnect. This returns immediately, and the window procedure of my internal helper window will get notified as soon as the connection succeeded. In case the connection is closed (because the remote client went away), the message procedure will be called and I will attempt to reconnect.
This system allows the me to attach and detach a remote client at will. It works quite well, but unfortunately it requires that I have a message loop running. Without the message loop, the notifications sent by the WSAAsyncSelect call don't seem to arrive at my helper window.
Is there any way to implement a class as described above without requiring a message loop? I was toying around with using blocking sockets in a helper thread, but I couldn't come up with anything reasonable yet. I also considered using a UDP socket, so that I don't even need to connect at all, but I'd like to know whether there is a remote client listening so that in case there is no remote client, the clients of the NetworkOutput class don't need to do any serialization work of complex objects before they can call write().
You can use WSAEventSelect instead of WSAASyncSelect, which takes the handle of a WSAEVENT instead of a message ID, and then use WSAWaitForMultipleEvents to wait for the event to be signalled.
Instead of WSAEVENT you can also use normal Win32 events created with CreateEvent, and the normal synchronisation functions such as WaitForMultipleObjects.
You are looking for the select function:
http://support.sas.com/documentation/onlinedoc/sasc/doc750/html/lr2/select.htm
Basically you specify a set of ports you want to listen to.
When called the select deschedules the thread (thus allowing other threads to work while you do a non busy wait). Your thread is woken up after either a time limit (usually infinite) a signal (if you want to manually make the thread or the system does) or there is some input that needs to be handled on any of the ports.
When your thread wakes up it is usually best to let another thread handle the work so; what usually happens is that you create a work object for each port that has data waiting to be read and add these to a queue where a set of worker threads than start handling the input. Once this is done you call select() again to wait for more input.
Note: You don't have to do this it can be done in a single thread.