Revision e6e5f703
Added by David Sorber almost 4 years ago
| software/read_test/src/Utilities/SynchronizedCounter.h | ||
|---|---|---|
|
/********************************************************************
|
||
|
* This software is "commercial computer software" as defined in the *
|
||
|
* Federal Acquisition Regulations and is subject to BlackLynx *
|
||
|
* Inc's standard End User License Agreement. *
|
||
|
* *
|
||
|
* CONFIDENTIAL - All source code is the propriety and confidential *
|
||
|
* information of BlackLynx Inc. *
|
||
|
* *
|
||
|
* Copyright 2018-2020 BlackLynx Inc. *
|
||
|
* Unpublished -- all rights reserved under the copyright laws *
|
||
|
* of the United States. *
|
||
|
********************************************************************/
|
||
|
#ifndef __BLNX_SYNCHRONIZEDCOUNTER_H__
|
||
|
#define __BLNX_SYNCHRONIZEDCOUNTER_H__
|
||
|
|
||
|
#include <chrono>
|
||
|
#include <mutex>
|
||
|
#include <condition_variable>
|
||
|
#include <iostream>
|
||
|
|
||
|
namespace BlackLynx
|
||
|
{
|
||
|
namespace SearchLynx
|
||
|
{
|
||
|
|
||
|
template<typename T>
|
||
|
class SynchronizedCounter
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
static_assert(std::is_integral<T>::value,
|
||
|
"Template parameter must be an integral type");
|
||
|
|
||
|
SynchronizedCounter()
|
||
|
: m_finalized(false),
|
||
|
m_value(0)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
SynchronizedCounter(T initValue)
|
||
|
: m_finalized(false),
|
||
|
m_value(initValue)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
inline void increment()
|
||
|
{
|
||
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||
|
++m_value;
|
||
|
}
|
||
|
|
||
|
inline void decrement()
|
||
|
{
|
||
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||
|
--m_value;
|
||
|
}
|
||
|
|
||
|
void finalize()
|
||
|
{
|
||
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||
|
m_finalized = true;
|
||
|
}
|
||
|
|
||
|
T getValue()
|
||
|
{
|
||
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||
|
return m_value;
|
||
|
}
|
||
|
|
||
|
T getValue(bool& finalized)
|
||
|
{
|
||
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||
|
finalize = m_finalized
|
||
|
return m_value;
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
|
||
|
bool m_finalized;
|
||
|
T m_value;
|
||
|
std::mutex m_mutex;
|
||
|
};
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif
|
||
| software/read_test/src/Utilities/SynchronizedValue.h | ||
|---|---|---|
|
class SynchronizedValue
|
||
|
{
|
||
|
public:
|
||
|
SynchronizedValue()
|
||
|
: m_terminateFlag(false),
|
||
|
m_flag(false)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
SynchronizedValue(T initValue)
|
||
|
: m_terminateFlag(false),
|
||
|
m_flag(false),
|
||
|
m_value(initValue)
|
||
|
|
||
|
SynchronizedValue()
|
||
|
: m_terminateFlag(false),
|
||
|
m_flag(false)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
SynchronizedValue(T initValue)
|
||
|
: m_terminateFlag(false),
|
||
|
m_flag(false),
|
||
|
m_value(initValue)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
virtual ~SynchronizedValue() {}
|
||
|
|
||
|
/**
|
||
|
* Terminate any pending getValue() calls.
|
||
|
*/
|
||
|
void terminate()
|
||
|
{
|
||
|
m_terminateFlag = true;
|
||
|
m_CV.notify_all();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the value and notify any blocked getValue() calls.
|
||
|
*/
|
||
|
void setValue(T value)
|
||
|
{
|
||
|
m_value = value;
|
||
|
{
|
||
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||
|
m_flag = true;
|
||
|
}
|
||
|
|
||
|
virtual ~SynchronizedValue() {}
|
||
|
|
||
|
/**
|
||
|
* Terminate any pending getValue() calls.
|
||
|
*/
|
||
|
void terminate()
|
||
|
{
|
||
|
m_terminateFlag = true;
|
||
|
m_CV.notify_all();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the value and notify any blocked getValue() calls.
|
||
|
*/
|
||
|
void setValue(T value)
|
||
|
m_CV.notify_all();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the value, potentially blocking until it becomes available. Note
|
||
|
* that the "terminated" parameter should always be checked before using
|
||
|
* the returned value as a call to terminate() might cause this function
|
||
|
* to return a default initialized value.
|
||
|
*
|
||
|
* @param terminated - indicates if a blocking wait was terminated
|
||
|
* @param block - (default: true) block while waiting for value to be set
|
||
|
*
|
||
|
* @return the stored value
|
||
|
*/
|
||
|
T getValue(bool& terminated, bool block=true)
|
||
|
{
|
||
|
terminated = false;
|
||
|
|
||
|
// If not blocking; return the current value without waiting if it
|
||
|
// hasn't yet been set
|
||
|
if (! block)
|
||
|
{
|
||
|
m_value = value;
|
||
|
{
|
||
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||
|
m_flag = true;
|
||
|
}
|
||
|
m_CV.notify_all();
|
||
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||
|
return m_value;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the value, potentially blocking until it becomes available. Note
|
||
|
* that the "terminated" parameter should always be checked before using
|
||
|
* the returned value as a call to terminate() might cause this function
|
||
|
* to return a default initialized value.
|
||
|
*
|
||
|
* @param terminated - indicates if a blocking wait was terminated
|
||
|
* @param block - (default: true) block while waiting for value to be set
|
||
|
*
|
||
|
* @return the stored value
|
||
|
*/
|
||
|
T getValue(bool& terminated, bool block=true)
|
||
|
|
||
|
std::unique_lock<std::mutex> muxLock(m_mutex);
|
||
|
while (m_flag == false)
|
||
|
{
|
||
|
terminated = false;
|
||
|
|
||
|
// If not blocking; return the current value without waiting if it
|
||
|
// hasn't yet been set
|
||
|
if (! block)
|
||
|
{
|
||
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||
|
return m_value;
|
||
|
}
|
||
|
|
||
|
std::unique_lock<std::mutex> muxLock(m_mutex);
|
||
|
while (m_flag == false)
|
||
|
m_CV.wait_for(muxLock, std::chrono::milliseconds(1));
|
||
|
|
||
|
// If we've been asked to terminate, break out of the loop and abort
|
||
|
if (m_terminateFlag)
|
||
|
{
|
||
|
m_CV.wait_for(muxLock, std::chrono::milliseconds(1));
|
||
|
|
||
|
// If we've been asked to terminate, break out of the loop and abort
|
||
|
if (m_terminateFlag)
|
||
|
{
|
||
|
terminated = true;
|
||
|
break;
|
||
|
}
|
||
|
terminated = true;
|
||
|
break;
|
||
|
}
|
||
|
muxLock.unlock();
|
||
|
|
||
|
return m_value;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Reset the internal flag to allow the value to be set again. Note this
|
||
|
* function must be used with care!
|
||
|
*/
|
||
|
void reset()
|
||
|
{
|
||
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||
|
m_flag = false;
|
||
|
}
|
||
|
|
||
|
void reset(T newVal)
|
||
|
{
|
||
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||
|
m_flag = false;
|
||
|
m_value = newVal;
|
||
|
}
|
||
|
muxLock.unlock();
|
||
|
|
||
|
return m_value;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Reset the internal flag to allow the value to be set again. Note this
|
||
|
* function must be used with care!
|
||
|
*/
|
||
|
void reset()
|
||
|
{
|
||
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||
|
m_flag = false;
|
||
|
}
|
||
|
|
||
|
void reset(T newVal)
|
||
|
{
|
||
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||
|
m_flag = false;
|
||
|
m_value = newVal;
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
|
||
read_test: Added SynchronizedCounter class.