Boost logo

Boost :

From: Chris Thomasson (cristom_at_[hidden])
Date: 2006-11-02 16:49:22


[...]

> your once<> class has a constructor, so it is therefore dynamically
> initialized, rather than statically, so there is a potential race
> condition in
> calling the constructor.

Here is one without a ctor:

 template<typename T>
  class once {
    var<T*> m_state;
    var<intword_t> m_count;

  public:
    // once() throw() : m_state(0), m_count(0) {}
    // m_state and m_count must be init to NULL!

    ~once() throw() {
      if (try_dec()) {
        try { delete local; }
          catch(...) { assert(false); throw; }
      }
    }

  private:
    bool try_dec() throw() {
      intword_t local;
      do {
        local = m_count.load(mb::naked);
        if (local < 0) { return false; }
        // use mb::fence to cover *both acquire and release
        // wrt the result of the decrement
      } while(! m_count.cas(local, local - 1, mb::fence));
      return (local == -1);
    }

    bool try_inc() throw() {
      intword_t local;
      do {
        local = m_count.load(mb::naked);
        if (local < 0) { return false; }
      } while(! m_count.cas(local, local + 1, mb::acquire_depends));
      return true;
    }

  public:
    // atomic load / thread-saftey: strong
    T* load() const {
      T *local = m_state.load(mb::depends);
      if (! local) {
        externlib_api::hashed_mutex::guard_t const &lock(this);
        if (! try_inc()) { return 0; }
        local = m_state.load(mb::naked);
        if (! local) {
          // call try_dec on exceptions...
          local = new T;
          m_state.store(local, mb::release);
        }
      } else if(! try_inc()) {
        return 0;
      }

      return local;
    }

    // dec the refcount
    void dec() { if (try_dec()) { delete m_state.load(mb::depends); } }
  };

The destructor runs if m_state is not null and if the refcount drops to -1.

I can't really see a problem here...


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk