2013-03-13 13 views
6

Sto usando scoped_lock nel mio codice multithread per accedere esclusivamente ad una parte del codice, ma a volte getta all'eccezione Accesso violazione posizione di scrittura ....boost :: mutex :: scoped_lock è stato utilizzato ed a volte getta l'eccezione

boost::mutex mMutex;  
boost::condition mInputQueueNotEmpty;  
Job* MyThreadPool<Job, JobOutput>::GetNextJob() 
{  
    boost::mutex::scoped_lock lock(mMutex); 

    while (mInputQueue.empty()) 
     mInputQueueNotEmpty.wait(lock); 

    // Do something ... 
} 

I risalire il codice e ho scoperto che c'è un active_count variabile in classe basic_timed_mutex e quando l'errore di runtime accade, questa variabile è inizializzata. errore di runtime accade intorno a qui:

bool try_lock() 
{ 
    return !win32::interlocked_bit_test_and_set(&active_count,lock_flag_bit); 
} 

non so cosa devo fare! perché non ho accesso a questa variabile e non sono responsabile per inizializzarlo.

UPDATE

la classe di mia funzione è questo:

#pragma once 

#include <vector.h> 
#include <boost/thread.hpp> 
#include "MyThread.h" 
#include <queue> 
#include <boost/thread/condition.hpp> 

template <class Job, class JobOutput> 
class MyThreadPool 
{ 
public: 
    MyThreadPool(int processJobWhenArrived);   
    virtual ~MyThreadPool(void); 
     void Initialize(int ThreadsCount); 
     void AddJob(Job* job); 
     void StartProcess(); 
     Job* GetNextJob(); 
    virtual void FinishJob(Job* job, JobOutput* jobOutput); 
     void WaitUntilAllJobsProcessed(); 

public: 
    vector<MyThread<Job, JobOutput>*> mThreads; 

    queue<Job*> mInputQueue; 
    queue<pair<Job*,JobOutput*>> mOutputQueue; 

    boost::mutex  mMutexAdd; 
    boost::mutex  mMutex; 
    boost::condition mInputQueueNotEmpty; 
    boost::mutex  mJobOutputMutex; 
    boost::mutex  mJobsMutex; 
    boost::condition mProcessJobs; 
    bool   mStartProcessJobs; 
    int   mJobsInputCount; 
    int   mJobsOutputCount; 
    int   mPrevJobsOutputCount; 
    bool   mProcessJobWhenArrived; 
}; 

template <class Job, class JobOutput> 
void MyThreadPool<Job, JobOutput>::Initialize(int threadsCount) 
{ 
    mStartProcessJobs = false; 
    for (int t = 0; t < threadsCount; t++) 
     mThreads.push_back(new MyThread<Job, JobOutput>(this)); 
} 

template <class Job, class JobOutput> 
void MyThreadPool<Job, JobOutput>::AddJob(Job* job) 
{ 
    boost::mutex::scoped_lock lock(mMutexAdd); 
    mInputQueue.push(job); 
    mJobsInputCount++; 

    if (mProcessJobWhenArrived) 
     mInputQueueNotEmpty.notify_all(); 
} 

template <class Job, class JobOutput> 
Job* MyThreadPool<Job, JobOutput>::GetNextJob() 
{ 
    boost::mutex::scoped_lock lock(mMutex); 

    if (mInputQueue.empty() && mStartProcessJobs && mJobsInputCount == mJobsOutputCount) 
     mProcessJobs.notify_one(); 

    while (mInputQueue.empty()) 
     mInputQueueNotEmpty.wait(lock); 

    Job* job = mInputQueue.front(); 
    mInputQueue.pop(); 

    return job; 
} 

e questo è il codice in cui io uso la funzione GetNextJob:

#pragma once 

#include <MyMemory.h> 
#include <boost/thread.hpp> 

template <class Job, class JobOutput> 
class MyThreadPool; 

template <class Job, class JobOutput> 
class MyThread 
{   
public: 
    static void StaticRun(MyThread* p); 
    void Run(); 

public: 
    boost::thread mThread;    
    MyThreadPool<Job, JobOutput>* mThreadPool;    
}; 

#include "MyThreadPool.h" 
template <class Job, class JobOutput> 
MyThread<Job, JobOutput>::MyThread(MyThreadPool<Job, JobOutput>* threadPool) 
{ 
    mThread = boost::thread(StaticRun, this); 
    mThreadPool = threadPool; 
} 

template <class Job, class JobOutput> 
void MyThread<Job, JobOutput>::StaticRun(MyThread* p) 
{ 
    p->Run(); 
} 

template <class Job, class JobOutput> 
void MyThread<Job, JobOutput>::Run() 
{ 
    JobOutput *jobOutput; 
    while (true) 
    { 
     Job* job = mThreadPool->GetNextJob(); 
     jobOutput = Process (job); 
     mThreadPool->FinishJob(job, jobOutput); 
    } 

} 

v'è una classe che inhrerits MyThreadPool

class SsThreadPool : public MyThreadPool<Job, JobOutput> 

e questo è dove ThreadPool è stato utilizzato:

class BPS 
{ 
    //... 
    SsThreadPool   mJobsThreadPool; 
    //... 
} 
void BPS::Initialize() 
{ 
    mJobsThreadPool.Initialize(mConcurrentThreadsCount); 
} 

void BPS::f() 
{ 
    //... 
    for (int i = 0; i < jobsCount; i++) 
    { 
     //... 
     mJobsThreadPool.AddJob(job); 
     //... 

    } 
    mJobsThreadPool.StartProcess(); 
    mJobsThreadPool.WaitUntilAllJobsProcessed(); 
    //... 
} 
+1

È questo il codice effettivo per il quale si ottiene una violazione di accesso? –

+0

è 'mMutex' una variabile globale? Stai cercando di accedervi dal costruttore dell'altro oggetto globale? –

+1

Sì, ottengo eccezione a questa riga: 'boost :: mutex :: scoped_lock lock (mMutex);' –

risposta

0

Forse l'oggetto, che sta tenendo il mutex, viene distrutta e poi qualcuno sta cercando di accedere al mutex. possibile nel tuo codice?

+0

Io non la penso così. la vita di quell'oggetto è lunga quanto il tempo di vita del programma. –

+0

Sei in posta principale? – rioki

2

Solleva violazione di accesso, perché si tenta di bloccare un mutex distrutto. Poiché il mutex è un membro della classe, significa che il tuo codice tenta di accedere a una funzione membro di un'istanza distrutta ("puntatore che penzola"). Per eseguire il debug di questo caso, inserire un punto di interruzione in ~MyThreadPool e vedere quando viene chiamato.

+0

come hai detto, ho messo breakpoint in '~ MyThreadPool' ma la violazione di accesso si alza prima di chiamare il distruttore. –

+0

@Samaneh Saadat Ok, capisco. Un'altra opzione (molto peggio) è un danneggiamento dell'heap che "sovrascrive" parte di 'mMutex'.Ad ogni modo, qualcosa rovina l'oggetto mutex. A proposito, quale versione di boost stai usando? –

+0

Uso boost 1.47.0 per gestire immediatamente l'errore che ho definito 'mMutex' nel metodo' GetNextJob', dopo che questa violazione di accesso alle modifiche si è verificata vicino alla riga successiva e ora ha problemi con 'mInputQueue'. –

Problemi correlati