-
Notifications
You must be signed in to change notification settings - Fork 935
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
poll interface #28
Comments
I think there has never been a mg_poll_server interface in Civetweb. Civetweb was forked from Mongoose in summer 2013 - since then they are two different webservers with different developers who have different ideas and priorities. Probably mg_poll_server has been added later? What is this function actually supposed to do? |
That is mongoose "hello world": int main(void) { for (;;) { return 0; And from the docs: "void mg_poll_server(struct mg_server *server, int milliseconds); So basically its api allows to handle server requests in the thread of users choosing - for example from the main thread. Civetweb does not currently allow it. Poll api could be added to Civetweb quite easily imho: when number of threads passed to mq_start() is 0 (zero) then user has to explicitly call mg_poll_server() to process all pending requests in that thread. It would be very useful for applications that already run in a loop constantly - like a game in my example. |
I once planned to provide a way to run the server in a single threaded environment - with the focus to small embedded devices, not game engines, but it would basically work for you as well. It is also useful for debugging, but I don't thing it is really simple. We can not take any code from mongoose, since it has an incompatible license. I did not do this yet, because I always considered it "nice to have", but not as essentially necessary - up to now I could afford the extra threads and I managed to debug it also as a multi-threaded application. |
It is problematic when you want to embed it in already functional application. Because server request handlers are always called from new thread, all the objects that will be accessed from it suddenly have to be thread safe. This bad idea for several reasons. Also, current design is also not very efficient as it should use tasking and not thread-per-request and that could also be fixed by moving threading model to the user. Civetweb must have client processing loop implemented already, why not expose it to the user? Why would Mongoose code be needed? I will survive as I already made my C++ version of HttpServer poll-based. Requests from handler thread are added to internal queue, then thread blocks, waits for a call to poll() from main thread, poll() fullfills queued requests and wakes handler thread to resume client processing. |
I recently added functions to protect objects that are not thread safe: I agree, the current "thread-per-connection" design is not very efficient. We discussed that since October 2013: https://groups.google.com/forum/#!topic/civetweb/sFHF75IDSH0 The is some more threading discussion here: |
mg_(un)lock_context(struct mg_context* ctx) seem ok to sync all worker threads but what about main application thread (and others)? Imagine you have a GUI application, user interacts with it the usual way, clicks widgets, edits with keyboard etc, lets say it is an spreadsheet app. In the background there is civetweb server running handling a request to print webpage based on the current state of the spreadsheet, now the spreadsheet has to locked every time it is accessed by civetweb or the user. But if there was poll interface, civetweb could be polled in the GUI thread explicitly or in some kind of Timer object that also triggers code in man/UI thread making everything just work correctly and integration of a server a breeze. |
Actually it can be done with the present lock mechanisms in the API as well. Changing the threading mechanism is not something that can be done quickly over the weekend, so it might take some weeks until I find time to look at this more closely. |
This issue is now open for a while, so I want to update the status: The issue is a request for an interface to use the web server in a way it does not create any thread, but only works as a callback called from an external thread. Thus, I think I will not restructure the threading model any time soon. Still, I do understand the problem and probably make a short example how you could use the multi-threaded server in an otherwise single-threaded application without taking care about locks there. |
It is not just a matter of performance, threading model should not be part of library or should be configurable at very least (whether task scheduler is single threaded or a pool of threads or just blocking etc.). For example boost.asio which is de-facto standard high performance networking / asynchronous request handling does not create threads for handling messages but lets the user decide how it should be handled. This way if user wants to create thread-per-connection it is perfectly fine (and often the choice) but still allows to customize things enough to be able to handle requests from very specific thread (like UI thread). If it wont happen for civetweb that's fine, I am syncing it manually now anyway but configurability is a good thing. |
I technically agree. |
Why is there no poll interface as with mongoose. I mean equivalent of mg_poll_server()?
I understand that current design might be more convenient to some but original one was much more flexible because threading model was up to the user.
In my case I am using civetweb in game engine and I had to really work-around current design to get back to original poll version.
The text was updated successfully, but these errors were encountered: