wrapping synchronization in objects?

G

Gernot Frisch

Hi,

is it possible (win32, *nix, only) to create a template class that
locks/unlocks a mutex every time the value of an object is used?

Like:


template <typename T> class wrapper
{
public:
wrapper() :m_t() {}
wrapper(const T& t) :m_t(t) {}
operator T() const
{
T t;
lock();
t=m_t;
unlock();
return t;
}
T operator = (const T& t)
{
lock();
m_t = t;
unlock();
return t;
}
private:
T m_t;
void lock()const {/*EnterCricitcalSection...whatever*/}
void unlock()const{/*LeaveCriticalSection...*/}
};

int main()
{
wrapper<int> i = 13;

return i;
}
 
V

Victor Bazarov

Gernot said:
is it possible (win32, *nix, only) to create a template class that
locks/unlocks a mutex every time the value of an object is used?

How do you define "used"?
Like:


template <typename T> class wrapper
{
public:
wrapper() :m_t() {}
wrapper(const T& t) :m_t(t) {}

You probably need to define the copy semantics too (the copy c-tor and
the copy assignment op).
operator T() const
{
T t;
lock();
t=m_t;
unlock();
return t;
}
T operator = (const T& t)
{
lock();
m_t = t;
unlock();
return t;

Isn't it customary to return '*this' from an assignment op?
}
private:
T m_t;
void lock()const {/*EnterCricitcalSection...whatever*/}
void unlock()const{/*LeaveCriticalSection...*/}
};

int main()
{
wrapper<int> i = 13;

return i;
}

In your program, then, there would be locking while the expression in
'return' is evaluated, right?

Why are you asking? Is there a problem with the program (besides the
stuff I've mentioned)? Does it not compile? Why ask "whether it's
possible" when you could just try it, don't you have a compiler handy?

V
 
S

SG

is it possible (win32, *nix, only) to create a template class that
locks/unlocks a mutex every time the value of an object is used?

I recently saw a nifty trick that involves a smart pointer that locks
a mutex upon "use" of its pointee.

The trick was to let operator-> return a proxy (local rvalue) that
locks the mutex in the constructor, unlocks it in the destructor and
also overrides operator-> to return the actual pointer.

void f(lockptr<my_class> p const&)
{
p->do_something();
}

would be short for

void f(lockptr<my_class> p const&)
{
p.operator->().operator->()->do_something();
}

After the first ->() you have a temporary. This temporary's ->()
returns the actual pointer which is then used to call the function.
The temporary is destroyed when the complete expression is evaluated
(including the function call do_something). Locking and unlocking is
done in the temporary's constructor and destructor.


Cheers!
SG
 
J

James Kanze

is it possible (win32, *nix, only) to create a template class
that locks/unlocks a mutex every time the value of an object
is used?

template <typename T> class wrapper
{
public:
wrapper() :m_t() {}
wrapper(const T& t) :m_t(t) {}
operator T() const
{
T t;
lock();
t=m_t;
unlock();
return t;
}
T operator = (const T& t)
{
lock();
m_t = t;
unlock();
return t;
}
private:
T m_t;
void lock()const {/*EnterCricitcalSection...whatever*/}
void unlock()const{/*LeaveCriticalSection...*/}
};
int main()
{
wrapper<int> i = 13;
return i;
}

Doubtlessly, but I doubt that it would be very useful.
Individual accesses rarely have the right granularity for
locking. (There are exceptions, of course, but they're rare
enough to probably not justify a generic solution.) Of course,
you'd want a scoped lock in the two functions, in case the
assignment threw an exception.
 
G

Gernot Frisch

In your program, then, there would be locking while the expression in
'return' is evaluated, right?

Why are you asking? Is there a problem with the program (besides the
stuff I've mentioned)? Does it not compile? Why ask "whether it's
possible" when you could just try it, don't you have a compiler handy?


My intention is to use a class instead of, say, an integer and wrap it in
lock/unlock functions so that the use of the variable is thread safe. The
whole thing is about multithreading.
 
B

Balog Pal

"Gernot Frisch"
My intention is to use a class instead of, say, an integer and wrap it in
lock/unlock functions so that the use of the variable is thread safe. The
whole thing is about multithreading.

As James pointed out, this approach is very unlikely to provide thread
safety. Though it may create the illusion of it for those unaware of common
mistakes in threading.
I suggest you first write the traditional critical sections, make them pass
review of an expert -- then come back to this problem if you found there is
exactly one access to your struct within most critical blocks.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,777
Messages
2,569,604
Members
45,228
Latest member
MikeMichal

Latest Threads

Top