Code Monkey home page Code Monkey logo

Comments (10)

bel2125 avatar bel2125 commented on May 19, 2024

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?

from civetweb.

slimshader avatar slimshader commented on May 19, 2024

That is mongoose "hello world":

int main(void) {
struct mg_server *server = mg_create_server(NULL, NULL);
mg_set_option(server, "document_root", "."); // Serve current directory
mg_set_option(server, "listening_port", "8080"); // Open port 8080

for (;;) {
mg_poll_server(server, 1000); // Infinite loop, Ctrl-C to stop
}
mg_destroy_server(&server);

return 0;
}

And from the docs:

"void mg_poll_server(struct mg_server *server, int milliseconds);
Performs one iteration of IO loop by iterating over all active connections, performing select() syscall on all sockets with a timeout of milliseconds. When select() returns, Mongoose does an IO for each socket that has data to be sent or received. Application code must call mg_poll_server() in a loop."

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.

from civetweb.

bel2125 avatar bel2125 commented on May 19, 2024

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.
Why do you think you can not use the multi-threaded version?

from civetweb.

slimshader avatar slimshader commented on May 19, 2024

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.

from civetweb.

bel2125 avatar bel2125 commented on May 19, 2024

I recently added functions to protect objects that are not thread safe:
https://github.com/bel2125/civetweb/blob/master/include/civetweb.h#L341

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 initial discussion was to do this for V1.6, but later I decided that V1.6 should be mainly about Lua redesign. V1.6 is released since about 3 weeks (and I took some holidays afterwards). So we can continue the discussion for V1.7 right now.

The is some more threading discussion here:
https://groups.google.com/forum/#!topic/civetweb/jQMC-okP2xk

from civetweb.

slimshader avatar slimshader commented on May 19, 2024

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.

from civetweb.

bel2125 avatar bel2125 commented on May 19, 2024

Actually it can be done with the present lock mechanisms in the API as well.
However, I agree that when we rewrite the threading mechanism, we should also support that civetweb does not create any thread at all - so you would have to use a poll interface like the one you need.

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.

from civetweb.

bel2125 avatar bel2125 commented on May 19, 2024

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.
It was reported when we planned to rewrite the threading model used within the server. Civetweb uses one thread per open connection, which in theory appears to be a bad idea since it uses a lot of threads, and threads are in theory expensive. Now, meanwhile we tested >32000 clients with one Civetweb instance by just creating 32000 threads, and in practice did not have any problems on a 5 year old standard desktop computer (see #50). It was not even a special server hardware but something you might even get second hand for <100$ nowadays.
So the original reason to restructure the threading model is no longer true (it was never true, but now there is an experimental evidence).

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.
Internally it will be some kind of lock or message queue, but not a really single threaded server.
Also I will start with this example not before the next release.

from civetweb.

slimshader avatar slimshader commented on May 19, 2024

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.

from civetweb.

bel2125 avatar bel2125 commented on May 19, 2024

I technically agree.
But boost is a C++ library and civetweb is and should remain pure C.
Changing the threading model and stabilizing the server again is a lot of work, and I can currently not take this effort.
I just wanted to state the original reason to restructure the threading model, the expected limit for a high number of connections, turned out to be not really a problem.

from civetweb.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.