Friday, January 25, 2013

Vital to server programming: pthreads!

Making request threads with pthread. This is just a theory I developed while I was in jail--bored out of my mind, wanting to get in front of a compiler.


So let's say we have the main() function, that's the one thread we always start off with.


#include<stdio.h>
#include<iostream>

int main(){
    while(true){
    }
    std::cout << "Hello World!" << endl;
    return 0;
}


If we execute this, will we ever get to see "Hello World!"? The answer is no. Since our main() thread is in a while(true) loop. Not until we return false; will we ever see "Hello World!" be displayed in output.

How about if we wanted to handle client connect/disconnect, handle database requests and also game requests? Wouldn't that require more than one while loop? Yes it would.

The answer is simple: we use pthreads.

Let's get rid of that while loop on main() and we'll use it somewhere else. Let main() be where all the threads start.

Let's create a thread identifier.
pthread_t t1;

Okay let's attach it to connectionThread.
pthread_create(&t1,NULL,connectionThread,NULL);


Then let's start it.
pthread_join(t1, NULL);

Here's how it would look in the main() would look now.


#include<stdio.h>
#include<iostream>

int main(){

    pthread_t t1;
    pthread_create(&t1,NULL,connectionThread,NULL);
    pthread_join(t1, NULL);

return 0;
}

Don't forget we also need to create connectionThread. It is required to have return void* and void* as a parameter. You must put this or it will not work!

void* connectionThread(void*){
    while(true){
         std::cout << "Connection Thread running!" << endl
    }
    return 0;
}

And there you have it. Another thread. You can always add more threads to suit your applications. Just repeat the same steps above.

Go ahead, try to create another thread, and have another while loop in there. They will run.. simultaneously!


YOU'RE NOT DONE YET!

Let's say you have two threads, and both of them access a vector. And let's also say one thread removes objects from this vector while another one analyzes it. You could say that this would cause very messy problems and possibly (most likely) even crash during runtime.

Well this is where mutex locks come in. Mutex stands for mutual exclusion. (Just letting you know so it doesn't look like some fucking alien programming term)

So we'll declare a lock (and like threads, you can declare as much as you want). Make it global (not declared within any threads) just so all the threads can access it.
pthread_mutex_t lock;

We'll initialize it in main()
if(pthread_mutex_init(&lock, NULL) != 0){
    perror("mutex");
    exit(EXIT_FAILURE);
}

Then in the chunk of code where the thread is accessing the vector, wherever it is critically accessing it. You should put at the beginning..
pthread_mutex_lock(&lock);

If the mutex isn't currently locked--then the function above will take the lock otherwise it'll block until the mutex is unlocked.

After the thread has accessed the vector and it is finished with the vector. Put this at the end to unlock it so other threads can claim the lock.
pthread_mutex_unlock(&lock);

And that's basically all you need to know for pthreads! Once you implement these simple procedures, you will have what you would call a multi-threaded application.

No comments:

Post a Comment