2013-03-13 15 views
6

Używam scoped_lock w moim kodu wielowątkowego się wyłącznie dostęp do niektórych części kodu, ale czasami rzuca wyjątku miejscu pisania naruszenie Dostępu ....boost :: mutex :: scoped_lock został wykorzystany i to czasami zgłasza wyjątek

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 ... 
} 

Wywiodłem kod i dowiedziałem się, że istnieje zmienna active_count w klasie basic_timed_mutex i ilekroć runtime error dzieje, zmienna ta jest niezainicjowany. Runtime error dzieje tutaj:

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

Nie wiem, co mam robić! ponieważ nie mam dostępu do tej zmiennej i nie jestem odpowiedzialny za jej zainicjowanie.

UPDATE

klasa mojej funkcji jest taka:

#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; 
} 

i jest to kod gdzie mogę używać funkcji 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); 
    } 

} 

istnieje klasa inhrerits MyThreadPool

class SsThreadPool : public MyThreadPool<Job, JobOutput> 

i to, gdzie zostały wykorzystane puli wątków:

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

Czy to jest rzeczywisty kod, dla którego otrzymujesz naruszenie zasad dostępu? –

+0

jest "mMutex" zmienną globalną? Czy próbujesz uzyskać do niego dostęp z konstruktora innego obiektu globalnego? –

+1

Tak, otrzymuję wyjątek w tej linii: 'boost :: mutex :: scoped_lock lock (mMutex);' –

Odpowiedz

0

Może przedmiot, który trzyma mutex, zostanie zniszczona, a następnie ktoś próbuje uzyskać dostęp mutex. możliwe w twoim kodzie?

+0

Nie sądzę. żywotność tego obiektu jest tak długa, jak czas życia programu. –

+0

Jesteś w głównym wątku? – rioki

2

Powoduje naruszenie zasad dostępu, ponieważ próbujesz zablokować zniszczoną wersję: mutex. Ponieważ muteks jest członkiem twojej klasy, oznacza to, że twój kod próbuje uzyskać dostęp do funkcji-członka zniszczonej instancji ("zwisający wskaźnik"). Aby debugować ten przypadek, umieść punkt przerwania w ~MyThreadPool i zobacz, kiedy zostanie wywołany.

+0

jak powiedziałeś, umieściłem punkt przerwania w '~ MyThreadPool', ale naruszenie dostępu podnosi się przed wywołaniem destruktora. –

+0

@Samaneh Saadat Ok, rozumiem. Inną opcją (o wiele gorszym) jest uszkodzenie sterty, które "nadpisuje" jakąś część 'mMutex'.W każdym razie coś rujnuje obiekt mutex. BTW, jakiej wersji wzmacniającej używasz? –

+0

Używam doładowania 1.47.0 do natychmiastowej obsługi błędu Zdefiniowałem 'mMutex' w metodzie' GetNextJob', po tym naruszeniu dostępu do modyfikacji podnosi się w pobliżu następnej linii, a teraz ma problem z 'mInputQueue'. –