Hello,

I try to use libmicrohttpd in conjunction with a main function which
acquires data in an endless loop (currently every 4 seconds).

What I want to achieve is that all the current client connections
with an active request for this data will block until it is
available.

Thus I decided to go for the MHD_USE_THREAD_PER_CONNECTION model.

I tried to use pthread_cond_wait and pthread_cond_broadcast to
implement the blocking scheme, but unfortunately this does not work
as expected when more than one client is in use.

Attached is a broken down example code.

compile with:
cc -o httpd-test -g -Wall -W httpd-test.c -lmicrohttpd

As a client I currently use a
couple of "wget -q -O - http://localhost:8888"; calls.

Any hint?

Sven

-- 
/* Fuck me gently with a chainsaw... */
(David S. Miller in /usr/src/linux/arch/sparc/kernel/ptrace.c)

/me is giggls@ircnet, http://sven.gegg.us/ on the Web
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdarg.h>
#include <microhttpd.h>
#include <pthread.h>

#define DELAY 4

#define UNUSED(expr) do { (void)(expr); } while (0)

float cur_val;

pthread_cond_t cv; 
pthread_mutex_t mutex; 
int nrclients=0;

static int answer_to_connection(void * cls,
		    struct MHD_Connection * connection,
		    const char * url,
		    const char * method,
                    const char * version,
		    const char * upload_data,
		    size_t * upload_data_size,
                    void ** ptr) {
  static int dummy;
  static char statedata[1024];
  struct MHD_Response * response;
  int ret;

  // ignore explicitely unused parameters
  // eliminate compiler warnings
  UNUSED(cls);
  UNUSED(url);
  UNUSED(version);
  UNUSED(upload_data);
  UNUSED(upload_data_size);

  if (0 != strcmp(method, "GET"))
    return MHD_NO; /* unexpected method */

  if (&dummy != *ptr) {
    /* The first time only the headers are valid,
       do not respond in the first round... */
    *ptr = &dummy;
    return MHD_YES;
  }

  *ptr = NULL; /* clear context pointer */

  nrclients++;
  printf("pthread_cond_wait\n");
  pthread_cond_wait(&cv, &mutex);
  nrclients--;
  snprintf(statedata,1024,
	   "cur_val=\"%5.1f\";\n",
	   cur_val);
  response = MHD_create_response_from_data(strlen(statedata),
					   (void*) statedata,
					   MHD_NO,
					   MHD_NO);
  MHD_add_response_header(response,
			  "Content-Type", "text/javascript");
 
  ret = MHD_queue_response(connection,
                           MHD_HTTP_OK,
                           response);
  MHD_destroy_response(response);

  return ret;
}

int main() {

  unsigned first;
  struct MHD_Daemon *daemon;

  first=1;
  while (1) {

    cur_val=42;

    if (first) {
      daemon = MHD_start_daemon(MHD_USE_THREAD_PER_CONNECTION,
				8888,
				NULL,
				NULL,
				&answer_to_connection,
				NULL,
				MHD_OPTION_END);
      if (daemon == NULL) {
	fprintf(stderr,"unable to run HTTP Server!\n");
	exit(EXIT_FAILURE);
      }
      first=0;
    } else {
      if (nrclients >0) {
	/* push values to clients */
	printf("pthread_cond_broadcast (%d)\n",nrclients);
	pthread_cond_broadcast(&cv);
      }
    }
    printf("acquire data here...\n");
    sleep(DELAY);
  }

  MHD_stop_daemon (daemon);
  exit(EXIT_SUCCESS);
}

Reply via email to