$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r64337 - trunk/boost/interprocess/detail
From: igaztanaga_at_[hidden]
Date: 2010-07-25 12:47:46
Author: igaztanaga
Date: 2010-07-25 12:47:46 EDT (Sun, 25 Jul 2010)
New Revision: 64337
URL: http://svn.boost.org/trac/boost/changeset/64337
Log:
Changes for Boost 1.45
Text files modified: 
   trunk/boost/interprocess/detail/intermodule_singleton.hpp |   496 +++++++++++++++++++++++++-------------- 
   1 files changed, 317 insertions(+), 179 deletions(-)
Modified: trunk/boost/interprocess/detail/intermodule_singleton.hpp
==============================================================================
--- trunk/boost/interprocess/detail/intermodule_singleton.hpp	(original)
+++ trunk/boost/interprocess/detail/intermodule_singleton.hpp	2010-07-25 12:47:46 EDT (Sun, 25 Jul 2010)
@@ -24,11 +24,12 @@
 #include <boost/interprocess/managed_shared_memory.hpp>
 #include <boost/interprocess/detail/tmp_dir_helpers.hpp>
 #include <boost/interprocess/detail/os_file_functions.hpp>
-#include <boost/interprocess/streams/bufferstream.hpp>
+#include <boost/interprocess/detail/mpl.hpp>
 #include <cassert>
 #include <cstddef>
 #include <cstdio>
 #include <cstring>
