How to make and synchronize p_threads that make request channels to a shared dataserver to send and retrieve requests?

We are learning to use posix threads in class. Our assignment is to create a bounded buffer for multiple request channels to withdraw requests and send them to one data server.

Here is how the class RequestChannel (provided for us) sends a request:

string RequestChannel::send_request(string _request) {
  cwrite(_request);
  string s = cread();
  return s;
}

string RequestChannel::cread() {
  char buf[MAX_MESSAGE];
  string s = buf;
  return s;
}

We make a RequestChannel in main called chan

RequestChannel chan("control", RequestChannel::CLIENT_SIDE);

called "control", and this is how it would send a request:

string reply = chan.send_request("newthread");

We start off with one control RequestChannel, which asks the data server to make us more RequestChannels.

Here is what DataServer.C looks like (also provided for us)

void process_request(RequestChannel & _channel, const string & _request) {
  if (_request.compare(0, 9, "newthread") == 0) {
    process_newthread(_channel, _request);
  }
  else {
    _channel.cwrite("unknown request");
  }
}

(I omitted processing other requests here, since I am only interested in making a new thread right now)

Here is the part I'm lost on:

void process_newthread(RequestChannel & _channel, const string & _request) {
  int error;
  nthreads ++;

  // -- Name new data channel

  string new_channel_name = "data" + int2string(nthreads) + "_";
  //  cout << "new channel name = " << new_channel_name << endl;

  // -- Pass new channel name back to client

  _channel.cwrite(new_channel_name);

  // -- Construct new data channel (pointer to be passed to thread function)

  RequestChannel * data_channel = new RequestChannel(new_channel_name, RequestChannel::SERVER_SIDE);

  // -- Create new thread to handle request channel

  pthread_t thread_id;
    cout << "starting new thread " << nthreads << endl;
  if (error = pthread_create(& thread_id, NULL, handle_data_requests, data_channel)) {
    fprintf(stderr, "p_create failed: %s\n", strerror(error));
  }  

}

Even with the boatload of comments, could someone explain:

  1. Where is the new thread?
  2. How can we find it and use it back in main?

Here was the code in main() to send requests to make new request channels and make new worker threads. Worker threads take one request channel and go to a function to process requests.

RequestChannel* channels[w];
    for(int i=0; i < w; i++){
        string reply = chan.send_request("newthread");
        channels[i] = new RequestChannel(reply, RequestChannel::CLIENT_SIDE);
    }
    cout << "-- done\n";
    pthread_t worker_threads[w];

    cout << "Creating worker threads...\n";
    for(int i = 0; i < w; i++){
        pthread_create(&worker_threads[i], NULL, sendAndRetrieveRequests, channels[i]);
    }
    cout << "-- done\n";

The block of code here is the solution I found online to this exact assignment, copied all the way, yet it won't work. *

This is the kind of errors I'm getting:

:: ./simpleclient
CLIENT STARTED:
Establishing control channel... done.


making boundedbufferslist
Creating channels for worker threads...
Received request : newthread
Request Channel (control) writing [newthread]in cread(), s is...uest
Request Channel (control) reads [uest]
processed cwrite : uest
Reading next request from channel (control) ...in cread(), s is...newthread
Request Channel (control) reads [newthread]
 done (control).
New request is newthread
^C

Solutions I have tried on my own:

  1. Use a Semaphore before and after requesting for a new thread in the for loop. This leads to pausing forever and never making a request, or receiving a request of [#]??

    2.First create the worker threads, and inside the worker thread ask for a new request channel thread -- > this usually leads to an error of trying to make the first thread, and pauses forever or all the workers scrambling to make the same request, in this case, I used a semaphore shared with all the workers, but it goes back to pausing forever for the first thread to make. In that case, I messed with the semaphore but I either get one or two of these errors.

  2. With a worker thread, pass in a struct holding a pointer to the control thread (and other buffers), and ask for new request channel within that function. Same errors as #2.

  3. A few attempts with cout's and making only one thread to test where it stops.

I think I am missing a fundamental understanding of threads.

*I know it is unethical to copy someone else's code, but I wanted to see what a correct solution looks like after trying on my own. It doesn't work though, and neither did my solutions. I would like to learn how it works and to make my own solutions too in the future.


If there is anything else you need, please ask. This is my first time posting on stackoverflow.