title: Is this the correct way to use pthread?
body: <p>I am trying to create an HTTP server using multi-threading. <em>main()</em> hands off the client_sock from <em>accept()</em> to one of the worker threads. If no worker threads are available, it waits until one is. I am restricted to not being able to call <em>accept()</em> within the worker threads. Here is a portion of my code so far. Some questions I have are:</p>
  <ol>
  <li>Do I need to use 2 pthread mutex and condition variables as I do right now?</li>
  <li>Do I need to use pthread lock or unlock at all in these cases?</li>
  <li>If I wanted to add a mutex lock when files are being created on the server, would I have to create another mutex variable or would one of the existing ones work?</li>
  </ol>
  <pre class="lang-c prettyprint-override"><code>#include &lt;iostream&gt;
  #include &lt;err.h&gt;
  #include &lt;fcntl.h&gt;
  #include &lt;netdb.h&gt;
  #include &lt;string.h&gt;
  #include &lt;sys/socket.h&gt;
  #include &lt;sys/stat.h&gt;
  #include &lt;sys/types.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;getopt.h&gt;
  #include &lt;pthread.h&gt;
  
  #define SIZE 1024
  
  struct shared_data
  {
      int redundancy;
      int client_sock;
      int working_threads;
      int dispatch_ready;
      pthread_mutex_t* dispatch_mutex;
      pthread_mutex_t* worker_mutex;
      pthread_cond_t* dispatch_cond;
      pthread_cond_t* worker_cond;
  };
  
  void* receiveAndSend(void* obj)
  {
      struct shared_data* data = (struct shared_data*) obj;
  
      int bytes;
      char buff[SIZE + 1];
  
      while(1)
      {
          while(!data-&gt;dispatch_ready)
          {
              pthread_cond_wait(data-&gt;dispatch_cond, data-&gt;dispatch_mutex);
          }
          data-&gt;dispatch_ready = 0;
  
          data-&gt;working_threads++;
  
          client_sock = data-&gt;client_sock;
  
          bytes = recv(client_sock, buff, SIZE, 0);
  
          // do work
  
          data-&gt;working_threads--;
          pthread_cond_signal(data-&gt;worker_cond);
      }
  }
  
  int main(int argc, char* argv[])
  {
      if(argc &lt; 2 || argc &gt; 6)
      {
          char msg[] = &quot;Error: invalid arg amount\n&quot;;
          write(STDERR_FILENO, msg, strlen(msg));
          exit(1);
      }
  
      char* addr = NULL;
      unsigned short port = 80;
      int num_threads = 4;
      int redundancy = 0;
      char opt;
  
      while((opt = getopt(argc, argv, &quot;N:r&quot;)) != -1)
      {
          if(opt == 'N')
          {
              num_threads = atoi(optarg);
  
              if(num_threads &lt; 1)
              {
                  char msg[] = &quot;Error: invalid input for -N argument\n&quot;;
                  write(STDERR_FILENO, msg, strlen(msg));
                  exit(1);
              }
          }
          else if(opt == 'r')
          {
              redundancy = 1;
          }
          else
          {
              // error (getopt automatically sends an error message)
              return 1;
          }
      }
  
      // non-option arguments are always the last indexes of argv, no matter how they are written in the terminal
      // optind is the next index of argv after all options
      if(optind &lt; argc)
      {
          addr = argv[optind];
          optind++;
      }
  
      if(optind &lt; argc)
      {
          port = atoi(argv[optind]);
      }
  
      if(addr == NULL)
      {
          char msg[] = &quot;Error: no address specified\n&quot;;
          write(STDERR_FILENO, msg, strlen(msg));
          exit(1);
      }
  
      struct sockaddr_in serv_addr;
      memset(&amp;serv_addr, 0, sizeof(serv_addr));
      serv_addr.sin_family = AF_INET;
      serv_addr.sin_addr.s_addr = getaddr(addr);
      serv_addr.sin_port = htons(port);
  
      int serv_sock = socket(AF_INET, SOCK_STREAM, 0);
      if(serv_sock &lt; 0)
      {
          err(1, &quot;socket()&quot;);
      }
  
      if(bind(serv_sock, (struct sockaddr*) &amp;serv_addr, sizeof(serv_addr)) &lt; 0)
      {
          err(1, &quot;bind()&quot;);
      }
  
      if(listen(serv_sock, 500) &lt; 0)
      {
          err(1, &quot;listen()&quot;);
      }
  
      // Connecting with a client
      struct sockaddr client_addr;
      socklen_t client_addrlen;
  
      pthread_mutex_t dispatch_mutex;
      pthread_mutex_init(&amp;dispatch_mutex, NULL);
      pthread_mutex_t worker_mutex;
      pthread_mutex_init(&amp;worker_mutex, NULL);
      pthread_cond_t dispatch_cond;
      pthread_cond_init(&amp;dispatch_cond, NULL);
      pthread_cond_t worker_cond;
      pthread_cond_init(&amp;worker_cond, NULL);
  
      struct shared_data data;
  
      data.redundancy = redundancy;
      data.dispatch_ready = 0;
      data.working_threads = 0;
      data.dispatch_mutex = &amp;dispatch_mutex;
      data.worker_mutex = &amp;worker_mutex;
      data.dispatch_cond = &amp;dispatch_cond;
      data.worker_cond = &amp;worker_cond;
  
      pthread_t* threads = new pthread_t[num_threads];
      for (int i = 0; i &lt; num_threads; i++)
      {
          pthread_create(&amp;threads[i], NULL, receiveAndSend, &amp;data);
      }
  
      while(1)
      {
          data.client_sock = accept(serv_sock, &amp;client_addr, &amp;client_addrlen);
  
          while(data.working_threads == num_threads)
          {
              pthread_cond_wait(data.worker_cond, data.worker_mutex);
          }
  
          data.dispatch_ready = 1;
          pthread_cond_signal(data.dispatch_cond);
      }
  
      return 0;
  }
  
  </code></pre>