8

I have an application written in C++ that was originally single threaded, but, due to the increasing complexity of this project, I'll need to expand it to at least two or three threads.

There are only a total of four variables that will be used between more than one thread threads, making it useless to make everything thread-safe. The obvious solution is to just create a mutex for each variable and move on with my life.

However, looking back, this seems like a horrible idea! I'm afraid that another programmer may forget that the majority of the methods and variables are not thread-safe and use a variable in another thread.

Since I'm the main programmer for this project, it doesn't seem like this would be an issue, but I honestly feel like this is bad programming and it feels really messy.

What are some ways to keep the variables separate to make it easier to tell which variable is for which thread? I've been thinking about isolating the code for the thread so it cannot access the other global variables (giving a compile error instead of silently creating a bug). I could also create a namespace or class for each thread. Is there a best practice for this?

10
  • 5
    The only way I know to prevent others from making thread-safe code unsafe is to teach the other programmers the gory details of multi threading, and to document thoroughly the piece of code in stake.
    – Doc Brown
    Nov 22, 2014 at 8:56
  • 1
    I'm almost positive this could be done in a better fashion, but without knowing how you're using these four variables, it is difficult to provide an alternative solution. This is one of those things that is rather dependent on context I'm afraid.
    – Neil
    Nov 22, 2014 at 9:12
  • Do you need to share these four variables among the threads? Can you perhaps have local variables and use some kind of message passing to exchange information between the threads?
    – Giorgio
    Nov 22, 2014 at 9:37
  • @Neil what are you getting at? I'm just curious if there are any stylistic approaches to keeping everything separate (i.e. namespaces, etc.). Nov 22, 2014 at 14:54
  • 1
    @DocBrown most documentation is an excuse for a poorly designed code/UI/etc. :) I'm trying to see if there's a standard practice to move everything to another file (or whatever practice) or if it just depends on how you want to organize it. Nov 22, 2014 at 14:56

4 Answers 4

3

There are two elements to this problem: #1, the technical change to the existing code base to support multi-threading, and #2 changing the culture of the company in order to be aware of thread safety in the code.

The first is relatively simple. First, document the functions in the class that are thread safe and are not thread safe. I agree with Jeffery Thomas that you should treat it as a major new feature. Often, I'll write an entirely new class with some (relation to the original class to keep it DRY) that is thread safe. While there is no explicit "thread safe" tag in c++, I find making the class const correct can do a lot to help out. You should also clearly document what is thread safe or not (follow a convention, be CONSISTENT, and make the assumed state not thread safe).

The larger problem is changing the culture of the company to make sure everyone is aware of thread safety. I find this is where things like a style guide and code reviews can be very helpful. A style guide can inform people exactly how to mark things as thread safe. We do a lot of C programming, so I'm partial to decorating names, but you should choose a style that works for you. Some companies lean towards making everything thread safe by default, but I find that tends to add a lot of unnecessary code complexity, and can add non-insignificant overhead on occasion.

Code reviews, when done correctly, are a way to educate everyone on the style and to pass around information about programming in general.

5

Wrap all access to the variables in a thread safe function so that access of the variables from anywhere in the code flows through a single method, and make the variable private.

This way any access of the variable from outside the class will be thread safe.

The next step is to move the variables into their own class, only accessible via the safe methods. (Not one class per variable, just all the variable in a separate class.)

There's always a way for another programmer to mess up the code, but in my experience if you write the code so that the easiest thing for them to do is the safe way, that will be what they do.

3
  • Please read the original question: "There are only a total of four variables that will be used between more than one thread threads, making it useless to make everything thread-safe." I guess this can work sometimes but it's not a reasonable option for this situation. Nov 22, 2014 at 19:12
  • 2
    It makes sense, this is what I'd do also (if you like to prevent others to make a mess...)
    – Nikko
    Nov 22, 2014 at 20:36
  • @AnnonomusPenguin Even if you don't make the method access the variables thread-safely, pulling them back and forcing access via the method is one way to coordinate via code a single route of access for each of the variables. Then make the one or two that need thread safety thread safe, and leave the rest as simple wrapper functions. Expand as needed.
    – SumGuy
    Nov 23, 2014 at 1:17
3

Adding multi-threading is a major new feature of a class. I think you should treat it like a major new feature, and don't try to sneak it in.

Rethink and refactor the class and it relationships. I would look into creating a new class to represent each threaded task and/or slice of functionality.

If needed you can preserve the old class interface as a proxy to the new cluster of classes.

1

After some work, I actually figured out a simple solution for this issue (as simple as they get)... namespaces.

I have each logical thread organized into a specific namespace. For example, this is what my namespace organization looks like (split into different files, obviously). If I had a ton more stuff shared, I would've done a class approach like SumGuy's answer for shared variables, but it'd be overkill to do this for all of the code since, besides the four variables, the threads are independent.

namespace MainThread {

}

namespace ThreadOne {

}

It isn't a pretty solution, but at least another person will have to explicitly type the word "thread" to use a variable/function in another thread, so it's their fault if they ignore such an obvious thing.

Also, if editing code in one namespace, it takes no extra effort to type the name of the current thread since that's automatically assumed!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.