This is the mail archive of the
mailing list for the GCC project.
A variation of constructor attribute
- From: J Decker <d3ck0r at gmail dot com>
- To: gcc at gcc dot gnu dot org
- Date: Fri, 21 Aug 2015 10:00:55 -0700
- Subject: A variation of constructor attribute
- Authentication-results: sourceware.org; auth=none
It's nice that GCC has included a constructor attribute, but it
doesn't work in complex scenarios.
I was considering tinkering with adding a 'initializer' and '?exiter'
or maybe 'deinitializer'? (not sure what to name the other side) But
on to the primary...
__attribute((initializer(priority))) similar to constructor, but, and
especially significant under windows, doesn't run until just before
main() is dispatched. The initializers would be added to a list (or
linked into a list) so they will all run in-order. It's not always
proper to run lowest level initializers first (at dynamic library load
time), and under windows the dll loader lock that blocks thread
creation prevents creation of threads in constructor or DllMain level
initializers. By waiting until all libraries have been loaded, and
then dispatching their initializers the thread block is overcome.
I implemented for my own library a method of doing this; but it
requires additional code be added to each library/executable that uses
this. Perhaps there is a way to overcome 2 of the source files I
include, but the third (the scheduling part) would still have to be
added, which makes adding new projects annoying. (I add a source at
start with a known, unique name that indicates the first in a
__attribute__((section( "deadstart_list" ))) and another that's the
last in the section, the third source knows the section and can
iterate through the objects defined there and schedule them. In the
program I link a 4th source that has a __attribute__((constructor))
that calls all the registered startups.)
So this new attribute would create a data structure similar to
constructor, with a few extra fields to support adding it in-place
into a list, and a flag for dispatched. it is possible that the list
will change as the list is processed too, since a initializer could
load another library which has it's own intializer attributed
functions with various priorities (perhaps priorities that are lower
than what has already been processed).
I do assume that this is like most other projects I've run into that
'if I want something done, I'll have to do it myself'.
Here's a rough flow of a process consisting of program lib1, plugin1
program loads, lib1 gets loaded; using constructor attributes,
initializers in lib1 run (and cannot create threads in windows)... but
if lib1 actually has a high priority constructor that loads plugin1
not all of the constructors have nessecarily run, but plugin1's
constructors will all run at that time; It may rely on higher
priority constructors from lib1 which run after the point it's
after scheduling the routines, and returning to main initializers,
intializer routines should start running, and new libraries loaded
during initialization should get their initializers scheduled at that
time (which may include initializers that are higher in priority than
the current running initializer). But after all initializers have
run, when a new library is loaded initializers should run
hmm requires support in dlopen/LoadLibrary function too, because
again, have to return to code outside of the loading process to create
threads.... so maybe it's not practical to implement