Thread: Multithreading (flag stopping a thread, ring buffer) volatile

  1. #1
    Registered User
    Join Date
    Apr 2009
    Posts
    11

    Multithreading (flag stopping a thread, ring buffer) volatile

    Hello. I was reading a lot about the volatile keyword lately in the net and the oppinions are very contradicting.
    I am using pthreads. I know that I am supposed to use mutexes to avoid problems with the shared variables, but sometimes it's just redicolous to use a mutex.
    First of all I don't know how one's supposed to stop a running thread. I've researched ptherad_cancel, but it doesn't work for me, because when I stop the tread I must be able to cleanup and do some stuff. I currently have a shared flag "stop" that acts to tell a thread to stop. There's a loop in the tread that executes while !stop. So this flag is checked every iteration. It seems to me that It would be very funny to protect a single flag that must be only read and is almost always going to be false (false is 0, it's defined in the standart library <stdbool.h>). It works fine, but after reading a lot of things about multithreading programming I descovered that's not very correct, because the flag may be cached and never be read. So I discovered the volatile word that seemed to be a correct way to do it, but then I came to all sorts of articles in the net against the use of volatile in multithreading. For this case it seems that volatile will be correct for me, because articles show problems with volatile that don't concern me in this situation:
    1. processor can rearange instructions - I don't care about that, the only thing I care is this variable to be read correctly some time after setting it to true
    2. the volatile doesn't mean atomic - well ... for a flag it's obvious that it's not a problem
    So I think as much as volatile is usless in multithreading programming I think in this case it should work better then accuiring and releasing a mutex every iteration.
    If there's a standart way to stop a thread different from using a shared flag, please tell me

    The second thing is a ring buffer. There is one thread that writes in the buffer and many threads that read the buffer. The write thread keeps a pointer that I use by the other threads as the marker where the reading should end. When the writing thread writes a data it moves the pointer. The reading threads just follow that pointer reading the bytes on the way. A situation where the writing passes the reading won't happen in the normal circumstances and if it happens I expect that the reading thread that's been overtaken will miss one buffer length of data (which is acceptable in an abnormal situation when the reader doesn't read fast enough). So I thought about protecting the buffer and the write pointer with a mutex, but I don't want to hurt the performance, because the reading threads can be many and accuiring a mutex every time before read is a thing that I want to avoid. Here I want to say again that in my machine everything works without volatile or mutexes but I'm afraid that on some unknown machine with multiple processors there may be some problems. So will there be problems for me to just declare the buffer and the write pointer as volatile if I make the following assumations:
    1) pointer assignment is an atomic operation: I think that I won't come accross a machine in which the pointer assignment won't be atomic.
    2) reading won't come close to beeing passed by the writing in normal circumstances and in case that happense there will at most be reading of currupt buffer data once and missing one length of the buffer (not program crash or something like that)
    The thing I also want is to be sure that the write pointer will be moved AFTER the data is written in the buffer and that's the thing that I see nothing can help except mutexes. I want to avoid accuiring and releasing mutexex at every read at all cost.
    I hope someone will be able to help the buffer situation. The thread stopping is mostly curiosity about volatile and common ways to stop a thread.
    Thanks.

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    All volatile does is tell the compiler "you can't trust this variable to not change". So it's fine for flags and such, but if you have more than one place where the variable is being changed, then you need some form of locking to prevent it from being modified by something else.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    Registered User
    Join Date
    May 2009
    Posts
    1

    Multithreading (flag stopping a thread, ring buffer) volatile

    Hi ShwangShwing
    I am amazed with your post,It is my exact query which i am suffering for from last 5 days.
    so if you have recognized the problem which u have posted , please guide me too.
    Thanks in advance

    Regards
    jaishree

  4. #4
    Registered User
    Join Date
    May 2007
    Posts
    147
    A "stop" flag is fairly common, yes.

    Volatile is applicable to threaded development. Any indication otherwise is likely a microscopic detail that's unimportant, perhaps one that applies to code which may be used on non-threaded and threaded applications, etc.

    A stop flag is not all that important to protect as you've analyzed. The only consequence could be that two or more 'calling' threads might set the flag to "stop" at the same time, which isn't an error.


    As to the ring buffer, consider the example source for shared_ptr in C++ (sorry, I know this is a C forum, but the code I'm citing is just a reference to something known that does this). The management of it's reference count is very similar to the management of the ring buffer's pointer, with the exception that in a ring buffer you usually have a 'head' and 'tail'. The tail is usually manipulated by code that adds to the buffer, and the head is exclusively managed by the ring buffer's consumer. If you can insist on that (and it's quite likely), there is no two part collision of something trying to manage both the head and the tail, reducing the 'protection' issue to either of these two as independent units, and so the solution found in shared_ptr is applicable.

    That solution is to use the atomic operations. It is not universally true that all multiple CPU machines are guaranteed to always perform atomic integer or pointer operations - there is nothing in the C or C++ standard that guarantees this (it's mute on threads), so it is possible that an increment followed by a compare ( a two step operation ) will happen without protection. The atomic functions used by shared_ptr are part of a library of functions that resort to CPU supported features (on CPU's that do support this - ARM, for example, does not on all it's processors). Look at the source of shared_ptr for where they manipulate the reference counter and you'll see what I'm talking about.

    It is, basically, an isolated and fairly standardized means of performing a "protected" increment/decrement followed by compare that doesn't require a mutex or critical section.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Simple thread object model (my first post)
    By Codeplug in forum Windows Programming
    Replies: 4
    Last Post: 12-12-2004, 11:34 PM
  2. How to make a thread sleep or std::recv timeout?
    By BrianK in forum Linux Programming
    Replies: 3
    Last Post: 02-26-2003, 10:27 PM
  3. Multithreading
    By Cela in forum Windows Programming
    Replies: 13
    Last Post: 01-15-2003, 03:02 PM
  4. function pointer & Thread Parameter :: Multithreading
    By kuphryn in forum Windows Programming
    Replies: 3
    Last Post: 09-11-2002, 08:42 AM
  5. Multi-Thread Programming
    By drdroid in forum C++ Programming
    Replies: 6
    Last Post: 04-04-2002, 02:53 PM

Tags for this Thread