00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 module mango.base.System;
00037
00038 private import std.c.time;
00039
00040 private import std.thread;
00041
00042
00043
00044
00045
00046
00047
00048 version (Win32)
00049 {
00050 private import std.c.windows.windows;
00051
00052 static uint FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100;
00053 static uint FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200;
00054 static uint FORMAT_MESSAGE_FROM_STRING = 0x00000400;
00055 static uint FORMAT_MESSAGE_FROM_HMODULE = 0x00000800;
00056 static uint FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;
00057 static uint FORMAT_MESSAGE_ARGUMENT_ARRAY = 0x00002000;
00058 static uint FORMAT_MESSAGE_MAX_WIDTH_MASK = 0x000000FF;
00059
00060 WORD MAKELANGID(WORD p, WORD s) { return (((cast(WORD)s) << 10) | cast(WORD)p); }
00061 WORD PRIMARYLANGID(WORD lgid) { return (cast(WORD)lgid & 0x3ff); }
00062 WORD SUBLANGID(WORD lgid) { return (cast(WORD)lgid >> 10); }
00063
00064 alias HGLOBAL HLOCAL;
00065
00066 static uint LANG_NEUTRAL = 0x00;
00067 static uint SUBLANG_DEFAULT = 0x01;
00068
00069 extern (Windows)
00070 {
00071 DWORD FormatMessageA (DWORD dwFlags,
00072 LPCVOID lpSource,
00073 DWORD dwMessageId,
00074 DWORD dwLanguageId,
00075 LPTSTR lpBuffer,
00076 DWORD nSize,
00077 LPCVOID args
00078 );
00079
00080 HLOCAL LocalFree(HLOCAL hMem);
00081 int QueryPerformanceCounter (ulong *count);
00082 int QueryPerformanceFrequency (ulong *frequency);
00083
00084 VOID Sleep (DWORD millisecs);
00085 }
00086 }
00087
00088 version (linux)
00089 {
00090 private import std.c.linux.linux;
00091
00092 extern (C) char *strerror (int);
00093 extern (C) int strlen (char *);
00094 extern (C) int getErrno ();
00095 }
00096
00097
00098
00099
00100
00101
00102
00103 static this()
00104 {
00105 version(Win32){}
00106 else
00107 version(linux){}
00108 else
00109 throw new Exception ("Unsupported O/S environment (version is not Win32 or linux).");
00110 }
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120 struct System
00121 {
00122 private static uint frequency;
00123 private static ulong beginTime;
00124 private static ulong beginCounter;
00125
00126
00127
00128
00129
00130
00131
00132
00133 enum Interval {
00134 Microsec = 1,
00135 Millisec = 1000,
00136 Second = 1_000_000,
00137 Minute = 60_000_000
00138 };
00139
00140
00141
00142
00143
00144
00145
00146
00147 static this ()
00148 {
00149 version (linux)
00150 {
00151 timeval tv;
00152
00153 if (gettimeofday (&tv, null))
00154 throw new Exception ("high-resolution timer is not available");
00155
00156 beginTime = tv.tv_sec * 1000;
00157 }
00158
00159 version (Win32)
00160 {
00161 SYSTEMTIME sTime;
00162 FILETIME fTime;
00163
00164 GetSystemTime (&sTime);
00165 SystemTimeToFileTime (&sTime, &fTime);
00166
00167 ulong time1 = (cast(long) fTime.dwHighDateTime) << 32 |
00168 fTime.dwLowDateTime;
00169
00170
00171 sTime.wYear = 1969;
00172 sTime.wMonth = 12;
00173 sTime.wDayOfWeek = 3;
00174 sTime.wDay = 31;
00175 sTime.wHour = 23;
00176 sTime.wMinute = 0;
00177 sTime.wSecond = 0;
00178 sTime.wMilliseconds = 0;
00179 SystemTimeToFileTime (&sTime, &fTime);
00180
00181 ulong time2 = (cast(long) fTime.dwHighDateTime) << 32 |
00182 fTime.dwLowDateTime;
00183
00184 beginTime = (time1 - time2) / 10_000;
00185
00186
00187 ulong time;
00188 ulong freq;
00189
00190 if (! QueryPerformanceFrequency (&freq))
00191 throw new Exception ("high-resolution timer is not available");
00192
00193 frequency = freq / 1000;
00194 QueryPerformanceCounter (&time);
00195 beginCounter = time / frequency;
00196 }
00197 }
00198
00199
00200
00201
00202
00203
00204
00205 final static ulong getMillisecs ()
00206 {
00207 version (linux)
00208 {
00209 timeval tv;
00210
00211 gettimeofday (&tv, null);
00212 return ((cast(ulong) tv.tv_sec) * 1000 + tv.tv_usec / 1000);
00213 }
00214
00215 version (Win32)
00216 {
00217 ulong time;
00218
00219 QueryPerformanceCounter (&time);
00220 return ((time / frequency) - beginCounter) + beginTime;
00221 }
00222 }
00223
00224
00225
00226
00227
00228
00229
00230 final static ulong getBeginTime ()
00231 {
00232 return beginTime;
00233 }
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243 final static void sleep (uint interval = uint.max)
00244 {
00245 version (linux)
00246 {
00247 do {
00248 usleep (interval);
00249 } while (interval == uint.max);
00250 }
00251
00252 version (Win32)
00253 Sleep (interval);
00254 }
00255
00256
00257
00258
00259
00260
00261
00262
00263 final static Thread createThread (int delegate() dg, bool start = false)
00264 {
00265 Thread t = new Thread (dg);
00266 if (start)
00267 t.start ();
00268 return t;
00269 }
00270
00271
00272
00273
00274
00275 final static char[] error ()
00276 {
00277 version (Win32)
00278 return error (GetLastError);
00279 else
00280 return error (getErrno);
00281 }
00282
00283
00284
00285
00286
00287 final static char[] error (uint errcode)
00288 {
00289 char[] text;
00290
00291 version (Win32)
00292 {
00293 DWORD r;
00294 LPVOID lpMsgBuf;
00295
00296 r = FormatMessageA (
00297 FORMAT_MESSAGE_ALLOCATE_BUFFER |
00298 FORMAT_MESSAGE_FROM_SYSTEM |
00299 FORMAT_MESSAGE_IGNORE_INSERTS,
00300 null,
00301 errcode,
00302 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
00303 cast(LPTSTR)&lpMsgBuf,
00304 0,
00305 null);
00306
00307
00308 if (r >= 2) r-= 2;
00309 text = (cast(char *)lpMsgBuf)[0..r].dup;
00310 LocalFree(cast(HLOCAL)lpMsgBuf);
00311 }
00312 else
00313 {
00314 uint r;
00315 char* pemsg;
00316
00317 pemsg = strerror(errcode);
00318 r = strlen(pemsg);
00319
00320
00321 if (pemsg[r-1] == '\n') r--;
00322 if (pemsg[r-1] == '\r') r--;
00323 text = pemsg[0..r].dup;
00324 }
00325
00326 return text;
00327 }
00328 }
00329