Thread: Threads and global variables

  1. #1
    Registered User
    Join Date
    May 2002
    Posts
    41

    Threads and global variables

    Hello!
    I hope this question isn't too stupid. I don't have a real clue about threads yet. My question is:
    I have several threads for my small chatserver, each thread is using one global string var and another thread is constantly pushing data into those buffers. Right now I have it that the main thread waits for the buffer to be empty before writing new stuff to it but that is too slow in the long run (because the chatthreads only send their buffer every second). So I want to attach the new info to the buffer if possible. Will this cause problems (errors?) when one thread is trying to delete this buffer (or parts of it) while another is trying to write into it at the same time? Or can't this happen?
    I'm still thinking of the times when I worked with ASCII databases. Whenever I had several processes writing and reading from it at once, chances are that the whole DB would be deleted. =)
    I hope this wasn't too confusing.

  2. #2
    ....
    Join Date
    Aug 2001
    Location
    Groningen (NL)
    Posts
    2,380
    >Will this cause problems (errors?) when one thread is trying to
    >delete this buffer (or parts of it) while another is trying to write
    >into it at the same time?

    If the reading process is faster than the writing process or vice versa, there is always one thread which as to wait. That's because buffers have finite length.

    You could use a circular buffer. For a small application I've once used a circular buffer, so that I could read and write at same time. You need two pointers for this, one pointing at the front and one pointing at the rear. The reading process reads data from the front and the writing process add data to the rear. Things can go wrong if one thread is faster than the other, then they have to wait on eachother. You should do some experimenting to find out what the size of the buffer should be to minimize waiting.

    Another solution would be to shift the buffer when data is read. So if your buffer is N bytes and you've read the last M bytes, then the N-M bytes which are not left can be shifted up to the output. This means that N-M bytes are free for the input, these free bytes can now be used by the writing process. Such pipes are also useful, but also here counts that the speed of the processes are the blocking detail. Also here you need to do some experimenting to find a nice buffer size to minimize waiting.

  3. #3
    Registered User
    Join Date
    May 2002
    Posts
    41
    Hello, thanks for your answer!
    Waiting time is not really my problem though. Both processes have a one second delay anyway, that's why writing line by line would be to slow, it should rather add let's say 1000 chars to the buffer so the reading thread can send them all together. My only worry is what happens when both processes want to write at the same time. Let's say the reading thread deletes the buffer and at the same time the writing thread wants to add some new chars. What will happen? Error or will one thread just wait for the other thread to finish before writing to the buffer? If that's the case then I have no problem. I just wanted to make sure that my program doesn't crash or accidently deletes all of the buffer when something like this happens (although accidently deleting the buffer wouldn't be a nightmare).

  4. #4
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Make a 'lock'. When a thread beings to do something to the variable, 'lock' it. When it is finished, unlock it.
    Code:
    struct buffer
    {
        char buf[BUFSIZE];
        long int threadLock;
    } globalBuffer;
    
    long int bufferText( long int caller, char *text )
    {
        if( globalBuffer.threadLock != -1 )
        {
            globalBuffer.threadLock = caller;
            memset( globalBuffer.buf, '\0', BUFSIZE );
            strncpy( globalBuffer.buf, text, strlen( text ) );
        }
        return globalBuffer.threadLock;
    }
    There. Now you can lock your thread with the number for the particular thread. When you're done, make an unlock function that sets the variable to -1.

    Quzah.
    Last edited by quzah; 05-28-2002 at 04:31 PM.
    Hope is the first step on the road to disappointment.

  5. #5
    Registered User
    Join Date
    May 2002
    Posts
    41
    Ok thanks. But is it needed? What _would_ happen if both threads would try to write at the global at the exact same time? Program crash? Lost data?

  6. #6
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Originally posted by Spark
    Ok thanks. But is it needed? What _would_ happen if both threads would try to write at the global at the exact same time? Program crash? Lost data?
    Nothing happens at the exact same time. They may be in the same "time slice", but they wouldn't be the exact same time. In any case, one would write, then the other would just write over top of it.

    So, yeah, data loss is likely.

    Quzah.
    Hope is the first step on the road to disappointment.

  7. #7
    Registered User
    Join Date
    May 2002
    Posts
    41
    Ok thanks.

  8. #8
    ....
    Join Date
    Aug 2001
    Location
    Groningen (NL)
    Posts
    2,380
    >But is it needed? What _would_ happen if both threads would
    >try to write at the global at the exact same time? Program
    >crash? Lost data?

    Assuming you're working on a machine with only one processor, operations can't happen at the same time. Though note that data can be lost. If the writing process puts a value in a variable before the reading process has read it, then the reading process will read the value which the writing process has just put there.

    To avoid problems like above, you have to make sure that it is not possible to read and write "at same time". You could make use of the concept of semaphores, which was introduced to solve problems like this. You can find information on semaphores in almost every book on operating systems.

    A semaphore is a variable which indicates that some process is in its critical section. In a critical section the process is using some piece of memory and no other process is allowed to use that memory during the time the first process is busy with it.

    Code:
    read_process ()
    {
        while (1)
        {
            wait (); /* Wait until memory is released */
            lock (); /* Lock memory */
            read_buffer (); /* Critical section */
            unlock (); /* Release memory */
        }
    }
    
    write_process ()
    {
        while (1)
        {
            wait (); /* Wait until memory is released */
            lock (); /* Lock memory */
            read_buffer (); /* Crictical section */
            unlock (); /* Release memory */
        }
    }
    So if the read_process has locked the memory, then write_process must wait until the memory is released. Then the write_process locks the memory and the read_process has to wait until the write_process has released the memory.

    For this situation the semaphore could be of type int and have for example value 1 for locked and 0 for released.

  9. #9
    Registered User
    Join Date
    May 2002
    Posts
    41
    Is this basically the same idea as using mutexes for threads?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. basic question about global variables
    By radeberger in forum C++ Programming
    Replies: 0
    Last Post: 04-06-2009, 12:54 AM
  2. Replies: 5
    Last Post: 10-17-2008, 11:28 AM
  3. global variables and thread safety
    By laertius in forum C Programming
    Replies: 11
    Last Post: 07-18-2006, 10:43 AM
  4. can't use global variables or funktion parameters
    By cocobo in forum C Programming
    Replies: 8
    Last Post: 05-14-2005, 08:50 AM
  5. Replies: 2
    Last Post: 10-02-2004, 10:12 AM