I have a hybrid-lock class that spin tries a lock for a (compile time fixed) number of spins before falling back to blocking on a std::mutex
until the lock becomes available.
Simplified:
#include <mutex>
template<unsigned SPIN_LIMIT>
class hybrid_lock {
public:
void lock(){
for(unsigned i(0);i<SPIN_LIMIT;++i){
if(this->mMutex.try_lock()){
return;
}
}
this->mMutex.lock();
}
void unlock(){
this->mMutex.unlock();
}
private:
std::mutex mMutex;
};
In the special case of SPIN_LIMIT==0
this falls back to being a 'plain' std::mutex
(i.e. no visible spins).
So I've specialized that to:
template<>
class hybrid_lock<0> : public std::mutex {};
It works fine but is that the approved way of specializing class templates to be another (pre-existing) template?
Note: I answered the actual question rather than the one in the title.
Well, now hybird_lock<0>
and hybird_lock<1>
are quite something different, one derives from std::mutex
and the other contains/wraps it. This changes whole constiution of hybird_lock
and meaning behind it. I.e. they are not semantically the same. This might led to some rather unexpected consequences -hybird_lock<0>
would inherit a whole lot of stuff, which other cases wouldn't have.
If that's the only difference I would not bother with specialization at all. Remember the zero-case will be known at compile time, and as certainly as it gets, the whole loop will be completely optimized out.
If there were other important (or actual) optimizations, I'd would go for something like:
template<>
class hybrid_lock<0> {
public:
void lock(){
this->mMutex.lock();
}
void unlock(){
this->mMutex.unlock();
}
private:
std::mutex mMutex;
};
This implementation makes 0
a special case, rather than something almost completely different.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With