C ++ std :: timed_mutex具有递归行为

时间:2014-02-28 00:13:06

标签: c++ mutex std timed

我有一个问题。我想为我的程序使用互斥锁。所以会发生这样的事情: 我正在构建一个包含std :: timed_mutex的对象。在创建时,此对象会锁定互斥锁,因为它应该在以后解锁。创建互斥锁的同一个线程现在应该等待该互斥锁,而其他一些线程在后台工作。加入线程是没有选择的。

class A{
    std::timed_mutex mutex;
    A(){
        mutex.lock();
    }

    bool waitForIt(int timeout){
        if(mutex.try_lock_for(std::chrono::milliseconds(timeout))){
            mutex.unlock();
            return true;
        }else{
            return false;
        }
    }
}

当从同一个线程调用waitForIt时程序刚刚通过并立即得到一个错误,完全忽略了超时。(是的,它打算在之后解锁互斥锁。它应该像事件一样mime,以便每个线程等待通过)

所以在documentation中它表示这个互斥锁具有非递归行为。但测试显示,例如我可以从同一个线程多次使用.lock()而不会被阻止。我也可以多次使用try_lock_for,每次都可以!如果我曾经在try_lock_fors之前使用过锁,我总是会弄错。遗憾的是,我需要的东西也会阻塞锁定互斥锁的同一个线程。我不知道该用什么。即时编程linux btw。所以也许有原生的解决方案?

我也没有在std libs.i中找到一个信号量,而不是使用互斥锁。使用我自己的实现是可能的,但我不知道如何制作我自己的信号量。任何想法?

因为人们似乎并不明白它不是那么简单:

class IObservable : public IInterface{
private:
    std::list<std::shared_ptr<IObserver>> observers;
public:
    virtual ~IObservable(){}

    void AddObserver(std::shared_ptr<IObserver> observer);
    void RemoveObserver(std::shared_ptr<IObserver> observer);
    void ClearObservers();
    void TellCompleted(bool wasCanceled = false, std::shared_ptr<void> status = 0);
    TYPEIDHASHFUNC(IObservable)
};

IObservable是线程可以添加观察者的东西。从IObservable派生的东西在其动作结束时调用TellCompleted方法。

class IObserver : public IInterface{
public:
    virtual ~IObserver(){}

    virtual CompleteResult Complete(bool wasCanceled, std::shared_ptr<void> status) = 0;
    virtual bool WaitForCompletion(int timeoutInMs) = 0;
    virtual bool IsCompleted() const = 0;
    virtual bool WasCanceled() const = 0;
    virtual std::shared_ptr<void> GetStatus() const = 0;
    virtual void Reset() = 0;
    TYPEIDHASHFUNC(IObserver)
};

IObserver是可以添加到IObservable的观察者。如果IObservable完成方法,则会在添加到observable

的每个观察者上调用Complete
class BasicObserver : public IObserver{
private:
    bool isCompleted;
    bool wasCanceled;
    CompleteResult completeResult;
    std::shared_ptr<void> status;
    std::timed_mutex mutex;
public:
    BasicObserver(CompleteResult completeResult);
    ~BasicObserver();

    CompleteResult Complete(bool wasCanceled, std::shared_ptr<void> status);
    bool WaitForCompletion(int timeoutInMs);
    bool IsCompleted() const;
    bool WasCanceled() const;
    std::shared_ptr<void> GetStatus() const;
    void Reset();
    TYPEIDHASHFUNC(BasicObserver)
};

这是观察者的一种实现。它保存互斥锁并使用超时实现WaitForCompletion。 WaitForCompletion应该阻止。当调用完成时,应该解锁其互斥锁。当超时运行时WaitForCompletion返回false

BasicObserver::BasicObserver(CompleteResult completeResult):
    isCompleted(false),
    wasCanceled(false),
    completeResult(completeResult)
{
    std::thread createThread([this]{
        this->mutex.lock();
    });
    createThread.join();
}

BasicObserver::~BasicObserver(){
}

CompleteResult BasicObserver::Complete(bool wasCanceled, std::shared_ptr<void> status){
    this->wasCanceled = wasCanceled;
    this->status = status;
    isCompleted = true;
    mutex.unlock();
    return completeResult;
}

bool BasicObserver::WaitForCompletion(int timeoutInMs){
    std::chrono::milliseconds time(timeoutInMs);
    if(mutex.try_lock_for(time)){
        mutex.unlock();
        return true;
    }else{
        return false;
    }
}

bool BasicObserver::IsCompleted() const{
    return isCompleted;
}

bool BasicObserver::WasCanceled() const{
    return wasCanceled;
}

std::shared_ptr<void> BasicObserver::GetStatus() const{
    return status;
}

void BasicObserver::Reset(){
    isCompleted = false;
    wasCanceled = false;
    status = 0;
    std::chrono::milliseconds time(250);
    mutex.try_lock_for(time); //if this fails it might be already resetted
}

// edit:使用信号量解决(semaphore.h中的sem_t)

2 个答案:

答案 0 :(得分:0)

您可以使用condation_variable,特别是wait_untilwait_for

答案 1 :(得分:0)

我会考虑重新设计你的锁定结构。 为什么不用主线程保持锁定,当事件x发生时你解锁它。如果你需要阻止一段时间,我会让线程睡眠。 让所有工作线程阻塞互斥锁试图获取锁定,如果它们需要同时运行,让它们在获取锁定后立即释放锁定。

可能使用第二个互斥锁来模拟事件x。

  

我想从线程1设置锁定,然后启动一个线程2   做某事(在这种情况下等待硬件输入)然后   等待线程1中的互斥锁。然后在线程2解锁互斥锁   按下硬件上的开关。我正在使用某种观察者   图案。所以我有一些可观察的东西,我添加一个观察者(在   这种情况下,A类是观察者)。在某些时候可观察到的   告诉所有添加的观察者,它完成了任务,从而解锁   互斥体。因为我们这里有硬件,可能就是硬件   锁定或传感器不起作用。所以我需要暂停 - fredlllll 3   分钟前

编辑 - 也许这会有效吗?

在线程2获得该锁定的输入块后,保持线程1中的锁定。让线程1在超时持续时间后释放锁定,也许稍微睡一会让线程通过再获取锁定。在获取互斥锁1后,让线程2释放锁定1然后在第二个互斥锁上开始阻塞,使硬件开关解锁互斥锁2导致线程2锁定互斥锁2然后解锁互斥锁2.使硬件交换机再次获取互斥锁2。