M
Marcel Müller
I would like to protect some functions of a class from being called
outside a synchronized context.
Of course I could write a proxy that forwards all functions with an
adjusted interface (see example below). But is is a bunch of work to
forward all of these methods. Note that
On the other hand I could use two interfaces one for synchronized class
instances (maybe the class itself) and a second one for the thread-safe
part. Unfortunately this causes a significant runtime overhead, since
even trivial functions would require a vtable lookup while they would
usually expanded inline else.
Any other ideas?
What a pity that one cannot define custom CV modifiers which would do
the job.
In fact I already abused volatile for strong thread safety. But this
should have no drawback since the volatile Info instances cannot be
accessed by ordinary statements anyway, since Info has no volatile methods.
Marcel
struct Info
{ Info() { }
Info(const volatile Info& r)
{ // Strongly thread safe access
}
const char* GetString() const;
// ...
};
class A
{ Info info;
protected:
void SyncMethod()
{ // ...
}
public:
void OrdinaryMethod()
{ // ...
}
const volatile Info& GetInfo() const // strong thread safety required
{ return info; }
public:
class Sync;
friend class Sync;
class Sync
{ A& a;
public:
Sync(A& a) : a(a)
{ // Aquire mutex
}
~Sync()
{ // Release mutex
}
public:
void SyncMethod()
{ a.SyncMethod();
}
void OrdinaryMethod()
{ a.OrdinaryMethod();
}
const Info& GetInfo() const // remove strong thread safety tag
{ return const_cast<Info&>(a.GetInfo());
}
Info& GetInfo()
{ return a.info; }
};
};
int main()
{
A a;
a.OrdinaryMethod();
//a.SyncMethod(); WRONG!
Info i(a.GetInfo()); // strong thread safety required
i.GetString(); // access Info content ...
{ // Hold mutex here
A::Sync a_sync(a);
a_sync.OrdinaryMethod();
a_sync.SyncMethod(); // valid
a_sync.GetInfo().GetString(); // no thread safety required
}
return 0;
}
outside a synchronized context.
Of course I could write a proxy that forwards all functions with an
adjusted interface (see example below). But is is a bunch of work to
forward all of these methods. Note that
On the other hand I could use two interfaces one for synchronized class
instances (maybe the class itself) and a second one for the thread-safe
part. Unfortunately this causes a significant runtime overhead, since
even trivial functions would require a vtable lookup while they would
usually expanded inline else.
Any other ideas?
What a pity that one cannot define custom CV modifiers which would do
the job.
In fact I already abused volatile for strong thread safety. But this
should have no drawback since the volatile Info instances cannot be
accessed by ordinary statements anyway, since Info has no volatile methods.
Marcel
struct Info
{ Info() { }
Info(const volatile Info& r)
{ // Strongly thread safe access
}
const char* GetString() const;
// ...
};
class A
{ Info info;
protected:
void SyncMethod()
{ // ...
}
public:
void OrdinaryMethod()
{ // ...
}
const volatile Info& GetInfo() const // strong thread safety required
{ return info; }
public:
class Sync;
friend class Sync;
class Sync
{ A& a;
public:
Sync(A& a) : a(a)
{ // Aquire mutex
}
~Sync()
{ // Release mutex
}
public:
void SyncMethod()
{ a.SyncMethod();
}
void OrdinaryMethod()
{ a.OrdinaryMethod();
}
const Info& GetInfo() const // remove strong thread safety tag
{ return const_cast<Info&>(a.GetInfo());
}
Info& GetInfo()
{ return a.info; }
};
};
int main()
{
A a;
a.OrdinaryMethod();
//a.SyncMethod(); WRONG!
Info i(a.GetInfo()); // strong thread safety required
i.GetString(); // access Info content ...
{ // Hold mutex here
A::Sync a_sync(a);
a_sync.OrdinaryMethod();
a_sync.SyncMethod(); // valid
a_sync.GetInfo().GetString(); // no thread safety required
}
return 0;
}