Making a class threadsafe / Locking a const accessor

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Sirmont
    New Member
    • Jul 2008
    • 12

    Making a class threadsafe / Locking a const accessor

    Good day all,

    Is there a logical way to lock data in an accessor?

    Because accessors are generally declared as const methods and a lock() operation is not, how can you lock the class internally when the accessor is called?

    For example:
    Code:
    class Class
    {
    public:
      int GetValue() const;
    
    protected:
      void Lock();
      void Unlock();
    
    private:
      int m_Value;
    }
    When I implement GetValue(), i'd like to do:
    Code:
    int Class::GetValue()
    {
      Lock();
      int TmpValue = m_Value;
      Unlock();
      return(TmpValue);
    }
    But obviously this isn't good, since Lock/Unlock aren't const (and can't be).

    I am sure I am not the first to try to make a class thread safe so I guess I'm just missing something...

    Thanks!


    EDIT: Strangely, I knew of a possible solution and yet it just disappeared from my head: using const_cast on the instance of the class (or lock) would be a valid solution. But would it be the best? What do you think?
    Last edited by Sirmont; Jul 8 '08, 09:06 PM. Reason: Remembered of a solution
  • Banfa
    Recognized Expert Expert
    • Feb 2006
    • 9067

    #2
    OK this is a guess but you could try declaring lock and unlock mutable (this is a C++ keyword). I believe that would make them modifiable even in a situation that normally requires constness, such as an accessor.

    Comment

    • Sirmont
      New Member
      • Jul 2008
      • 12

      #3
      This is just absolutely perfect! Exactly what I need! Thanks!

      Comment

      • hdanw
        New Member
        • Feb 2008
        • 61

        #4
        May not be what you want.

        Can you Identify what the scope is on this Lock() call?

        Essentially a mutex m, is either locked, or unlocked.

        The OS core, is not selective about who acquires the mutex, when.

        So lets say that you are in a multi threaded environment, as is the case when synchronization is required, and you have a mutex, which is inherently associated with the object / instance.

        So when you call Lock(), you are in essence calling ParentClass.Loc k().

        Which means that accessors for other data elements are waiting for exclusive access to that object instance before they can write.

        If mutlple calls come in for seperate data members it wont matter. And since the OS is not selective, one accessor can be held indefinately while other accessors do there jobs. Potentially dogging your system. And takeing away any advantage you hoped to gain by being multi-Threaded.

        A better way is to create a Critical Section for each Specific Data Item or member. So that calls to that accessor is only blocking other calls to that same accessor. and the Other Accessors can freely access their data simultaneously.

        So, to speed up your application serialize the accessors for each data member, instead of serializing access to the intire object instance.


        Code:
        The steps are easy ...
        
        1. at instantiation call InitializeCriticalSection() for each data member.
        2. in the accessors call EnterCriticalSection() emmediatley prior to the access, 
        3, call LeaveCriticalSection() immediately following access, and finally
        4. DeleteCriticalSection in class Destructor.
        
        1: http://msdn.microsoft.com/en-us/library/ms683472(VS.85).aspx
        2: http://msdn.microsoft.com/en-us/library/ms682608.aspx
        3: http://msdn.microsoft.com/en-us/library/ms684169(VS.85).aspx
        4: http://msdn.microsoft.com/en-us/library/ms682552(VS.85).aspx
        Which is much faster than the equivalent mutex operation.

        BTW the Lock keyword is a C# thing, that was extended by the CLR.
        Without the CLR your application may have issues.

        Happy Coding!

        Comment

        • Sirmont
          New Member
          • Jul 2008
          • 12

          #5
          Very relevant comment. I understand why it would be more efficient to have one mutex/critical section per member. In fact I am very couscious of this, but the class I am making thread-safe is basically making operations on a map, so there's pretty much no gain to be made there.

          What I don't understand is why should I use a critical section instead of a mutex and how it is different?

          Thanks for your input!
          J-O

          P.-S. My Lock()/Unlock() methods were just examples. In fact I use wxWidgets, so I use wxLock/wxUnlock and wxCriticalSecti on.

          Comment

          • Banfa
            Recognized Expert Expert
            • Feb 2006
            • 9067

            #6
            A Critical Section is a more limited but lighter version of a mutex.

            That is a Critical Section provides less functionality, it in only works inter-thread with-in a single process where as a mutex works inter-process and a critical section is not a OS object so you can't use the Wait... functions to wait on it which you can with a mutex.

            However the loss of functionality results in a performance gain, it is quicker to lock/unlock a critical section compared to a mutex.

            Comment

            • Sirmont
              New Member
              • Jul 2008
              • 12

              #7
              Great! Thanks guys! This answers it all...

              Comment

              Working...