Re: libfcgi in multi threaded app
"Martin Chapman" <[email protected]> Mon, 3 May 2010 11:14:10 -0600
| Newsgroups | gmane.comp.web.fastcgi.devel |
|---|---|
| Message-ID | <585FF838A7EB4CD88CD2C05DE0BCAD0B@chapmanm64> |
Rob, So how does this solution account for the fact that FCGX_Accept_r () resets the stdio global structure each time it's called? If you are synchronizing the code between each request, regardless of it's processed on a separate worker thread then only one request at a time is really being executed. Martin -----Original Message----- From: fastcgi-developers-bounces+chapmanm=pixia.com-xGejAJT2w6xVgU18Zptdi0EOCMrvLtNR@public.gmane.org [mailto:fastcgi-developers-bounces+chapmanm=pixia.com-xGejAJT2w6xVgU18Zptdi0EOCMrvLtNR@public.gmane.org] On Behalf Of Rob Sent: Monday, May 03, 2010 11:06 AM To: [email protected] Subject: Re: [FASTCGI] libfcgi in multi threaded app On 05/03/2010 10:27 AM, AlannY wrote: > I've created a socket via FCGX_OpenSocket. Everything all right. > > Then, I'm creating threads (5, for example). In each thread, I'm > creating a request with FCGX_InitRequest (with socket, created early and > FCGI_FAIL_ACCEPT_ON_INTR). > > Then the main loop starts. In this loop I'm calling FCGX_Accept_r on > this request. Here is trouble. Some of threads can successfully accept, > but some of then can't. Return code from FCGX_Accept is -9. The main thread loop should repeatedly call FCGX_Accept_r(). Requests successfully accepted by FCGX_Accept_r() must then be passed off to your worker threads for processing. Therefore, you might choose to dynamically allocate an fcgi request structure before calling FCGX_Accept_r() and then pass the dynamically allocated request structure to an available worker thread. The worker thread would then process the request and then deallocate the request. The multi-threaded problem is: "how to pass the requests to the worker threads?" Your program will be simple and graceful if you choose the means of a synchronized queue data structure. In a synchronized queue object, all of the thread synchronization is performed upon access to get or put items on the queue. The mutex guards access to the internal data. The conditions NotFull and NotEmpty signal the threads to wake up appropriately via the condition primitives: notify_one or notify_all. We use C++ and boost::threads to do something like this: pseudo code for main thread: synchronized_queue_class synchronized_queue #this is the only object that must be visible from all threads function get_fcgi_request( request ) request = allocate(sizeof request) FCGX_init_request(request ...) if FCGX_Accept_r(request) is successful then return TRUE else return FALSE endif endfunction while get_fcgi_request( request ) synchronized_queue.Put(request) endwhile pseudo code for worker threads: while synchronized_queue.Get(request) process(request) deallocate(request) endwhile pseudo code for synchronized_queue_class: class synchronized_queue_class: queue internal_queue condition notFull_condition condition notEmpty_condition mutex monitor procedure Put(item): scoped_lock(monitor) while internal_queue.full() notFull_condition.wait(monitor) internal_queue.put(item) notEmpty_condition.notify_one() endprocedure procedure Get(item): scoped_lock(monitor) while internal_queue.empty: notEmpty_condition.wait(monitor) internal_queue.push(item) notFull_condtion.notify_one() endprocedure endclass (There are other details in the synchronized queue which should be addressed, such as how to shut down the queue at the end of the program and tell the worker threads to exit.) _______________________________________________ FastCGI-developers mailing list FastCGI-developers-xGejAJT2w6xVgU18Zptdi0EOCMrvLtNR@public.gmane.org http://mailman.pins.net/mailman/listinfo.cgi/fastcgi-developers