Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. How do I make calling InitializeCriticalSection() thread safe? [modified]

How do I make calling InitializeCriticalSection() thread safe? [modified]

Scheduled Pinned Locked Moved C / C++ / MFC
questiondatabasehelp
4 Posts 4 Posters 1 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    S Offline
    Steve Thresher
    wrote on last edited by
    #1

    I have a static class I use for caching data. This will now be accessed from multiple threads which means I need to add a CRITICAL_SECTION to make updating the cache thread safe. I now have the problem of who initialises the CRITICAL_SECTION given a static class doesn't have a constructor.

    std::map<int,std::string> CMY_CACHE::m_cache_map;
    
    CRITICAL_SECTION CMY_CACHE::m_critical_section;
    
    class CMY_CACHE
    {
    private:
      static std::map<int,std::string> m_cache_map;
    
      static CRITICAL_SECTION m_critical_section; //<-- Where do I initialize this?
    
    public:
        
    std::string read(int index)
    {
      EnterCriticalSection(&m_critical_section);
    
      std::map<int,std::string>::iterator it=m_cache_map.find(index);
      
      if (it==m_cache_map.end())
      {
        // Add value to cache
    
        // Adjust iterator
      }
    
      LeaveCriticalSection(&m_critical_section);
    
    
      return(it->second);
    }
    
    ...
    
      // The following call could be issued by multiple threads
      std::string s=CMY_CACHE::read(0);
    

    modified on Friday, October 16, 2009 8:28 AM

    C CPalliniC C 3 Replies Last reply
    0
    • S Steve Thresher

      I have a static class I use for caching data. This will now be accessed from multiple threads which means I need to add a CRITICAL_SECTION to make updating the cache thread safe. I now have the problem of who initialises the CRITICAL_SECTION given a static class doesn't have a constructor.

      std::map<int,std::string> CMY_CACHE::m_cache_map;
      
      CRITICAL_SECTION CMY_CACHE::m_critical_section;
      
      class CMY_CACHE
      {
      private:
        static std::map<int,std::string> m_cache_map;
      
        static CRITICAL_SECTION m_critical_section; //<-- Where do I initialize this?
      
      public:
          
      std::string read(int index)
      {
        EnterCriticalSection(&m_critical_section);
      
        std::map<int,std::string>::iterator it=m_cache_map.find(index);
        
        if (it==m_cache_map.end())
        {
          // Add value to cache
      
          // Adjust iterator
        }
      
        LeaveCriticalSection(&m_critical_section);
      
      
        return(it->second);
      }
      
      ...
      
        // The following call could be issued by multiple threads
        std::string s=CMY_CACHE::read(0);
      

      modified on Friday, October 16, 2009 8:28 AM

      C Offline
      C Offline
      Cedric Moonen
      wrote on last edited by
      #2

      Instead of having all members static, you could use a singleton pattern: it is a design pattern that makes sure your class is created only once. I won't go into much details here but I suggest you google for "Thread safe singleton pattern". Basically, you add a public static function that returns a pointer to your single instance (CMY_CACHE* CMY_CACHE::instance for example). Once your class is a singleton, you can simply create your critical section in the class constructor. Your read method is no more a static function and you call it this way:

      CMY_CACHE::instance()->read(0);

      Cédric Moonen Software developer
      Charting control [v2.0] OpenGL game tutorial in C++

      1 Reply Last reply
      0
      • S Steve Thresher

        I have a static class I use for caching data. This will now be accessed from multiple threads which means I need to add a CRITICAL_SECTION to make updating the cache thread safe. I now have the problem of who initialises the CRITICAL_SECTION given a static class doesn't have a constructor.

        std::map<int,std::string> CMY_CACHE::m_cache_map;
        
        CRITICAL_SECTION CMY_CACHE::m_critical_section;
        
        class CMY_CACHE
        {
        private:
          static std::map<int,std::string> m_cache_map;
        
          static CRITICAL_SECTION m_critical_section; //<-- Where do I initialize this?
        
        public:
            
        std::string read(int index)
        {
          EnterCriticalSection(&m_critical_section);
        
          std::map<int,std::string>::iterator it=m_cache_map.find(index);
          
          if (it==m_cache_map.end())
          {
            // Add value to cache
        
            // Adjust iterator
          }
        
          LeaveCriticalSection(&m_critical_section);
        
        
          return(it->second);
        }
        
        ...
        
          // The following call could be issued by multiple threads
          std::string s=CMY_CACHE::read(0);
        

        modified on Friday, October 16, 2009 8:28 AM

        CPalliniC Offline
        CPalliniC Offline
        CPallini
        wrote on last edited by
        #3

        The quick & dirty (you're warned...) trick: wrap the CRITICAL_SECTION in a struct and do initialization (cleanup) in struct constructor (destructor). :)

        If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
        This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarke
        [My articles]

        In testa che avete, signor di Ceprano?

        1 Reply Last reply
        0
        • S Steve Thresher

          I have a static class I use for caching data. This will now be accessed from multiple threads which means I need to add a CRITICAL_SECTION to make updating the cache thread safe. I now have the problem of who initialises the CRITICAL_SECTION given a static class doesn't have a constructor.

          std::map<int,std::string> CMY_CACHE::m_cache_map;
          
          CRITICAL_SECTION CMY_CACHE::m_critical_section;
          
          class CMY_CACHE
          {
          private:
            static std::map<int,std::string> m_cache_map;
          
            static CRITICAL_SECTION m_critical_section; //<-- Where do I initialize this?
          
          public:
              
          std::string read(int index)
          {
            EnterCriticalSection(&m_critical_section);
          
            std::map<int,std::string>::iterator it=m_cache_map.find(index);
            
            if (it==m_cache_map.end())
            {
              // Add value to cache
          
              // Adjust iterator
            }
          
            LeaveCriticalSection(&m_critical_section);
          
          
            return(it->second);
          }
          
          ...
          
            // The following call could be issued by multiple threads
            std::string s=CMY_CACHE::read(0);
          

          modified on Friday, October 16, 2009 8:28 AM

          C Offline
          C Offline
          cmk
          wrote on last edited by
          #4

          ... or, instead of a singleton, you could write a CRITICAL_SECTION wrapper class. e.g. something like

          class CS : public CRITICAL_SECTION
          {
          public:
          CS( ulong SPINCOUNT = 4000 ) {
          #ifdef _DEBUG
          ::InitializeCriticalSectionEx(this, SPINCOUNT, 0);
          #else
          ::InitializeCriticalSectionEx(this, SPINCOUNT, CRITICAL_SECTION_NO_DEBUG_INFO);
          #endif
          }
          ~CS() {
          ::DeleteCriticalSection(this);
          }
          };

          then use it wherever you used CRITICAL_SECTION.

          ...cmk The idea that I can be presented with a problem, set out to logically solve it with the tools at hand, and wind up with a program that could not be legally used because someone else followed the same logical steps some years ago and filed for a patent on it is horrifying. - John Carmack

          1 Reply Last reply
          0
          Reply
          • Reply as topic
          Log in to reply
          • Oldest to Newest
          • Newest to Oldest
          • Most Votes


          • Login

          • Don't have an account? Register

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • World
          • Users
          • Groups