MotorControlModuleSDFM_TMS3.../Projects/EFC_Application/UMLibrary/common/ResourceKeeper.hpp

304 lines
6.2 KiB
C++
Raw Normal View History

/*
* ResourceKeeper.hpp
*
* Created on: 29 <EFBFBD><EFBFBD><EFBFBD>. 2018 <EFBFBD>.
* Author: titov
*/
#ifndef SOURCE_COMMON_RESOURCEKEEPER_HPP_
#define SOURCE_COMMON_RESOURCEKEEPER_HPP_
#include <atomic>
#include <cstddef>
//!<21><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
/*!<21><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
*/
template<typename T>
class ResourceKeeper {
protected:
T & resource; //!<<3C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
std::atomic_flag & usable; //!<<3C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
public:
ResourceKeeper( T & resource, std::atomic_flag & flag );
virtual T * grab(); //!<<3C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
const T & show(); //!<<3C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
virtual void release( T * & ) noexcept; //!<<3C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
bool is_owned( T * p ) const noexcept;
virtual ~ResourceKeeper() = default;
};
template<typename T>
inline ResourceKeeper<T>::ResourceKeeper( T & r, std::atomic_flag & flag ) : resource(r), usable(flag) {
usable.clear();
}
template<typename T>
inline T * ResourceKeeper<T>::grab() {
T * result = nullptr;
//todo: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> cpu.
if( !usable.test_and_set() )
result = &resource;
return result;
}
template<typename T>
inline const T & ResourceKeeper<T>::show() {
return resource;
}
template<typename T>
inline void ResourceKeeper<T>::release( T * & arg ) noexcept {
if( arg == &resource ) {
arg = nullptr;
usable.clear();
}
}
template<typename T>
class Local {
private:
T * resource; //!<<3C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
ResourceKeeper<T> * keeper;
Local( const Local &) = delete;
Local & operator=( const Local & ) = delete;
public:
Local( T * res, ResourceKeeper<T> & keep );
Local( ResourceKeeper<T> * );
~Local() noexcept;
T * operator->();
explicit operator bool() {
return resource;
}
void release( T * & );
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> release
void reset(T * &);
};
template<typename T>
inline Local<T>::Local( T * res, ResourceKeeper<T> & keep ) :
resource(res), keeper(&keep) {}
template<typename T>
inline Local<T>::~Local() noexcept {
if( resource and keeper )
keeper->release( resource );
}
template<typename T>
inline Local<T>::Local( ResourceKeeper<T> * keep ) :
keeper(keep), resource(keep ? keep->grab() : nullptr) {}
template<typename T>
inline T * Local<T>::operator ->() {
return resource;
}
template<typename T>
inline T * grab( ResourceKeeper<T> * rk ) {
return rk ? rk->grab() : nullptr;
}
template<typename T>
inline const T * show( ResourceKeeper<T> * rk ) {
return rk ? &rk->show() : nullptr;
}
template<typename T>
inline bool grab( T * & res, ResourceKeeper<T> * rk ) {
T * new_ptr = ( rk ? rk->grab() : nullptr );
res = res ? res : new_ptr;
return res;
}
template<typename T>
inline bool show( const T * & res, ResourceKeeper<T> * rk ) {
const T * new_ptr = ( rk ? &rk->show() : nullptr );
res = res ? res : new_ptr;
return res;
}
template<typename T>
inline void release( ResourceKeeper<T> * rk, T * k ) {
if( rk and k ) rk->release( k );
}
template<typename T>
inline void Local<T>::release( T * & new_owner ) {
T * temp = resource;
resource = nullptr;
new_owner = temp;
}
template<typename T>
inline void Local<T>::reset( T * & new_resource ) {
if( resource and keeper )
keeper->release( resource );
resource = new_resource;
}
struct LocableInterface {
virtual bool try_lock() = 0;
virtual void unlock() = 0;
virtual ~LocableInterface() = default;
};
template<typename T>
class Locable : public LocableInterface {
public:
Locable( ResourceKeeper<T> & keeper );
~Locable() noexcept;
T * operator->() const;
T * pointer() const;
const T & show() const;
explicit operator bool() const {
return resource;
}
bool try_lock();
void unlock() noexcept;
private:
T * resource;
ResourceKeeper<T> & keeper;
Locable( const Locable &) = delete;
Locable & operator=( const Locable & ) = delete;
};
template<typename T>
inline Locable<T>::Locable( ResourceKeeper<T> & keeper ) : keeper(keeper), resource(nullptr) {}
template<typename T>
inline Locable<T>::~Locable() noexcept {
keeper.release( resource );
}
template<typename T>
inline T * Locable<T>::operator->() const {
return resource;
}
template<typename T>
inline const T & Locable<T>::show() const {
return keeper.show();
}
template<typename T>
inline bool Locable<T>::try_lock() {
resource = keeper.grab();
return resource;
}
template<typename T>
inline T * Locable<T>::pointer() const {
return resource;
}
template<typename T>
inline void Locable<T>::unlock() noexcept {
keeper.release( resource );
}
template<typename ... Args>
struct ScopeLock {
ScopeLock( Args & ... args );
explicit operator bool();
void freeze();
~ScopeLock() noexcept;
private:
bool is_locked;
bool frozen;
std::size_t counter;
LocableInterface * locable[ sizeof...(Args) ];
int add( LocableInterface & );
};
template<typename ... Args>
inline ScopeLock<Args...>::ScopeLock( Args & ... args ) : is_locked( true ), frozen( false ), counter( 0 ) {
int temp[] = { add(args)... };
}
template<typename ... Args>
inline ScopeLock<Args...>::operator bool() {
return is_locked;
}
template<typename ... Args>
inline ScopeLock<Args...>::~ScopeLock() noexcept {
if( not is_locked or not frozen ) {
for( std::size_t i = 0; i < counter; i++ )
locable[i]->unlock();
}
}
template<typename ... Args>
inline int ScopeLock<Args...>::add( LocableInterface & lc ) {
if( is_locked and ( is_locked = lc.try_lock() ) )
locable[counter++] = &lc;
return is_locked;
}
template<typename ... Args>
inline void ScopeLock<Args...>::freeze() {
frozen = true;
}
template<typename T>
inline bool ResourceKeeper<T>::is_owned( T * pointer ) const noexcept {
return pointer == &resource;
}
#endif /* SOURCE_COMMON_RESOURCEKEEPER_HPP_ */