Boost logo

Boost :

From: Chris Thomasson (cristom_at_[hidden])
Date: 2006-10-30 09:02:18


"Roland Schwarz" <roland.schwarz_at_[hidden]> wrote in message

news:4544CC77.9060009_at_chello.at...
> Triggered by the question how to do
> static initialization of a mutex, I
> tried to write one that is.

Here is something you can try...

pseudo-code
-----------------

namespace atomic {
  template<typename T> class var;
  template<typename T> class once;

  namespace mb {
    enum naked_e { naked };
    enum fence_e { fence };
    enum release_e { release };
    enum depends_e { depends };
  }

  namespace externlib_api {
    class hashed_mutex;

    template<typename T> extern
    T load(T volatile*, mb::naked_e) const throw();

    template<typename T> extern
    T load(T volatile*, mb::depends_e) const throw();

    template<typename T> extern
    void store(T volatile*, T const&, mb::release_e) throw();

    template<typename T> extern
    void store(T volatile*, T const&, mb::naked_e) throw();
  }

  template<typename T>
  class var {
    mutable T volatile m_state;

  public:
    var() throw() {}
    var(T const &state) throw() : m_state(state) {}

  public:
    inline T load(mb::depends_e) const throw() {
      return externlib_api::load(&m_state, mb::depends);
    }

    inline T load(mb::naked_e) const throw() {
      return externlib_api::load(&m_state, mb::naked);
    }

  public:
    inline void store(T const &xchg, mb::fence_e) throw() {
      externlib_api::store(&m_state, xchg, mb::fence);
    }

    inline void store(T const &xchg, mb::naked_e) throw() {
      externlib_api::store(&m_state, xchg, mb::naked);
    }
  };

  template<typename T>
  class once {
    var<T> m_state;

  public:
    once() throw() : m_state(0) {}

    ~once() throw() {
      T *local = m_state.load(mb::naked);
      if (local) {
        // assume this is statically out of scope
        try { delete local; }
          catch(...) { assert(false); throw; }
      }
    }

  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);
        local = m_state.load(mb::naked);
        if (! local) {
          local = new T;
          m_state.store(local, mb::release);
        }
      }
      return local;
    }
  };
}

// usage...
static atomic::once<foo> g_foo;

void some_threads(...) {
  for(;;) {
    // whatever...

    foo *myfoo = g_foo.load();
  }
}

Any thoughts?


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