From eb8b5fefdbd3c400869ad4ab0e88acb74c4f60ea Mon Sep 17 00:00:00 2001 From: Alexei Sheplyakov Date: Thu, 21 Aug 2008 15:15:09 +0400 Subject: [PATCH] Replace CL_REQUIRE/CL_PROVIDE(cl_no_ring) with portable code. The order of initialization of non-local objects in different compilation units is not specified in C++. Hence special care should be taken to avoid static initialization order fiasco. CLN solved the problem with some evil (GCC specific, and even GCC-version-specific) hack. Replace it with a technique similar to one used in STL to initialize std::cout and friends. --- include/cln/ring.h | 10 +++++++++- src/base/ring/cl_no_ring.cc | 34 +++++++++++++++++++++++++--------- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/include/cln/ring.h b/include/cln/ring.h index fcdcac9..b79d9ab 100644 --- a/include/cln/ring.h +++ b/include/cln/ring.h @@ -381,7 +381,15 @@ public: extern const cl_ring cl_no_ring; extern cl_class cl_class_no_ring; -CL_REQUIRE(cl_no_ring) + +class cl_no_ring_init_helper +{ + static int count; +public: + cl_no_ring_init_helper(); + ~cl_no_ring_init_helper(); +}; +static cl_no_ring_init_helper cl_no_ring_init_helper_instance; inline cl_ring::cl_ring () : cl_rcpointer (as_cl_private_thing(cl_no_ring)) {} diff --git a/src/base/ring/cl_no_ring.cc b/src/base/ring/cl_no_ring.cc index 5904864..88e76e7 100644 --- a/src/base/ring/cl_no_ring.cc +++ b/src/base/ring/cl_no_ring.cc @@ -3,8 +3,6 @@ // General includes. #include "cl_sysdep.h" -CL_PROVIDE(cl_no_ring) - // Specification. #include "cln/ring.h" @@ -152,14 +150,32 @@ static void cl_no_ring_dprint (cl_heap* pointer) fprint(cl_debugout, "(cl_ring) cl_no_ring"); } -cl_class cl_class_no_ring = { - cl_no_ring_destructor, - 0, - cl_no_ring_dprint -}; +cl_class cl_class_no_ring; + +static cl_heap_no_ring* cl_heap_no_ring_instance; +// const cl_ring cl_no_ring = cl_ring (new cl_heap_no_ring()); +const cl_ring cl_no_ring = cl_no_ring; + + +int cl_no_ring_init_helper::count = 0; -const cl_ring cl_no_ring = cl_ring (new cl_heap_no_ring()); +cl_no_ring_init_helper::cl_no_ring_init_helper() +{ + if (count++ == 0) { + cl_class_no_ring.destruct = cl_no_ring_destructor; + cl_class_no_ring.flags = 0; + cl_class_no_ring.dprint = cl_no_ring_dprint; + + cl_heap_no_ring_instance = new cl_heap_no_ring(); + new((void*)&cl_no_ring) cl_ring(cl_heap_no_ring_instance); + } +} + +cl_no_ring_init_helper::~cl_no_ring_init_helper() +{ + if (--count == 0) + delete cl_heap_no_ring_instance; +} } // namespace cln -CL_PROVIDE_END(cl_no_ring)