[phobos] Proposal of StopWatch module

Andrei Alexandrescu andrei at erdani.com
Thu Aug 19 08:08:21 PDT 2010


On 08/18/2010 12:21 PM, SHOO wrote:
> (2010/08/18 20:18), Andrei Alexandrescu wrote:
>> Line 94 and others: you have a fair amount of @system methods that are
>> very @safe. Why mark them as @system? I think the entire module is @safe
>> in fact.
>>
>
> The reason is because it does a calculation to lose precision.
> I do not yet understand it about @safe/@trusted/@system well.

Their implementation is still under flux, but until then, we can't use 
them as a matter of preference. You may want to eliminate them entirely 
(or comment them out for now), or try to compile the entire module with 
@safe: at the top and report every compiler error as a bug. In 
particular, explicit casting from real to long is entirely safe and 
should not be an error.

> How about:
> T toSeconds(T=real)() if (isNumeric!T) {
> return (cast(T)value)/TICKSPERSEC;
> }
> @property alias toSeconds!real seconds;

I think that should work.

>> Line 318: return cast(int) (value - t.value);
>>
>
> No. value is long, it cannot cast to int.
> Check this:
>
> import std.stdio;
> void main()
> {
> long l1 = 0x1000000000000001L;
> long l2 = 0x4000000000000000L;
> writeln(l1); // 1152921504606846977
> writeln(l2); // 4611686018427387904
> writeln(l1 - l2); // -3458764513820540927
> writeln(cast(int)(l1 - l2)); // 1 <- !!!!
> }

Ha, thanks for the lesson.

>> Line 414: no need for @trusted, casting numbers is not unsafe.
>>
>
> Error: cast from const(long) to real not allowed in safe code

Compiler bug. I wonder whether const has anything to do with (shouldn't).

> The struct does not have a default constructer. This class must
> initialize it by all means in runtime. Because this class is a final
> class, nothing has override functions. This means that it can show the
> best performance by optimization.
> There are not advantages with using struct that sacrifice the secure
> initialization.

Oh, I missed that the class is final. Thanks. The sad reality is that 
classes will end up using dynamic allocation, which would cost much more 
than inserting one check in each of your four primitives.

> If there is even a default constructer, I will use a struct.
> I discussed even an argument of before, I really want the default
> constructer for struct.

I would like it too.

> It's my understanding that there are two reasons why a struct doesn't
> have a default constructer toward.
> Primarily, it can define as a variable without minding an initialization
> method in particular generic programming.
> Second, it ensure the initialization that resource assignment does not
> occur.
> See also: http://j.mp/9KGTFd

Unfortunately that won't help this case because we can't call system 
APIs during compilation.

> Cannot these be settled by making templates such as
> hasDefaultConstructor!T and canMakeStaticVariable!T ?

It's possible, but then we'd have structs impossible to clear. 
Alternatively, we should accept that cleared structs only have the .init 
values set for their members.

>> Line 489: if we go with a struct design, we should have a constructor
>> that "autostarts" a StopWatch, e.g.:
>>
>> auto myWatch = StopWatch(AutoStart.yes);
>>
>
> I examine.

Leaving aside all struct-related issues, I really think it's entirely 
reasonable to have the default constructor of a stopwatch leave it in 
the "not started" state. The C++ stopwatches we use at Facebook (which I 
think are inspired by Boost) need to be explicitly initialized like this:

Timer timer;
timer.start();

or like this:

Timer timer(true);

I didn't hear many protests about that setup. So why not do the same? By 
default there's no system call, so you can create an array of Stopwatch 
objects without incurring a large cost. Then you start them manually as 
you find fit.

> One question: Is there the reason using enum? Should not it be bool?
> auto myWatch = StopWatch(true);

Ha! Good question. Many people consider passing options as Booleans a 
poor design (the design of Facebook's Timer above notwithstanding :o)). 
This is because most of the time the reader must look up the manual to 
see what the meaning of "true" or "false" is. Just search std/ for the 
string ".yes" and you'll see for example that I don't use true and false 
for case sensitive, I use CaseSensitive.no or CaseSensitive.yes. It 
would be really difficult for a reader to figure what indexOf(str1, 
str2, true) is, but indexOf(str1, str2, CaseSensitive.yes) is very easy 
to understand.


Andrei


More information about the phobos mailing list