This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: PATCH: Configure libstdc++-v3 against gthr.h


SGI STL maintains a few mutex-protected global variables in order to
maintain the high-speed memory allocators for containers.  Here is a
portion of a header comment about the requirements of the mutex
abstraction:

// Locking class.  Note that this class *does not have a constructor*.
// It must be initialized either statically, with __STL_MUTEX_INITIALIZER,
// or dynamically, by explicitly calling the _M_initialize member function.
// (This is similar to the ways that a pthreads mutex can be initialized.)
[...]
// There is no constructor because static initialization is essential for
// some uses, and only a class aggregate (see section 8.5.1 of the C++
// standard) can be initialized that way.  That means we must have no
// constructors, no base classes, no virtual functions, and no private or
// protected members.

I understand that it is nice to have static initialization, when
possible, to avoid global constructor ordering issues, etc but for
platforms that do not provide a way to statically allocate a mutex,
some sort of automatic way to dynamically initialize a global variable
is required unless we want to force users to have to add STL
initialization code to their setup code as recommended in the comment.
My fear is that any approach that requires users of some platforms to
do special setup will produce many bug reports from users that fail to
do so when required.

This code example was abstracted from current STL code.  To this
abstraction, I have added a new __NOINIT case that violates the rules
in the code comment.  I propose that path should only be used on
platforms that do not provide __GTHREAD_MUTEX_INIT --- i.e. they
provide __GTHREAD_MUTEX_INIT_FUNCTION instead because their system
does not support static initialization of mutex.

I did look into using something based on __gthread_once() but (if we
assume that we can place the once call at the start of the lock
method) the issue is that we need to initialize an object whose
position is not known to the static function that must be bound to
__gthread_once.

Other related approaches fail since we do not know how many copies of
the object exist at startup time nor how many will exist.

Hence, I think the correct fallback is:

(1) Create as aggregate, if possible.
(2) Add the constructor, if required and allowed by the platform.
    This might preclude some STL uses.  In particular, the user must
    avoid global objects that contain STL containers, etc.  But the
    C++ standard already makes it hard to use global variables.
(3) Force user to do initialization setup.  Actually, the user
    has the same problem here, where does he stick his code to
    ensure it runs before any global constructor that may have
    run and assumed the mutex existed.

I would really like to completely remove option (3).  But if I can't,
I need to know how to detect whether a platform supports (2) in all
cases.

Are there any platforms supported by g++ that absolutely can't do (2)?

Is there a special g++ feature supported on all platforms where
libstdc++-v3 is compiled that I should use to reduce the issues with
option (2)?

#include <iostream>

#ifndef __NOINIT
#define __INIT = { 42, 49 }
#endif

struct __foo
{
  int __a;
  int __b;
#ifdef __NOINIT
  __foo () { __a = 42; __b = 49; }
#endif
};

template <bool __t, int __i>
class __default_foo_template {
 public:
  static __foo _S_bar;
};

// Assume these next lines appears in a header and thus seen by multiple
// translation units.
template <bool __t, int __i>
__foo __default_foo_template<__t, __i>::_S_bar __INIT;

typedef __default_foo_template<true, 0> __zippy;

main()
{
  std::cout << __zippy::_S_bar.__a << ' '
	    << __zippy::_S_bar.__b << std::endl;
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]