0
|
1 // Written in the D programming language
|
|
2 // www.digitalmars.com/d/
|
|
3
|
|
4 /*
|
|
5 * The contents of this file are subject to the Mozilla Public License Version
|
|
6 * 1.1 (the "License"); you may not use this file except in compliance with
|
|
7 * the License. You may obtain a copy of the License at
|
|
8 * http://www.mozilla.org/MPL/
|
|
9 *
|
|
10 * Software distributed under the License is distributed on an "AS IS" basis,
|
|
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
12 * for the specific language governing rights and limitations under the
|
|
13 * License.
|
|
14 *
|
|
15 * The Original Code is the Dynamin library.
|
|
16 *
|
|
17 * The Initial Developer of the Original Code is Jordan Miner.
|
|
18 * Portions created by the Initial Developer are Copyright (C) 2006-2009
|
|
19 * the Initial Developer. All Rights Reserved.
|
|
20 *
|
|
21 * Contributor(s):
|
|
22 * Jordan Miner <jminer7@gmail.com>
|
|
23 *
|
|
24 */
|
|
25
|
|
26 module dynamin.core.environment;
|
|
27
|
|
28 import dynamin.all_core;
|
|
29 import dynamin.core_backend;
|
|
30
|
|
31 /**
|
|
32 * Contains static methods to access information about the computer the
|
|
33 * application is running on.
|
|
34 */
|
|
35 static class Environment {
|
|
36 static:
|
|
37 private:
|
|
38 mixin EnvironmentBackend;
|
|
39 public:
|
|
40 /**
|
|
41 * Returns the time in milliseconds since the program was started.
|
|
42 * On Windows XP, this time is updated every millisecond.
|
|
43 * On Linux, this time is usually updated every millisecond, but
|
|
44 * occasionally may take 5 to 10 milliseconds.
|
|
45 * This is the author's dream time function because
|
|
46 *
|
|
47 * $(OL
|
|
48 * $(LI It is accurate to 1 millisecond.)
|
|
49 * $(LI It works correctly on multiple core computers.)
|
|
50 * $(LI It is unaffected by changes to the system time.)
|
|
51 * $(LI It never wraps to zero.)
|
|
52 * )
|
|
53 *
|
|
54 * On my 1.3 GHz celeron, this function can be called about 480 times
|
|
55 * in one millisecond under Windows and about 380 times in one millisecond
|
|
56 * under Linux.
|
|
57 *
|
|
58 * TODO: make sure it works with multiple cores, although I'm sure it does
|
|
59 */
|
|
60 long runningTime() {
|
|
61 return backend_runningTime;
|
|
62 }
|
|
63 /**
|
|
64 * Returns the system time in milliseconds since January 1, 1970 UTC.
|
|
65 * On Windows XP, this time is only updated every 15.625 milliseconds.
|
|
66 *
|
|
67 * On my 1.3 GHz celeron, this function can be called about 12,000 times
|
|
68 * in one millisecond under Windows and about 460 times in one millisecond
|
|
69 * under Linux.
|
|
70 */
|
|
71 long systemTime() {
|
|
72 return backend_systemTime;
|
|
73 }
|
|
74 /**
|
|
75 * Gets the number of logical processors on this computer. A logical
|
|
76 * processor can either be a different physical processor or simply
|
|
77 * another core in the same processor. Even a single core hyper-threaded
|
|
78 * processor is considered to have two logical processors.
|
|
79 * Returns: the number of logical processors
|
|
80 */
|
|
81 int processorCount() {
|
|
82 return backend_processorCount;
|
|
83 }
|
|
84 /**
|
|
85 * The number returned by this method can be used to measure the
|
|
86 * time between two calls. This method uses the highest resolution
|
|
87 * timer available.
|
|
88 *
|
|
89 * On my 1.3 GHz celeron, this function can be called about 500 times
|
|
90 * in one millisecond under Windows.
|
|
91 *
|
|
92 * Returns: the current time in milliseconds
|
|
93 *
|
|
94 * Note: Under Windows, this is implemented using QueryPerformanceCounter().
|
|
95 * QueryPerformanceCounter() gets the time counter from the processor.
|
|
96 * On processors with multiple cores (such as an Althon X2 or a Core 2 Duo),
|
|
97 * the time counter for each core may be a few milliseconds different.
|
|
98 * (Microsoft's documentation says this is due to bugs in the BIOS or HAL.)
|
|
99 * Since QueryPerformanceCounter() can get the time from either core,
|
|
100 * the time between two calls made within the same millisecond can be off.
|
|
101 * For example, on my Althon X2 computer, the difference between cores
|
|
102 * is usually 60 ms. If two calls to QueryPerformanceCounter() are made
|
|
103 * in the same millisecond, there is a possiblity that the second one
|
|
104 * will return a time 60 ms smaller than the first.
|
|
105 * Under Linux, this is implemented using gettimeofday(), which has no
|
|
106 * problems with multiple cores and is accurate.
|
|
107 * One way to fix this inaccuracy is by only allowing the thread to
|
|
108 * use one processor. Another problem is that this time will run slightly
|
|
109 * faster or slower than the system time.
|
|
110 */
|
|
111 private long processorTime() {
|
|
112 return backend_processorTime;
|
|
113 }
|
|
114 }
|
|
115
|
|
116 unittest {
|
|
117 auto startTime = Environment.runningTime;
|
|
118 assert(startTime > 0);
|
|
119 auto time = startTime;
|
|
120 const SAMPLE = 50;
|
|
121 // makes sure that RunningTime does not go backwards
|
|
122 for(int i = 0; i < SAMPLE;) {
|
|
123 auto time2 = Environment.runningTime;
|
|
124 assert(time2 >= time);
|
|
125 if(time2 > time) {
|
|
126 time = time2;
|
|
127 ++i;
|
|
128 }
|
|
129 }
|
|
130 //printf("avg accuracy: %.1f ms\n", (time-startTime)/cast(float)SAMPLE);
|
|
131 }
|
|
132
|