On 12/16/11 1:41 PM, Jonathan M Davis wrote:
You could make core.time use property functions instead of the static
immutable variables that it's using now for ticksPerSec and
appOrigin, but in order to do that right would require introducing a
mutex or synchronized block (which is really just a mutex under the
hood anyway), and I'm loathe to do that in time-related code.
ticksPerSec gets used all over the place in TickDuration, and that
could have a negative impact on performance for something that needs
to be really fast (since it's used in stuff like StopWatch and
benchmarking). On top of that, in order to maintain the current
semantics, the property functions would have to be pure, which they
can't be without doing some nasty casting to convince the compiler
that stuff which isn't pure is actually pure.

For std.datetime, the problem would be reduced if a class could be
created in CTFE and still be around at runtime, but we can't do that
yet, and it wouldn't completely solve the problem, since the shared
static constructor related to LocalTime has to call tzset. So, some
sort of runtime initialization must be done. And the instances for
the singleton are not only immutable, but the functions for getting
them are pure. So, once again, some nasty casting would be required
to get it to work without breaking purity. And once again, we'd have
introduce a mutex. And for both core.time and std.datetime we're
talking about a mutex would be needed only briefly to ensure that we
don't end up with two threads trying to initialize the variable at
the same time. After that, it would just be impeding performance for
no value. They're classic situations for static constructors -
initializing static immutable variables - and really, they _should_
be using static constructors. If we have to get rid of them, it's to
get around other problems in the language or compiler instead of
fixing those problems. So, on some level, that seems like a failure
on the part of the language and the compiler. If we _have_ to find a
workaround, then we have to find a workaround, but I find the need to
be distasteful to say the least. I previously tried to get rid of the
static constructors in std.datetime and couldn't precisely because
they're needed unless you play major casting games to get around
immutable and pure.

If we play nice, it's impossible to get rid of the static
constructors in std.datetime. It probably is possible if we do nasty
casting, but (much as I hate to use the word) it seems like this is a
hack to get around the fact that the compiler isn't dealing with
static constructors as well as we'd like. I'd _really_ like to see
this fixed at the compiler level.

I understand and empathize with the sentiment, and I agree with most of the technical points at face value, save for a few details. But there are other things at stake.

Consider scope. Many arguments applicable to application code are not quite fit for the standard library. The stdlib is the connection between the compiler innards, the runtime innards, and the OS innards all meet, and the role of the stdlib is to provide nice abstractions to client code. Inside the stdlib it's entirely expected to find things like __traits most nobody heard of, casts, and other things that would be normally shunned in application code. I'd be more worried if there was no possibility to do what we need to do. The standard library is not a place to play it nice. We can't afford to say "well yeah everyone's binary is bloated and slower to start but we didn't like the cast that would have taken care of that".

As another matter, there is value in minimizing compulsive work during library startup. Consider for example this code in std.datetime:

    shared static this()
    {
        tzset();
        _localTime = new immutable(LocalTime)();
    }

This summons the garbage collector right off the bat, thus wiping off anyone's chance of compiling and linking without a GC - as many people seem to want to do. And that happens not to programs that import and use std.datetime, but to program using any part of the standard library that transitively imports std.datetime, even for the most innocuous uses, and even if they never, ever use _localtime! That one line essentially locks out 75% of the standard library to anyone wishing to ever avoid using the GC.

And honestly, I think that a far worse problem with static
constructors is circular dependencies. _That_ is something that
needs to be addressed with regards to static constructors. In general
at this point, it's looking like static constructors are turning out
to be a bit of a failure on some level, given the issues that we're
having because of them, and I think that we should fix the language
and/or compiler so that they _aren't_ a failure.

Here I totally disagree. The design is sound. The issues discussed here are entirely detail implementation artifacts.


Andrei

Reply via email to