+#include <string>
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -49,57 +50,96 @@
 namespace interprocess{
 namespace detail{
 
-namespace intermodule_singleton_helpers {
-
-const int GMemMarkToBeRemoved = -1;
-const int GMemNotPresent      = -2;
-
-typedef char pid_str_t[sizeof(OS_process_id_t)*3+1];
+namespace file_locking_helpers {
 
-inline void get_pid_str(pid_str_t &pid_str)
+inline void get_pid_creation_time_str(std::string &s)
 {
-   OS_process_id_t pid = get_current_process_id();
-   bufferstream bstream(pid_str, sizeof(pid_str));
-   bstream << pid << std::ends;
+   std::stringstream stream;
+   stream << get_current_process_id() << '_';
+   stream.precision(6);
+   stream << std::fixed << get_current_process_creation_time();
+   s = stream.str();
 }
 
-inline const char *get_lock_file_base_name()
-{  return "bip.gmem.lock.";  }
-
-inline const char *get_lock_file_subdir_name()
-{  return "bip.gmem.locks";  }
-
-inline void create_and_get_lock_file_path(std::string &s)
+inline void create_tmp_subdir_and_get_pid_based_filepath(const char *subdir_name, const char *file_prefix, OS_process_id_t pid, std::string &s, bool creation_time = false)
 {
-   std::string filename(get_lock_file_base_name());
-   pid_str_t pid_str;
-   get_pid_str(pid_str);
-   filename += pid_str;
-   tmp_folder(s);
-   if(!open_or_create_directory(s.c_str())){
-      throw interprocess_exception(error_info(system_error_code()));
-   }
+   //Let's create a lock file for each process gmem that will mark if
+   //the process is alive or not
+   create_tmp_and_clean_old(s);
    s += "/";
-   s += get_lock_file_subdir_name();
+   s += subdir_name;
    if(!open_or_create_directory(s.c_str())){
       throw interprocess_exception(error_info(system_error_code()));
    }
    s += "/";
-   s += filename;
+   s += file_prefix;
+   if(creation_time){
+      std::string sstamp;   
+      get_pid_creation_time_str(sstamp);
+      s += sstamp;
+   }
+   else{
+      pid_str_t pid_str;
+      get_pid_str(pid_str, pid);
+      s += pid_str;
+   }
 }
 
-inline void get_lock_file_path(std::string &s)
-{
-   std::string filename(get_lock_file_base_name());
+inline bool check_if_filename_complies_with_pid
+   (const char *filename, const char *prefix, OS_process_id_t pid, std::string &file_suffix, bool creation_time = false)
+{
+   //Check if filename complies with lock file name pattern
+   std::string fname(filename);
+   std::string fprefix(prefix);
+   if(fname.size() <= fprefix.size()){
+      return false;
+   }
+   fname.resize(fprefix.size());
+   if(fname != fprefix){
+      return false;
+   }
+
+   //If not our lock file, delete it if we can lock it
+   fname = filename;
+   fname.erase(0, fprefix.size());
    pid_str_t pid_str;
-   get_pid_str(pid_str);
-   filename += pid_str;
+   get_pid_str(pid_str, pid);
+   file_suffix = pid_str;
+   if(creation_time){
+      std::size_t p = fname.find('_');
+      if (p == std::string::npos){
+         return false;
+      }
+      std::string save_suffix(fname);
+      fname.erase(p);
+      fname.swap(file_suffix);
+      bool ret = (file_suffix == fname);
+      file_suffix.swap(save_suffix);
+      return ret;
+   }
+   else{
+      fname.swap(file_suffix);
+      return (file_suffix == fname);
+   }
+}
 
-   tmp_folder(s);
-   s += "/";
-   s += get_lock_file_subdir_name();
-   s += "/";
-   s += filename;
+}  //file_locking_helpers
+
+namespace intermodule_singleton_helpers {
+
+const int GMemMarkToBeRemoved = -1;
+const int GMemNotPresent      = -2;
+
+inline const char *get_lock_file_subdir_name()
+{  return "gmem";  }
+
+inline const char *get_lock_file_base_name()
+{  return "lck";  }
+
+inline void create_and_get_singleton_lock_file_path(std::string &s)
+{
+   file_locking_helpers::create_tmp_subdir_and_get_pid_based_filepath
+      (get_lock_file_subdir_name(), get_lock_file_base_name(), get_current_process_id(), s, true);
 }
 
 inline const char *get_shm_base_name()
@@ -107,55 +147,26 @@
 
 inline void get_shm_name(std::string &shm_name)
 {
-   shm_name = get_shm_base_name();
-   pid_str_t pid_str;
-   get_pid_str(pid_str);
-   shm_name += pid_str;
+   file_locking_helpers::get_pid_creation_time_str(shm_name);
+   shm_name.insert(0, get_shm_base_name());
 }
 
 inline std::size_t get_shm_size()
 {  return 65536;  }
 
-inline bool is_other_process_gmem_lock_file(const char *filename, std::string &pid_string)
-{
-   const char * const base_str = get_lock_file_base_name();
-   const std::size_t base_str_len = std::strlen(base_str);
-   const std::size_t filename_length = std::strlen(filename);
-
-   //Get pid string
-   pid_str_t pid_str;
-   get_pid_str(pid_str);
-
-   //Check filename length
-   const std::size_t pid_str_len = std::strlen(pid_str);
-   if(base_str_len >= filename_length){
-      return false;
-   }
-   //Check base str
-   for(std::size_t i = 0, max = base_str_len; i != max; ++i){
-      if(base_str[i] != filename[i]){
-         return false;
-      }
-   }
-
-   pid_string = &filename[base_str_len];
-   if((base_str_len + pid_str_len) != filename_length){
-      return true;
-   }
+inline void apply_gmem_erase_logic(const char *filepath, const char *filename);
 
-   //Check pid
-   for(std::size_t i = base_str_len, max = filename_length, pid_i = 0; i != max; ++i, ++pid_i){
-      if(filename[i] != pid_str[pid_i]){
-         return true;
-      }
-   }
-   return false;
+inline bool remove_old_gmem()
+{
+   std::string refcstrRootDirectory;
+   tmp_folder(refcstrRootDirectory);
+   refcstrRootDirectory += "/";
+   refcstrRootDirectory += get_lock_file_subdir_name();
+   return for_each_file_in_dir(refcstrRootDirectory.c_str(), apply_gmem_erase_logic);
 }
 
-inline void apply_gmem_erase_logic(const char *filepath, const char *filename);
-
 #if (defined BOOST_INTERPROCESS_WINDOWS)
-
+/*
 inline bool remove_old_gmem()
 {
    void *             hFile;                       // Handle to directory
@@ -193,7 +204,7 @@
    }
    return true;
 }
-
+*/
 
 struct locking_file_serial_id
 {
@@ -201,7 +212,11 @@
    unsigned long dwVolumeSerialNumber;
    unsigned long nFileIndexHigh;
    unsigned long nFileIndexLow;
-   volatile boost::uint32_t ref_count;
+   //This reference count counts the number of modules attached
+   //to the shared memory and lock file. This serves to unlink
+   //the locking file and shared memory when all modules are
+   //done with the global memory (shared memory)
+   volatile boost::uint32_t modules_attached_to_gmem_count;
 };
 
 inline bool lock_locking_file(int fd)
@@ -220,8 +235,10 @@
 
 inline int open_or_create_and_lock_file(const char *name)
 {
+   permissions p;
+   p.set_unrestricted();
    while(1){
-      file_handle_t handle = create_or_open_file(name);
+      file_handle_t handle = create_or_open_file(name, read_write, p);
       int fd = _open_osfhandle((intptr_t)handle, _O_TEXT);
       if(fd < 0){
          close_file(handle);
@@ -243,7 +260,7 @@
 
 inline int try_open_and_lock_file(const char *name)
 {
-   file_handle_t handle = open_existing_file(name);
+   file_handle_t handle = open_existing_file(name, read_write);
    int fd = _open_osfhandle((intptr_t)handle, _O_TEXT);
    if(fd < 0){
       close_file(handle);
@@ -292,7 +309,7 @@
    id.dwVolumeSerialNumber = info.dwVolumeSerialNumber;
    id.nFileIndexHigh = info.nFileIndexHigh;
    id.nFileIndexLow = info.nFileIndexLow;
-   id.ref_count = 1; //Initialize attached count
+   id.modules_attached_to_gmem_count = 1; //Initialize attached count
    return true;
 }
 
@@ -308,7 +325,7 @@
 }
 
 #else //UNIX
-
+/*
 inline bool remove_old_gmem()
 {
    std::string refcstrRootDirectory;
@@ -341,7 +358,7 @@
       fn += '/';
       fn += de->d_name;
 
-      if(std::remove(fn.c_str())) {
+      //if(std::remove(fn.c_str())) {
          if(::stat(fn.c_str(), & st)) {
             return false;
          }
@@ -349,17 +366,21 @@
          if(!S_ISDIR(st.st_mode)) {
             apply_gmem_erase_logic(fn.c_str(), de->d_name);
          }
-      }
+      //}
    }
    return true;
 }
-
+*/
 struct locking_file_serial_id
 {
    int fd;
    dev_t st_dev;
    ino_t st_ino;
-   volatile boost::uint32_t ref_count;
+   //This reference count counts the number of modules attached
+   //to the shared memory and lock file. This serves to unlink
+   //the locking file and shared memory when all modules are
+   //done with the global memory (shared memory)
+   volatile boost::uint32_t modules_attached_to_gmem_count;
 };
 
 inline bool lock_locking_file(int fd)
@@ -388,8 +409,10 @@
 
 inline int open_or_create_and_lock_file(const char *name)
 {
+   permissions p;
+   p.set_unrestricted();
    while(1){
-      int fd = create_or_open_file(name);
+      int fd = create_or_open_file(name, read_write, p);
       if(fd < 0){
          return fd;
       }
@@ -409,7 +432,7 @@
 
 inline int try_open_and_lock_file(const char *name)
 {
-   int fd = open_existing_file(name);
+   int fd = open_existing_file(name, read_write);
    if(fd < 0){
       return fd;
    }
@@ -453,7 +476,7 @@
    id.fd = fd;
    id.st_dev = s.st_dev;
    id.st_ino = s.st_ino;
-   id.ref_count = 1; //Initialize attached count
+   id.modules_attached_to_gmem_count = 1; //Initialize attached count
    return true;
 }
 
@@ -471,8 +494,8 @@
 
 struct gmem_erase_func
 {
-   gmem_erase_func(const char *shm_name, const char *lock_file_path, managed_shared_memory & shm)
-      :shm_name_(shm_name), lock_file_path_(lock_file_path), shm_(shm)
+   gmem_erase_func(const char *shm_name, const char *singleton_lock_file_path, managed_shared_memory & shm)
+      :shm_name_(shm_name), singleton_lock_file_path_(singleton_lock_file_path), shm_(shm)
    {}
 
    void operator()()
@@ -481,27 +504,33 @@
       if(pserial_id){
          pserial_id->fd = GMemMarkToBeRemoved;
       }
-      delete_file(lock_file_path_);
+      delete_file(singleton_lock_file_path_);
       shared_memory_object::remove(shm_name_);
    }
    
    const char * const shm_name_;
-   const char * const lock_file_path_;
+   const char * const singleton_lock_file_path_;
    managed_shared_memory & shm_;
 };
 
+//This function applies shared memory erasure logic based on the passed lock file.
 inline void apply_gmem_erase_logic(const char *filepath, const char *filename)
 {
    int fd = GMemMarkToBeRemoved;
    try{
       std::string str;
-      if(!is_other_process_gmem_lock_file(filename, str)){
+      //If the filename is current process lock file, then avoid it
+      if(file_locking_helpers::check_if_filename_complies_with_pid
+         (filename, get_lock_file_base_name(), get_current_process_id(), str, true)){
          return;
       }
+      //Open and lock the other process' lock file
       fd = try_open_and_lock_file(filepath);
       if(fd < 0){
          return;
       }
+      //If done, then the process is dead so take global shared memory name
+      //(the name is based on the lock file name) and try to apply erasure logic
       str.insert(0, get_shm_base_name());
       try{
          managed_shared_memory shm(open_only, str.c_str());
@@ -509,6 +538,7 @@
          shm.try_atomic_func(func);
       }
       catch(interprocess_exception &e){
+         //If shared memory is not found erase the lock file
          if(e.get_error_code() == not_found_error){
             delete_file(filepath);
          }
@@ -528,6 +558,7 @@
 
 namespace intermodule_singleton_helpers {
 
+//The lock file logic creates uses a unique instance to a file
 struct lock_file_logic
 {
    lock_file_logic(managed_shared_memory &shm)
@@ -544,19 +575,30 @@
    void operator()(void)
    {
       retry_with_new_shm = false;
-      locking_file_serial_id *pserial_id = mshm.find<locking_file_serial_id>("lock_file_fd").first;
+
+      //First find the file locking descriptor id
+      locking_file_serial_id *pserial_id =
+         mshm.find<locking_file_serial_id>("lock_file_fd").first;
 
       int fd;
+      //If not found schedule a creation
       if(!pserial_id){
          fd = GMemNotPresent;
       }
+      //Else get it
       else{
          fd = pserial_id->fd;
       }
+      //If we need to create a new one, do it
       if(fd == GMemNotPresent){
          std::string lck_str;
-         create_and_get_lock_file_path(lck_str);
+         //Create a unique current pid based lock file path
+         create_and_get_singleton_lock_file_path(lck_str);
+         //Open or create and lock file
          int fd = intermodule_singleton_helpers::open_or_create_and_lock_file(lck_str.c_str());
+         //If failed, write a bad file descriptor to notify other modules that
+         //something was wrong and unlink shared memory. Mark the function object
+         //to tell caller to retry with another shared memory
          if(fd < 0){
             this->register_lock_file(GMemMarkToBeRemoved);
             std::string s;
@@ -564,13 +606,21 @@
             shared_memory_object::remove(s.c_str());
             retry_with_new_shm = true;
          }
+         //If successful, register the file descriptor
          else{
             this->register_lock_file(fd);
          }
       }
+      //If the fd was invalid (maybe a previous try failed) notify caller that
+      //should retry creation logic, since this shm might have been already
+      //unlinked since the shm was removed
       else if (fd == GMemMarkToBeRemoved){
          retry_with_new_shm = true;
       }
+      //If the stored fd is not valid (a open fd, a normal file with the
+      //expected size, or does not have the same file id number,
+      //then it's an old shm from an old process with the same pid.
+      //If that's the case, mark it as invalid
       else if(!is_valid_fd(fd) ||
             !is_normal_file(fd) ||
             0 != get_size(fd) ||
@@ -582,8 +632,9 @@
          retry_with_new_shm = true;
       }
       else{
-         //Valid lock file, just increment ref count
-         atomic_inc32(&pserial_id->ref_count);
+         //If the lock file is ok, increment reference count of
+         //attached modules to shared memory
+         atomic_inc32(&pserial_id->modules_attached_to_gmem_count);
       }
    }
 
@@ -601,19 +652,30 @@
 class intermodule_singleton_common
 {
    public:
-   typedef void*(init_func_t)(managed_shared_memory &);
-   typedef void (fini_func_t)(void *, managed_shared_memory &);
+   typedef void*(singleton_constructor_t)(managed_shared_memory &);
+   typedef void (singleton_destructor_t)(void *, managed_shared_memory &);
+
+   static const ::boost::uint32_t Uninitialized       = 0u;
+   static const ::boost::uint32_t Initializing        = 1u;
+   static const ::boost::uint32_t Initialized         = 2u;
+   static const ::boost::uint32_t Broken              = 3u;
 
-   static void destroy_pc(void *ptr, fini_func_t fini_func)
+   static void finalize_singleton_logic(void *ptr, singleton_destructor_t destructor)
    {
       if(ptr)
-         fini_func(ptr, get_shm());
-      if(1 == atomic_dec32(&shm_ref_count)){
+         destructor(ptr, get_shm());
+      //If this is the last singleton of this module
+      //apply shm destruction.
+      //Note: singletons are destroyed when the module is unloaded
+      //so no threads should be executing or holding references
+      //to this module
+      if(1 == atomic_dec32(&this_module_singleton_count)){
          destroy_shm();
       }
    }
 
-   static void initialize_pc(void *&ptr, volatile boost::uint32_t &barrier, init_func_t ini_func);
+   static void initialize_singleton_logic
+      (void *&ptr, volatile boost::uint32_t &this_module_singleton_initialized, singleton_constructor_t ini_func);
 
    private:
    static managed_shared_memory &get_shm()
@@ -625,19 +687,21 @@
    static void initialize_shm();
    static void destroy_shm();
    //Static data, zero-initalized without any dependencies
-   static volatile boost::uint32_t shm_ref_count;
-   static volatile boost::uint32_t shm_initialized;
+   //this_module_singleton_count is the number of singletons used by this module
+   static volatile boost::uint32_t this_module_singleton_count;
+   //this_module_shm_initialized is the state of this module's shm class object
+   static volatile boost::uint32_t this_module_shm_initialized;
    static max_align shm_mem[MemSize];
 };
 
 template<int Dummy>
-volatile boost::uint32_t intermodule_singleton_common<Dummy>::shm_ref_count;
+volatile boost::uint32_t intermodule_singleton_common<Dummy>::this_module_singleton_count;
 
-template<int Dummy>
-const std::size_t intermodule_singleton_common<Dummy>::MemSize;
+//template<int Dummy>
+//const std::size_t intermodule_singleton_common<Dummy>::MemSize;
 
 template<int Dummy>
-volatile boost::uint32_t intermodule_singleton_common<Dummy>::shm_initialized;
+volatile boost::uint32_t intermodule_singleton_common<Dummy>::this_module_shm_initialized;
 
 template<int Dummy>
 max_align intermodule_singleton_common<Dummy>::shm_mem[intermodule_singleton_common<Dummy>::MemSize];
@@ -645,30 +709,41 @@
 template<int Dummy>
 void intermodule_singleton_common<Dummy>::initialize_shm()
 {
+   //Obtain unique shm name and size
    std::string s;
    intermodule_singleton_helpers::get_shm_name(s);
    const char *ShmName = s.c_str();
    const std::size_t ShmSize = intermodule_singleton_helpers::get_shm_size();;
    while(1){
-      ::boost::uint32_t tmp = atomic_cas32(&shm_initialized, 1, 0);
-      if(tmp >= 2u){
+      //Try to pass shm state to initializing
+      ::boost::uint32_t tmp = atomic_cas32(&this_module_shm_initialized, Initializing, Uninitialized);
+      if(tmp >= Initialized){
          break;
       }
-      else if(tmp == 1u){
+      //If some other thread is doing the work wait
+      else if(tmp == Initializing){
          thread_yield();
       }
-      else{ //(tmp == 0u)
+      else{ //(tmp == Uninitialized)
+         //If not initialized try it again?
          try{
+            //Remove old shared memory from the system
             intermodule_singleton_helpers::remove_old_gmem();
+            //in-place construction of the shared memory class
             ::new (&get_shm())managed_shared_memory(open_or_create, ShmName, ShmSize);
-             intermodule_singleton_helpers::lock_file_logic f(get_shm());
+            //Use shared memory internal lock to initialize the lock file
+            //that will mark this gmem as "in use".
+            intermodule_singleton_helpers::lock_file_logic f(get_shm());
             get_shm().atomic_func(f);
+            //If function failed (maybe a competing process has erased the shared
+            //memory between creation and file locking), retry with a new instance.
             if(f.retry_with_new_shm){
                get_shm().~managed_shared_memory();
-               atomic_write32(&shm_initialized, 0);
+               atomic_write32(&this_module_shm_initialized, Uninitialized);
             }
             else{
-               atomic_write32(&shm_initialized, 2);
+               //Locking succeeded, so this shared memory module-instance is ready
+               atomic_write32(&this_module_shm_initialized, Initialized);
                break;
             }
          }
@@ -691,12 +766,12 @@
          mshm_.find<intermodule_singleton_helpers::locking_file_serial_id>
             ("lock_file_fd").first;
       assert(0 != pserial_id);
-      if(1 == atomic_dec32(&pserial_id->ref_count)){
+      if(1 == atomic_dec32(&pserial_id->modules_attached_to_gmem_count)){
          int fd = pserial_id->fd;
          if(fd > 0){
             pserial_id->fd = intermodule_singleton_helpers::GMemMarkToBeRemoved;
             std::string s;
-            intermodule_singleton_helpers::get_lock_file_path(s);
+            intermodule_singleton_helpers::create_and_get_singleton_lock_file_path(s);
             delete_file(s.c_str());
             intermodule_singleton_helpers::close_lock_file(fd);
             intermodule_singleton_helpers::get_shm_name(s);
@@ -710,51 +785,80 @@
 template<int Dummy>
 void intermodule_singleton_common<Dummy>::destroy_shm()
 {
-   if(!atomic_read32(&shm_ref_count)){
+   if(!atomic_read32(&this_module_singleton_count)){
+      //This module is being unloaded, so destroy
+      //the shared memory object of this module
+      //and unlink the shared memory if it's the last
       unlink_shmlogic f(get_shm());
       get_shm().atomic_func(f);
       (get_shm()).~managed_shared_memory();
-      atomic_write32(&shm_initialized, 0u);
+      atomic_write32(&this_module_shm_initialized, Uninitialized);
+      //Do some cleanup for other processes old gmem instances
       intermodule_singleton_helpers::remove_old_gmem();
    }
 }
 
+//Initialize this_module_singleton_ptr, creates the shared memory if needed and also creates an unique
+//opaque type in shared memory through a singleton_constructor_t function call,
+//initializing the passed pointer to that unique instance.
+//
+//We have two concurrency types here. a)the shared memory/singleton creation must
+//be safe between threads of this process but in different modules/dlls. b)
+//the pointer to the singleton is per-module, so we have to protect this
+//initization between threads of the same module.
+//
+//All static variables declared here are shared between inside a module
+//so atomic operations will synchronize only threads of the same module.
 template<int Dummy>
-void intermodule_singleton_common<Dummy>::initialize_pc(void *&ptr, volatile boost::uint32_t &barrier, init_func_t init_func)
+void intermodule_singleton_common<Dummy>::initialize_singleton_logic
+   (void *&ptr, volatile boost::uint32_t &this_module_singleton_initialized, singleton_constructor_t constructor)
 {
-   // insert memory barrier
-   if(atomic_read32(&barrier) != 2u){
-      //Try to pass from 0 to 1, and insert memory barrier
-      ::boost::uint32_t tmp_barrier = atomic_cas32(&barrier, 1, 0);
-      if(tmp_barrier == 0u){
+   //If current module is not initialized enter to lock free logic
+   if(atomic_read32(&this_module_singleton_initialized) != Initialized){
+      //Now a single thread of the module will succeed in this CAS.
+      //trying to pass from Uninitialized to Initializing
+      ::boost::uint32_t previous_module_singleton_initialized = atomic_cas32
+         (&this_module_singleton_initialized, Initializing, Uninitialized);
+      //If the thread succeeded the CAS (winner) it will compete with other 
+      //winner threads from other modules to create the shared memory
+      if(previous_module_singleton_initialized == Uninitialized){
          try{
+            //Now initialize shm, this function solves concurrency issues
+            //between threads of several modules
             initialize_shm();
-            atomic_inc32(&shm_ref_count);
-            //This can throw
-            void *tmp = init_func(get_shm());
-            //Barrier...
-            atomic_write32(&barrier, 1u);
-            //This won't throw
+            //Increment the module reference count that reflects how many
+            //singletons this module holds, so that we can safely destroy
+            //module shared memory object when no singleton is left
+            atomic_inc32(&this_module_singleton_count);
+            //Now try to create the singleton in shared memory.
+            //This function solves concurrency issues
+            //between threads of several modules
+            void *tmp = constructor(get_shm());
+            //Insert a barrier before assigning the pointer to
+            //make sure this assignment comes after the initialization
+            atomic_write32(&this_module_singleton_initialized, Initializing);
+            //Assign the singleton address to the module-local pointer
             ptr = tmp;
             //Memory barrier inserted, all previous operations should complete
-            //before this one
-            atomic_inc32(&barrier);
+            //before this one. Now marked as initialized
+            atomic_inc32(&this_module_singleton_initialized);
          }
          catch(...){
             //Mark singleton failed to initialize
-            atomic_write32(&barrier, 3u);
+            atomic_write32(&this_module_singleton_initialized, Broken);
             throw;
          }
       }
-      else if(tmp_barrier == 1u){
-         //Another thread is initializing the singleton, just wait
+      //If previous state was initializing, this means that another winner thread is
+      //trying to initialize the singleton. Just wait until completes its work.
+      else if(previous_module_singleton_initialized == Initializing){
          while(1){
-            tmp_barrier = atomic_read32(&barrier);
-            if(tmp_barrier >= 2u){
+            previous_module_singleton_initialized = atomic_read32(&this_module_singleton_initialized);
+            if(previous_module_singleton_initialized >= Initialized){
                //Already initialized, or exception thrown by initializer thread
                break;
             }
-            else if(tmp_barrier == 1u){
+            else if(previous_module_singleton_initialized == Initializing){
                detail::thread_yield();
             }
             else{
@@ -763,65 +867,95 @@
             }
          }
       }
-      if(tmp_barrier > 2u){
-         //Exception thrown, singleton initialization failed
-         throw interprocess_exception();
+      else if(previous_module_singleton_initialized == Initialized){
+         //Nothing to do here, the singleton is ready
+      }
+      //If previous state was greater than initialized, then memory is broken
+      //trying to initialize the singleton.
+      else{//(previous_module_singleton_initialized > Initialized)
+         throw interprocess_exception("boost::interprocess::intermodule_singleton initialization failed");
       }
    }
    assert(ptr != 0);
 }
 
-
-//Now this class is a classic singleton, initializing the singleton in
-//the first get() function call
-
-template<typename C>
+//Now this class is a singleton, initializing the singleton in
+//the first get() function call if LazyInit is false. If true
+//then the singleton will be initialized when loading the module.
+template<typename C, bool LazyInit = false>
 class intermodule_singleton
 {
    public:
    static C& get()   //Let's make inlining easy
    {
-      if(!pc){
-         if(deleter.dummy_function())  //This forces deleter instantiation, for reference counted destruction
-            intermodule_singleton_common<0>::initialize_pc(pc, barrier, initialize);
+      if(!this_module_singleton_ptr){
+         if(lifetime.dummy_function())  //This forces lifetime instantiation, for reference counted destruction
+            intermodule_singleton_common<0>::initialize_singleton_logic
+               (this_module_singleton_ptr, this_module_singleton_initialized, singleton_constructor);
       }
-      return *static_cast<C*>(pc);
+      return *static_cast<C*>(this_module_singleton_ptr);
    }
 
    struct ref_count_ptr
    {
       ref_count_ptr(C *p, boost::uint32_t count)
-         : ptr(p), ref_count(count)
+         : ptr(p), singleton_ref_count(count)
       {}
       C *ptr;
-      volatile boost::uint32_t ref_count;
+      //This reference count serves to count the number of attached
+      //modules to this singleton
+      volatile boost::uint32_t singleton_ref_count;
    };
 
    private:
-   //These will be zero-initialized without any constructor call dependency
-   static void*                      pc;
-   static volatile boost::uint32_t   barrier;
+   //These statics will be zero-initialized without any constructor call dependency
+   //this_module_singleton_ptr will be a module-local pointer to the singleton
+   static void*                      this_module_singleton_ptr;
+   //this_module_singleton_count will be used to synchronize threads of the same module
+   //for access to a singleton instance, and to flag the state of the
+   //singleton.
+   static volatile boost::uint32_t   this_module_singleton_initialized;
+
    //This class destructor will trigger singleton destruction
-   static struct deleter_type
+   struct lifetime_type_lazy
    {
       bool dummy_function()
       {  return m_dummy == 0; }
 
-      ~deleter_type()
+      ~lifetime_type_lazy()
       {
-         intermodule_singleton_common<0>::destroy_pc(pc, finalize);
+         intermodule_singleton_common<0>::finalize_singleton_logic
+            (this_module_singleton_ptr, singleton_destructor);
       }
       //Dummy volatile so that the compiler can't resolve its value at compile-time
-      //and can't avoid deleter_type instantiation if dummy_function() is called.
+      //and can't avoid lifetime_type instantiation if dummy_function() is called.
       static volatile int m_dummy;
-   } deleter;
+   };
 
-   
+   struct lifetime_type_static
+      : public lifetime_type_lazy
+   {
+      lifetime_type_static()
+      {
+         intermodule_singleton_common<0>::initialize_singleton_logic
+            (this_module_singleton_ptr, this_module_singleton_initialized, singleton_constructor);
+      }
+   };
+
+   typedef typename if_c
+      <LazyInit, lifetime_type_lazy, lifetime_type_static>::type lifetime_type;
+
+   static lifetime_type lifetime;
+
+   //A functor to be executed inside shared memory lock that just
+   //searches for the singleton in shm and if not present creates a new one.
+   //If singleton constructor throws, the exception is propagated
    struct init_atomic_func
    {
       init_atomic_func(managed_shared_memory &m)
          : mshm(m)
       {}
+
       void operator()()
       {
          ref_count_ptr *rcount = mshm.find<ref_count_ptr>(unique_instance).first;
@@ -835,25 +969,28 @@
                throw;
             }
          }
-         atomic_inc32(&rcount->ref_count);
+         atomic_inc32(&rcount->singleton_ref_count);
          ret_ptr = rcount->ptr;
       }
       managed_shared_memory &mshm;
       void *ret_ptr;
    };
 
+   //A functor to be executed inside shared memory lock that just
+   //deletes the singleton in shm if the attached count reaches to zero
    struct fini_atomic_func
    {
       fini_atomic_func(managed_shared_memory &m)
          : mshm(m)
       {}
+
       void operator()()
       {
          ref_count_ptr *rcount = mshm.find<ref_count_ptr>(unique_instance).first;
             //The object must exist
          assert(rcount);
          //Check if last reference
-         if(atomic_dec32(&rcount->ref_count) == 1){
+         if(atomic_dec32(&rcount->singleton_ref_count) == 1){
             //If last, destroy the object
             assert(rcount->ptr != 0);
             delete rcount->ptr;
@@ -866,33 +1003,34 @@
       void *ret_ptr;
    };
 
-
-   static void *initialize(managed_shared_memory &mshm)
+   //A wrapper to execute init_atomic_func
+   static void *singleton_constructor(managed_shared_memory &mshm)
    {
       init_atomic_func f(mshm);
       mshm.atomic_func(f);
       return f.ret_ptr;
    }
 
-   static void finalize(void *p, managed_shared_memory &mshm)
+   //A wrapper to execute fini_atomic_func
+   static void singleton_destructor(void *p, managed_shared_memory &mshm)
    {  (void)p;
       fini_atomic_func f(mshm);
       mshm.atomic_func(f);
    }
 };
 
-template <typename C>
-volatile int intermodule_singleton<C>::deleter_type::m_dummy;
+template <typename C, bool L>
+volatile int intermodule_singleton<C, L>::lifetime_type_lazy::m_dummy;
 
 //These will be zero-initialized by the loader
-template <typename C>
-void *intermodule_singleton<C>::pc;
+template <typename C, bool L>
+void *intermodule_singleton<C, L>::this_module_singleton_ptr;
 
-template <typename C>
-volatile boost::uint32_t intermodule_singleton<C>::barrier;
+template <typename C, bool L>
+volatile boost::uint32_t intermodule_singleton<C, L>::this_module_singleton_initialized;
 
-template <typename C>
-typename intermodule_singleton<C>::deleter_type intermodule_singleton<C>::deleter;
+template <typename C, bool L>
+typename intermodule_singleton<C, L>::lifetime_type intermodule_singleton<C, L>::lifetime;
   
 
 }  //namespace detail{