私は問題があります。プログラムでミューテックスを使用したい。何が起こるかというと、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 を呼び出すと、プログラムは通過し、タイムアウトを完全に無視して即座に false を取得します (はい、後でミューテックスのロックを解除することを目的としています。待機中のすべてのスレッドが通過するように、イベントのようなものを模倣する必要があります)。
そのため、ドキュメントでは、このミューテックスには非再帰的な動作があると書かれています。しかし、テストにより、たとえば、ブロックされることなく同じスレッドから .lock() を複数回使用できることが明らかになりました。また、try_lock_for を複数回使用して、毎回 true にすることもできます!!! try_lock_fors の前に一度ロックを使用すると、常に false になります。悲しいことに、ミューテックスをロックした同じスレッドもブロックするものが必要です。そして、私は何を使うべきかわかりません。ところで、Linuxでプログラミングしています。ネイティブソリューションがあるかもしれませんか?
また、std libs にセマフォが見つかりませんでした。ミューテックスの代わりにそれを使用できます。独自の実装を使用することは可能ですが、独自のセマフォを作成する方法がわかりません。何か案は?
人々はそれほど単純ではないことを理解していないようです:
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)
};
これは、オブザーバーの 1 つの実装です。ミューテックスを保持し、タイムアウトで WaitForCompletion を実装します。WaitForCompletion はブロックする必要があります。complete が呼び出されると、そのミューテックスのロックが解除されます。タイムアウトが実行されると、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
}
//編集: 代わりにセマフォを使用して解決 (semaphore.h の sem_t)