Multithreading and locking?

According to the documentation, “Task.h” provides a way to do multithreading on the robot. I wanted to try running my camera processing code on a separate thread and ping back on it periodically to grab the latest set of data it produces.

I’m pretty new to multithreading, but as best as I can tell, I need to lock a variable or something before I read/write to it to make sure things don’t go haywire. However, I don’t know how to lock a variable or otherwise communicate between a thread and the main program.

How would I accomplish this? If possible, could somebody point to some example code that does something similar so I can use it for reference?

Google around for “VxWorks semaphore”, and have a look at the SEM_ID data structure.

Just use global variables. Don’t tell anyone (I know it’s bad), but our team does’t use any lock/semaphore-type structures, and we’ve never had a problem. Then again, the data shared between the threads is only a float and a string.

Zera’s Law: Once you realize that something bad can happen, it will.

One example worth looking at is the PIDController. It spawns a task which updates every 50ms from the PIDInput and writes its results to PIDWrite. That will serve as a good example. But if there’s a lack of clarity as to what you’re really trying to do, here’s “it” in a nutshell. Since you have two tasks running at the same time, one must be careful to not wind up modifying something while it is being read by the other task. The lock basically says that the other task cannot get their lock until you unlock on the other one. One must also be careful to program in a manner where you always give up a lock that you’ve taken - or else the other thread will be forever waiting to gain the lock which you never give up… and similarly, if you take a lock, you have to be careful to make sure you don’t accidentally call a function which tries to take the lock a 2nd time which would result in the same deadlock situation.

bob

I can attest to that. As soon as I took a second look at our code I realized that we’d had static initialization order issues, and sure enough, a few days later it segfaulted…

The AxisCamera code also has some locking that you can look at. We also wrapped it a little in our code: https://github.com/rbmj/612-code/blob/master/vision_thread.cpp

I was looking through your code and do you realize you can use namespaces?

so for example right after your includes you would put something like this…

using namespace cv;
using namespace std;

Now that you have that instead of doing something like

std::cout << cv::Point(10,10) << std::endl;

You can now do this

cout << Point(10,10) << endl;

Just something I thought I would share with everyone.

As long as you only have one writer thread, you won’t run into any problems.

Very true. Arguing this very thing at work at the moment. Any context switch were writing can only occur in one of the context events then you do not need to lock it to protect it from the reader/writer problem.

That depends on the behavior of the scheduler, and what the “writer” thread is writing to…

That depends on the variable. Try to manipulate a linked list without mutual exclusion and you are toast. Using a global double on a 32-bit machine might cause you trouble. If the global variable is simply an integer or a float and there is only one writer you should be ok.

The kernel we are using has all the RT extensions enabled so they could be in trouble.

If you’re not conscientious about read-once in a separate task, you can cause yourself problems again where obj.Value = 57 at the start of a function and obj.Value = 118 by the end, despite you not writing anything to it.

Actually, it isn’t really considered good practice to use namespaces, when you start using multiple libraries with similarly named functions, it can get hectic, and its just better to get into the habit of not using them if possible.