Multithreading

Overview

This tutorial will show you how to work with Mongoose on a multithreaded environment.

When serving static pages or even in dynamic RESTful servers, it is common to return content on the same callback function that handles the request. However, when that request triggers an action that requires a long processing time, we might want to take advantage of a multithreaded environment and spawn a new thread for each request to take care of it.

As explicitly noted in the documentation, Mongoose is not thread-safe:

Since Mongoose's core is not protected against concurrent accesses, make sure that all mg_* API functions are called from the same thread or RTOS task.

To be able to use several threads, we need a mechanism that enables these threads to communicate with the main context in which the event manager is running. We can use a lock-free queue for that, though the event handler needs to poll for messages in that queue when it receives an MG_EV_POLL event. To have the event manager thread sleeping and wakeup when necessary, Mongoose provides a socket-based helper function.

** GRAPH **

  • The initialization sequence inits the wakeup scheme calling mg_wakeup_init()
  • The client connects to our web server
  • The usual event handler callback function receives the request, though this time, instead of handling it and sending a response, it will spawn a worker thread and pass the request to it
  • The worker thread does it work and, when processing has finished, writes its response calling mg_wakeup(), frees its resources and exits
  • This wakes up the event manager, and the web server event handler receives an MG_EV_WAKEUP event, carrying the response from the worker; then sends it to the client

Build and run

This example starts a web server that spawns a thread to handle each request. That thread will sleep for a second, simulating a long process, and send a response back. If you POST to it, it will send the CRC of the posted data, otherwise it will just let you know that.

  • Follow the Build Tools tutorial to setup your development environment.
  • Start a terminal in the project directory; if you've not already done so, clone the Mongoose Library repo
    git clone https://github.com/cesanta/mongoose
    
  • Build the example, this will also start Mongoose:
    cd mongoose/examples/multi-threaded
    make clean all
    
  • Go to http://localhost:8000 in your browser; after two seconds, you'll see a response

How it works

For each incoming request:

  • The event handler function receives an MG_EV_HTTP_MSG event
    • allocates memory for a structure
    • duplicates the HTML message body containing the request
    • spawns a new thread and hands over the request to it
  • The worker thread:
    • simulates a long processing time (parsing and executing the request)
    • writes a response using mg_wakeup()
    • frees resources and exits
  • The event handler function receives an MG_EV_WAKEUP event
    • gets the response data and forwards it to the client

On program startup, we initialize the event manager and the wakeup scheme, create the listener, and call the event manager in an infinite loop:

Browse latest code