I try to handle a deadlock in my code but I can't fugure out how to prevent it. I have a thread which accesses data and an update method which update the data. The code looks like this:
thread {
forever {
if (Running) {
LOCK
access data
UNLOCK
}
Running = false;
}
}
update {
Running = false;
LOCK
access data
UNLOCK
Running = true;
}
I tried to fix it with a second access variable but it doesn't change anything.
thread {
forever {
if (!Updating) {
if (Running) {
LOCK
access data
UNLOCK
}
}
Running = false;
}
}
update {
Updating = true;
Running = false;
LOCK
access data
UNLOCK
Updating = false;
Running = true;
}
Thanks for your help.
UPDATE
This is a better description of the problem:
thread {
forever {
if (Running) {
LOCK
if (!Running) leave
access data
UNLOCK
}
Running = false;
}
}
update {
Running = false;
LOCK
access data
UNLOCK
Running = true;
}
My update function is a bit more complex, so that I can't see a way to use one of the standard algorithm for this.
UPDATE 2
Here is the simplified c++ source code. maybe it's better to read as the pseudocode:
void run() {
forever {
if (mRunning) {
QMutexLocker locker(&mMutex);
for (int i; i < 10; i++) {
qDebug("run %d", i);
sleep(1);
if (!mRunning) break;
}
mRunning = false;
}
}
}
void update() {
mRunning = false;
QMutexLocker locker(&mMutex);
qDebug("update");
mRunning = true;
}
UPDATE 3
Ok. The problem is a bit more complex. I forgot that my accesss data part in the thread starts also some child threads to fill the data structure
datathread {
access data
}
thread {
forever {
if (Running) {
LOCK
if (!Running) leave
forloop
start datathread to fill data to accessdata list
UNLOCK
}
Running = false;
}
}
update {
Running = false;
LOCK
access data
UNLOCK
Running = true;
}
Standard way for read method being restarted when during write is to use seqlock. With single writer and reader seqlock is just atomic integer variable, which is incremented every time when writer is started and when it is ended. Such a way reader method can periodically check whether variable is unchanged since read is started:
atomic<int> seq = 0;
updater() // *writer*
{
seq = seq + 1;
<update data>
seq = seq + 1;
}
thread() // *reader*
{
retry: // Start point of unmodified data processing.
{
int seq_old = seq;
if(seq_old & 1)
{
// odd value of the counter means that updater is in progress
goto retry;
}
for(int i = 0; i < 10; i++)
{
<process data[i]>
if(seq_old != seq)
{
// updater has been started. Restart processing.
goto retry;
}
}
// Data processing is done.
}
}
If several updater() can be executed concurrently, whole update code should be executed with mutex taken:
updater() // *writer*
{
QMutexLocker locker(&updater_Mutex);
seq = seq + 1;
<update data>
seq = seq + 1;
}
If even single element of data cannot be accessed concurrently with updating, both <update data> and <process data[i]> should be executed with mutex taken.
Related
In my Android app, I use C++ to do some work. In my C++ code, I use a thread to do some tasks. Using this example and this example, here is how I proceed (I simplified the actual code to keep it easy to read):
std::thread* threadLocal;
std::queue<ThreadMessage*> queueLocale;
std::mutex mutexLocal;
std::condition_variable cvLocal;
struct ThreadMessage
{
ThreadMessage(int i)
{
id = i;
}
int id;
};
void MyWorkerThread::createThread()
{
if (!threadLocal)
{
threadLocal = new std::thread(&MyWorkerThread::process, this);
}
}
void MyWorkerThread::sendTask1()
{
if (threadLocal)
{
// message:
ThreadMessage* threadMessage = new ThreadMessage(MSG_TASK_1);
// send the message:
std::unique_lock<std::mutex> lock(mutexLocal);
queueLocale.push(std::move(threadMessage));
cvLocal.notify_one();
}
}
void MyWorkerThread::sendTask2()
{
if (threadLocal)
{
// message:
ThreadMessage* threadMessage = new ThreadMessage(MSG_TASK_2);
// send the message:
std::unique_lock<std::mutex> lock(mutexLocal);
queueLocale.push(std::move(threadMessage));
cvLocal.notify_one();
}
}
void MyWorkerThread::process()
{
while (1)
{
// init :
ThreadMessage* threadMessage = 0;
// waiting for messages :
{
std::unique_lock<std::mutex> lock(mutexLocal);
while (queueLocale.empty())
{
cvLocal.wait(lock);
}
threadMessage = std::move(queueLocale.front());
queueLocale.pop();
}
// tasks :
switch (threadMessage->id)
{
case MSG_TASK_1:
{
doSomeWork1();
delete threadMessage;
break;
}
case MSG_TASK_2:
{
doSomeWork2();
delete threadMessage;
break;
}
default:
{
delete threadMessage;
break;
}
}
}
}
It works well in most cases, but sometimes, my app crashes when a delete threadMessage is called, and I don't understand why (since I don't see how it can be called twice on a same object).
Here are the reasons why I need to send messages to a thread, instead of just creating new threads each time I want to run doSomeWork1() or doSomeWork2():
The doSomeWork1() and doSomeWork2() functions have to be executed in the same thread
One of those functions is very frequently called (approx. 200 times / sec), so I don't want to create a thread each time
So my question is: what is the proper way to send a message to a thread, and manage it inside the thread, to avoid error on the delete?
Thanks for your help.
I'm trying to implement a threadsafe locking mechanism for an array with the following intended use case:
Request the indexes you want to lock and try to acquire them. If you fail to acquire ANY index, bail out, and try again (essentially spin).
Once the necessary locks have been acquired perform processing on these indexes.
Release the acquired locks!
I'm using the below code to test the lock - it just increments a test count, with the same indexes being specified for each iteration (so it forces access to be sequential). The only problem is it doesn't work, and I'm kind of stumped...
I have a feeling I'm missing some sort of key race condition, but I can't identity it yet :(
#pragma omp parallel for
for (int i = 0; i < activeItems; i++)
{
std::vector<int> lockedBucketIndexes = {0, 1, 2, 3};
//try and get a lock on the buckets we want, otherwise keep trying
while (!spatialHash->TryAcquireBucketLocks(lockedBucketIndexes))
{
//TODO - do some fancy backoff here
}
testCount++;
spatialHash->DropBucketLocks(lockedBucketIndexes);
}
The class/methods that do the locking:
std::vector<int> _bucketLocks;
SpinLock _bucketLockLock;
bool SpatialHash::TryAcquireBucketLocks(std::vector<int> bucketIndexes)
{
bool success = true;
//try and get a lock to set our bucket locks... lockception
_bucketLockLock.lock();
//quickly check that the buckets we want are free
for each (int bucketIndex in bucketIndexes)
{
if (_bucketLocks[bucketIndex] > 0)
{
success = false;
break;
}
}
//if all the buckets are free, set them to occupied
if (success)
{
for each (int bucketIndex in bucketIndexes)
{
_bucketLocks[bucketIndex] = 1;
}
}
//let go of the lock
_bucketLockLock.unlock();
return success;
}
void DropBucketLocks(std::vector<int> bucketIndexes)
{
//I have no idea why these locks are required
//It seems to almost work with them though...
_bucketLockLock.lock();
for each (int bucketIndex in bucketIndexes)
{
_bucketLocks[bucketIndex] = 0;
}
_bucketLockLock.unlock();
return true;
}
The spinlock class:
class SpinLock {
std::atomic_flag locked = ATOMIC_FLAG_INIT;
public:
void lock() {
while (locked.test_and_set(std::memory_order_acquire)) { ; }
}
void unlock() {
locked.clear(std::memory_order_release);
}
};
Describtion of the problem:
we need to call a function in extern process as fast as possible. Boost interprocess shared memory is used for communication. The extern process is either mpi master or a single executable. The calculation time of the function lies between 1ms and 1s. The function should be called up to 10^8-10^9 times.
I've tried a lot of possibilities, but I still have some problems with each of them. Here I introduce two of best working implementations
Version 1 ( using intreprocess conditions )
Main-process
bool calculate(double& result, std::vector<double> c){
// data_ptr is a structure in shared memoty
data_ptr_->validCalculation = false;
bool timeout = false;
// write data (cVec_ is a vector in shared memory )
cVec_->clear();
for (int i = 0; i < c.size(); ++i)
{
cVec_->push_back(c[i]);
}
// cond_input_data is boost interprocess condition
data_ptr_->cond_input_data.notify_one();
boost::system_time const waittime = boost::get_system_time() + boost::posix_time::seconds(maxWaitTime_in_sec);
// lock slave process
scoped_lock<interprocess_mutex> lock_output(data_ptr_->mutex_output);
// wait till data calculated
timeout = !(data_ptr_->cond_output_data.timed_wait(lock_output, waittime)); // true if timeout, false if no timeout
if (!timeout)
{
// get result
result = *result_;
return data_ptr_->validCalculation;
}
else
{
return false;
}
};
Extern process runs a while-loop ( till abort condition is fullfilled)
do {
scoped_lock<interprocess_mutex> lock_input(data_ptr_->mutex_input);
boost::system_time const waittime = boost::get_system_time() + boost::posix_time::seconds(maxWaitTime_in_sec);
timeout = !(data_ptr_->cond_input_data.timed_wait(lock_input, waittime)); // true if timeout, false if no timeout
if (!timeout)
{
if (!*abort_flag_) {
c.clear();
for (int i = 0; i < (*cVec_).size(); ++i) //Insert data in the vector
{
c.push_back(cVec_->at(i));
}
// calculate value
if (call_of_function_here(result, c)) { // valid calculation ?
*result_ = result;
data_ptr_->validCalculation = true;
}
}
}
//Notify the other process that the data is avalible or we dont get the input data
data_ptr_->cond_output_data.notify_one();
} while (!*abort_flag_); // while abort flag is not set, check if some values should be calculated
This is best working version, but sometimes it holds up, if the calculation time is short (~1ms). I assume, it happens, if main-process reaches
data_ptr_->cond_input_data.notify_one();
earlier, than extern process is waiting on
timeout = !(data_ptr_->cond_input_data.timed_wait(lock_input, waittime));
waiting condition. So we have probably some kind of synchronisation problem.
Second condition does not help ( i.e. wait only if input data not set, similar to the anonymous condition example with message_in flag). Since, it is still possible, that one process notify the other one, before the second one is waiting for notification.
Version 2 ( using boolean flag and while loop with some delay )
Main-process
bool calculate(double& result, std::vector<double> c){
data_ptr_->validCalculation = false;
bool timeout = false;
// write data
cVec_->clear();
for (int i = 0; i < c.size(); ++i) //Insert data in the vector
{
cVec_->push_back(c[i]);
}
// this is the flag in shared memory used for communication
*calc_flag_ = true;
clock_t test_begin = clock();
clock_t calc_time_begin = clock();
do
{
calc_time_begin = clock();
boost::this_thread::sleep(boost::posix_time::milliseconds(while_loop_delay_m_s));
// wait till data calculated
timeout = (double(calc_time_begin - test_begin) / CLOCKS_PER_SEC > maxWaitTime_in_sec);
} while (*(calc_flag_) && !timeout);
if (!timeout)
{
// get result
result = *result_;
return data_ptr_->validCalculation;
}
else
{
return false;
}
};
and the extern process
do {
// we wait till input data is set
wait_begin = clock();
do
{
wait_end = clock();
timeout = (double(wait_end - wait_begin) / CLOCKS_PER_SEC > maxWaitTime_in_sec);
boost::this_thread::sleep(boost::posix_time::milliseconds(while_loop_delay_m_s));
} while (!(*calc_flag_) && !(*abort_flag_) && !timeout);
if (!timeout)
{
if (!*abort_flag_) {
c.clear();
for (int i = 0; i < (*cVec_).size(); ++i) //Insert data in the vector
{
c.push_back(cVec_->at(i));
}
// calculate value
if (call_of_local_function(result, c)) { // valid calculation ?
*result_ = result;
data_ptr_->validCalculation = true;
}
}
}
//Notify the other process that the data is avalible or we dont get the input data
*calc_flag_ = false;
} while (!*abort_flag_); // while abort flag is not set, check if some values should be calculated
The problem in this version is the delay-time. Since we have calculation times close to 1ms, we have to set the delay at least to this value. For smaller delays the cpu-load is high, for higher delays we lose a lot of performance due to not necessary waiting time
Do you have an idea how to improve one of this versions? or may be there is a better solution?
thx.
I can't find a good solution on how to implement a good mutual exclusion on a common resource between different threads.
I've got many methods (from a class) that do a lot of access to a database, this is one of them
string id = QUERYPHYSICAL + toString(ID);
wait();
mysql_query(connection, id.c_str());
MYSQL_RES *result = mysql_use_result(connection);
while (MYSQL_ROW row = mysql_fetch_row(result)){
Physical[ID - 1].ID = atoi(row[0]);
Physical[ID - 1].NAME = row[1];
Physical[ID - 1].PEOPLE = atoi(row[2]);
Physical[ID - 1].PIRSTATUS = atoi(row[3]);
Physical[ID - 1].LIGHTSTATUS = atoi(row[4]);
}
mysql_free_result(result);
signal();
The methods wait and signal do these things:
void Database::wait(void) {
while(!this->semaphore);
this->semaphore = false;
}
void Database::signal(void) {
this->semaphore = true;
}
But in this case my CPU goes to more than 190% of usage (reading from /proc/loadavg). What should I do to reduce CPU overload and let the system be more efficient? I'm on a 800MHz RaspberryPi
You can use pthread_mutex_t init at the constructor, lock for wait, unlock for signal, destroy at the destructor.
like this:
class Mutex{
pthread_mutex_t m;
public:
Mutex(){
pthread_mutex_init(&m,NULL);
}
~Mutex(){
pthread_mutex_destroy(&m);
}
void wait() {
pthread_mutex_lock(&m);
}
void signal() {
pthread_mutex_unlock(&m);
}
} ;
You also should check the return value of the pthread_mutex functions: 0 for success, non zero means error.
If I desire to run a piece of code in a function, only from the second invocation of the function onwards,
Questions:
Is there something wrong to do that?
How can I possibly achieve this ? Is using a static variable to do this a good idea ?
There's two answers to this question, depending on whether you have to deal with multi-threaded serialization or not.
No threading:
void doSomething() {
static bool firstTime = true;
if (firstTime) {
// do code specific to first pass
firstTime = false;
} else {
// do code specific to 2nd+ pass
}
// do any code that is common
}
With threading:
I'll write the generic boilerplate, but this code is system specific (requiring some variant of an atomic compareAndSet).
void doSomethingThreadSafe() {
static volatile atomic<int> passState = 0;
do {
if ( passState == 2 ) {
//perform pass 2+ code
break;
} else
if ( passState.compareAndSet(0,1) ) { // if passState==0 set passState=1 return true else return false
//perform pass 1 initialization code
passState = 2;
break;
} else {
//loser in setup collision, delay (wait for init code to finish) then retry
sleep(1);
}
} while(1);
//perform code common to all passes
}
Multi-threading will be a problem. To prevent this, if required, you'll probably need something like a mutex.
Like this:
void someFunction()
{
static bool firstRun = true;
if (!firstRun)
{
// code to execute from the second time onwards
}
else
{
firstRun = false;
}
// other code
}
Add a global counter.
eg:-
static int counter = 0;
public void testFunc(){
if(counter==1){
........
<Execute the functionality>
........
}
counter++;
}