#1
  1. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    May 2003
    Posts
    79
    Rep Power
    12

    Question multithread intercommunication help


    I have run into a situation where I need to use multithreading in order to ocomplish my task. Now all I could find on the net on multithreading gave me enough info to create a couple basic threads. What I need to be able to do is share information between the threads.

    I have one OpenGL thread that is drawing. I have another thread that is recieving udp packets from the internet. Now I need the networking thread to be able to pass the info it recieves to the OpenGL thread for drawing.

    This may be simple and I may just be missing the obvious but im stuck. If anyone has an suggestions, tutorials, or eample code on passing info between threads it would be a huge help.

    Thanks.
  2. #2
  3. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,255
    Rep Power
    2222
    The first question is whether you are doing this in Windows or Linux. Both support multithreading, but with different functions and possibly other differences.

    Basically, threads are separate lines of code being executed independently. They have their own stack and their own local variables (which were declared in the function passed to the start_thread function call). But they share the program's global variables, which normally forms the basis for inter-thread communication.

    As I understand your objective:
    1. the OpenGL thread will read data from a buffer and display it.
    2. the udp thread will receive data from the network and store it in the buffer that the OpenGL thread will read.

    So that buffer will be declared globally so that the two threads can both access it. The udp thread will add data to the buffer. The OpenGL thread will periodically check to see if there's something in the buffer. If there is then it will process it, emptying the buffer as it does so. If the buffer is empty, then it will do something else for a while (even if it's just sleep()) then check the buffer again.

    Since there can be problems if both threads try to operate on the buffer at the same time, you should use a mutex ("mutual exclusion"). The buffer and their code where the buffer is accessed and changed is called a "critical section". Before a thread enters a critical section, it needs to lock the mutex so that it has exclusive access blocking all other threads. Then when it leaves that critical section, it unlocks the mutex allowing the other threads access. If that critical section is already locked, then the thread's mutex_lock call will block until the mutex has been unlocked by the other thread, whereupon it can proceed.

    BTW, watch out for conditions where both threads are waiting for a resource that the other thread has already locked. Neither will ever be able to continue. As I recall, that's called a "race condition" or a "deadly embrace".

    Also, multithreaded programs are difficult to debug.

    The Wrox book, "Beginning Linux Programming", has a chapter on pthreads and describes the use of mutexes. So should several sites on the Web, now that you know to Google on mutex.
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2002
    Posts
    272
    Rep Power
    19
    A race condition is what might occur if the mutex is not used. The data might be read while it is being written, which can cause what is read to be only partially correct. A deadly embrace (also know as a deadlock) is what will happen if both threads block on the same condition.
  6. #4
  7. No Profile Picture
    .
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2002
    Posts
    296
    Rep Power
    12
    on the system i'm using - mac os x, which is unix based, so pthreads - doing anything graphical or user interfacial from a thread other than the main one seems to be problematic. - possible but extra complications and if possible much better avoided - just from less work p-o-v. not sure if that specific to os x or applies to other sytems.
  8. #5
  9. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    May 2003
    Posts
    79
    Rep Power
    12
    Thank you dwise1... that was very helpful. I am writing this code for windows probably will be used on 2k and XP. A question about "mutex". I understand how you explained it but tell me in my situation weather it is nessecary.

    This is the server example of the code.

    What basically happens is the OpenGL thread draws frames of a player model to the screen. The coordinates of where the model is drawn is recieved by the network thread and then passed to the OpenGL thread thru a global variable. So using structures you would have a new structure created for every player that connects to the server. Then as they move thier player arround on the client it sends the data to the network thread of the server. It then it stores the players coordinates in the players coordinates variable of thier structure. Opengl thread reads thier coordinates from the variable and then draws the player model in the appropriate position. Now what if the player doesnt move? The variable wont be updated so the OpenGL thread will read the same coordinates and draw the model in the same place. Now this is right to me cause the player hasnt moved so it should be drawn in the same place.

    Does this situation need "mutex"?

    I have found a few tutorials but they aren't very good...can you recommend a good multithread for windows tutorial?

    I also noticed that balance mentioned graphics in a thread can cause problems. Should I leave the graphics code in the main section of the program and only have the network code as a thread.(if I dont put udp code in a thread it stalls the game waiting for packets.)?
  10. #6
  11. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,255
    Rep Power
    2222
    Originally posted by phantom_turtle
    I understand how you explained it but tell me in my situation weather it is nessecary.

    This is the server example of the code.

    What basically happens is the OpenGL thread draws frames of a player model to the screen. The coordinates of where the model is drawn is recieved by the network thread and then passed to the OpenGL thread thru a global variable. So using structures you would have a new structure created for every player that connects to the server. Then as they move thier player arround on the client it sends the data to the network thread of the server. It then it stores the players coordinates in the players coordinates variable of thier structure. Opengl thread reads thier coordinates from the variable and then draws the player model in the appropriate position. Now what if the player doesnt move? The variable wont be updated so the OpenGL thread will read the same coordinates and draw the model in the same place. Now this is right to me cause the player hasnt moved so it should be drawn in the same place.

    Does this situation need "mutex"?
    The buffer I envisioned was a FIFO buffer, AKA a "queue". The udp thread would write to it by adding a new data object to it. The OpenGL thread would read from it by removing the next data object from it. When all data objects have been read/removed from the buffer, then it would be empty. Hence, the situation in which the OpenGL thread would read a data object previously read would not happen.

    We've implemented this kind of a buffer with an array that we use as a ring buffer. We maintain two indices, a head and a tail. The head tells us where the next item will be inserted and the tail tells us where the next one is to be read. If head == tail, then the buffer is empty.

    So, yes, you would still need a mutex because you will still have a critical section. The OpenGL thread would periodically lock the critical section. If it's empty, it would immediately unlock, else it would read the data and remove it from the buffer. Then it would unlock the critical section. The mutex is still needed to keep both threads from changing the buffer at the same time before either is done with it.

    Originally posted by phantom_turtle
    Thank you dwise1... that was very helpful. I am writing this code for windows probably will be used on 2k and XP.

    ...

    I have found a few tutorials but they aren't very good...can you recommend a good multithread for windows tutorial?
    Most of my background with threads is POSIX threads (AKA "pthreads") on Linux. For that matter, we just covered it in class two weeks ago. For Windows threads, I have a couple books, but I'm not familiar with what's online for it.

    Since you are using Windows' threads, you need slightly different keywords.

    MFC provides you with a CCriticalSection class which you initialize, lock, and unlock. You will work with a CWinThread object.

    In Windows API, Petzold describes the CRITICAL_SECTION data type and its associated functions:
    InitializeCriticalSection(CRITICAL_SECTION *cs);
    EnterCriticalSection(CRITICAL_SECTION *cs);
    LeaveCriticalSection(CRITICAL_SECTION *cs);
    DeleteCriticalSection(CRITICAL_SECTION *cs);

    Perhaps those keywords will help narrow your search.

    Originally posted by phantom_turtle

    I also noticed that balance mentioned graphics in a thread can cause problems. Should I leave the graphics code in the main section of the program and only have the network code as a thread.(if I dont put udp code in a thread it stalls the game waiting for packets.)?
    Actually, every program runs at least one thread, the main thread. It's my understanding that in Windows especially you should keep the UI in the main thread, which includes the graphics. The networking code should do quite well in a second, worker thread.
  12. #7
  13. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    May 2003
    Posts
    79
    Rep Power
    12
    Thanks again for your help....

    Im reading thru some info on it now... It all makes alot more sense to me now.
  14. #8
  15. No Profile Picture
    .
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2002
    Posts
    296
    Rep Power
    12
    i think more often than not, locking shared data is necessary, to make sure only one thread at at ime can make use of it. not needing to lock shared data seems quite rare. an example of shared data that doesn't require locking might be this:

    one thread (not the main one) doing long-winded job. main thread used, amoungst otherthings, to report the progress of the other thread in a progress bar. the data in the non-main thread that indicates how far it's got in the job so far, doesn't have to be locked even though it's shared - the main thread is simply reading from it (not changing it), and if it happens to get slightly old or inaccurate data it really doesn't matter much - nothing's going to go awry if it does - it's only using it to display a progress bar, which is not something that's relied on for absolute accuracy, so therefore not critical.

    a good analogy of the need for locking that i recently read was 2 people using a shared bank account and both requesting the balance in the account and making withdrawls, from seperate cash machines at the same time. - the amount of money in the account being a critical piece of info.
  16. #9
  17. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    May 2003
    Posts
    1
    Rep Power
    0

    HawkNL


    I use HawkNL network library. It is an linux/windows library that in windows comes as a dll file and it handles udp sockets.

    It takes care of all the multithread stuff for you hand you just check the buffer in a loop. Very simple.

    You can find it here http://www.hawksoft.com/hawknl/

    Try it, it has examples using mutex and multithreaded servers to.

    /David
  18. #10
  19. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    May 2003
    Posts
    79
    Rep Power
    12
    davidmartensson,

    you mention that I should try the Hawk Network Library. It looks interesting and I would like to try it out but all I could find on the page is docs on the functions. Is there any docs on how to include it in a project, wich files to include and maybe a small example of it being used?

    Thanks

IMN logo majestic logo threadwatch logo seochat tools logo