Reputation: 1490
Watching Herb Sutter's talk about atomics at C++ and beyond I glimpsed at his idea of an easy to use lock/unlock mechanism that may or may not come in a future standard of the language.
The mechanism looks likes:
atomic{
// code here
}
Not wanting to wait for a future standard I tried implementing this myself, what I've come up with is this:
#define CONCAT_IMPL(A, B) A ## B
#define CONCAT(A, B) CONCAT_IMPL(A, B)
# define atomic(a) { \
static_assert(std::is_same<decltype(a), std::mutex>::value,"Argument must be of type std::mutex !");\
struct CONCAT(atomic_impl_, __LINE__)\
{\
std::function<void()> func;\
std::mutex* impl;\
CONCAT(atomic_impl_, __LINE__)(std::mutex& b)\
{ \
impl = &b;\
impl->lock();\
}\
CONCAT(~atomic_impl_, __LINE__)()\
{ \
func();\
impl->unlock(); \
}\
} CONCAT(atomic_impl_var_, __LINE__)(a);\
CONCAT(atomic_impl_var_, __LINE__).func = [&]()
and usage:
std::mutex mut;
atomic(mut){
// code here
};}
The problem, obviously, is the }; which I'd like to remove.
Is this possible in any way?
Upvotes: 3
Views: 661
Reputation: 56883
A simpler version would use for
and a std::unique_lock
:
#include <iostream>
#include <type_traits>
#include <mutex>
#define atomic(a) \
for(auto lock=std::unique_lock<std::decay<decltype(a)>::type>(a); lock; lock.unlock())
int main()
{
std::mutex m;
atomic(m) {
std::cout << "Hello, world!" << std::endl;
}
}
Upvotes: 2
Reputation: 8143
You can do this with the trick of defining variables inside an if
statement.
template <typename M>
struct atomic_guard_ {
explicit atomic_guard_(M& m) : lock(m) {}
atomic_guard_(M const&) =delete; // Since we unfortunately have to use uniform
atomic_guard_(M&&) =delete; // initialization, make it at least a little safe
operator bool() const { return false; }
std::lock_guard<M> lock;
};
#define atomic(m) \
if (atomic_guard_<std::decay<decltype(m)>::type> _{m}) {} else
int main()
{
std::mutex m;
atomic(m) {
std::cout << "a\n";
}
atomic(m) // this works too, but I think this is ok
std::cout << "b\n";
}
Upvotes: 7
Reputation: 279325
Use lock_guard
. If you want to involve a macro I suppose you can, it will save you choosing a variable name and it will avoid the (surprisingly easy) typo of accidentally creating a temporary instead of a variable.
Upvotes: 4