#include <Platform.hpp>
Usually, using it is done through volatile declaration.
Using volatile on thread shared object will automatically make the compiler check for direct access, and forbid it at COMPILE time, not runtime. It's an enormous advantage for big projects, where a single oversight could break down the whole application.
Because you can only call volatile methods on an object declared as volatile (the compiler will reject any other access), the only thing you have to do, is to create inline volatile stub that simply lock the shared object, const_cast to non-volatile and call the non volatile version.
That way, when the object is used in single threaded environment, you don't pay the cost of locking/unlocking a synchronization object. This is an huge saving for most case.
Use the LockingObjPtr if you don't want to copy the non-volatile code in volatile method. It's optimized out by the compiler, and finally, only factors as a Lock/Unlock overhead.
struct SomeSharedStruct { // Members here // Then... the lock volatile FastLock lock; public: int aMethodThatChangesSomeMember() { // Change the member here } int anotherMethod() { } public: // This is a stub that simply call the non volatile version, making sure the lock is acquired before doing so inline int aMethodThatChangesSomeMember() volatile { return LockingObjPtr<SomeSharedStruct>(*this, lock)->aMethodThatChangesSomeMember(); } // It's even easier using the AccessProt template method : (but lock must be public) // inline int aMethodThatChangesSomeMember() volatile { return AccessProt(*this)->aMethodThatChangesSomeMember(); } }; class Application { SomeSharedStruct a; volatile SomeSharedStruct b; void thread1() { a.aMethodThatChangesSomeMember(); // Will call the non volatile version, as "a" is not declared as volatile (hence it's not shared) a.anotherMethod(); // Ok, "a" is non volatile. b.aMethodThatChangesSomeMember(); // Will call the volatile version, effectively locking b.lock, changing the member, and unlocking b.lock // b.anotherMethod(); // Compiler error here, if enabled, as there is no volatile version for this method } void thread2() { a.aMethodThatChangesSomeMember(); // Will call the non volatile version, as "a" is not declared as volatile (hence it's not shared), // thus leading to synchronization errors => a is broken, the application can be too, if "a" state is vital a.anotherMethod(); // Ok, "a" is non volatile (but broken above) b.aMethodThatChangesSomeMember(); // Without even knowing it, you've avoided a big threading issue... } void main() { // Run thread1 in a new thread // Run thread2 in a new thread } };
Public Types | |
enum | TimeOut { InstantCheck = 0, Infinite = 0xFFFFFFFF } |
The timeout to wait for. More... | |
Public Member Functions | |
bool | Acquire () |
Try to acquire the lock. | |
FastLock (const char *sName=NULL, const bool &bInitialOwner=false) | |
bool | Release () |
Release the (acquired) lock or do nothing if unlocked. | |
~FastLock () |
PlatformSpecific::FastLock::FastLock | ( | const char * | sName = NULL , |
|
const bool & | bInitialOwner = false | |||
) |
PlatformSpecific::FastLock::~FastLock | ( | ) |
bool PlatformSpecific::FastLock::Acquire | ( | ) | [inline] |
Try to acquire the lock.
bool PlatformSpecific::FastLock::Release | ( | ) | [inline] |
Release the (acquired) lock or do nothing if unlocked.