Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages

System.d

Go to the documentation of this file.
00001 /*******************************************************************************
00002 
00003         @file System.d
00004         
00005         Copyright (c) 2004 Kris Bell
00006         
00007         This software is provided 'as-is', without any express or implied
00008         warranty. In no event will the authors be held liable for damages
00009         of any kind arising from the use of this software.
00010         
00011         Permission is hereby granted to anyone to use this software for any 
00012         purpose, including commercial applications, and to alter it and/or 
00013         redistribute it freely, subject to the following restrictions:
00014         
00015         1. The origin of this software must not be misrepresented; you must 
00016            not claim that you wrote the original software. If you use this 
00017            software in a product, an acknowledgment within documentation of 
00018            said product would be appreciated but is not required.
00019 
00020         2. Altered source versions must be plainly marked as such, and must 
00021            not be misrepresented as being the original software.
00022 
00023         3. This notice may not be removed or altered from any distribution
00024            of the source.
00025 
00026         4. Derivative works are permitted, but they must carry this notice
00027            in full and credit the original source.
00028 
00029 
00030                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00031 
00032 
00033         @version        Initial version, March 2004      
00034         @author         Kris
00035 
00036 
00037 *******************************************************************************/
00038 
00039 module mango.base.System;
00040 
00041 private import std.c.time;
00042 
00043 private import std.thread;     
00044 
00045 /*******************************************************************************
00046 
00047         Stuff for sysError(), kindly provided by Regan Heath. 
00048 
00049 *******************************************************************************/
00050 
00051 version (Win32)
00052         {
00053         private import std.c.windows.windows;
00054 
00055         static uint FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100;
00056         static uint FORMAT_MESSAGE_IGNORE_INSERTS  = 0x00000200;
00057         static uint FORMAT_MESSAGE_FROM_STRING     = 0x00000400;
00058         static uint FORMAT_MESSAGE_FROM_HMODULE    = 0x00000800;
00059         static uint FORMAT_MESSAGE_FROM_SYSTEM     = 0x00001000;
00060         static uint FORMAT_MESSAGE_ARGUMENT_ARRAY  = 0x00002000;
00061         static uint FORMAT_MESSAGE_MAX_WIDTH_MASK  = 0x000000FF;
00062 
00063         WORD MAKELANGID(WORD p, WORD s)  { return (((cast(WORD)s) << 10) | cast(WORD)p); }
00064         WORD PRIMARYLANGID(WORD lgid)    { return (cast(WORD)lgid & 0x3ff); }
00065         WORD SUBLANGID(WORD lgid)        { return (cast(WORD)lgid >> 10); }
00066 
00067         alias HGLOBAL HLOCAL;
00068 
00069         static uint LANG_NEUTRAL = 0x00;
00070         static uint SUBLANG_DEFAULT = 0x01;
00071 
00072         extern (Windows) 
00073                {
00074                DWORD FormatMessageA (DWORD dwFlags,
00075                                      LPCVOID lpSource,
00076                                      DWORD dwMessageId,
00077                                      DWORD dwLanguageId,
00078                                      LPTSTR lpBuffer,
00079                                      DWORD nSize,
00080                                      LPCVOID args
00081                                      );
00082 
00083                HLOCAL LocalFree(HLOCAL hMem);
00084                int QueryPerformanceCounter (ulong *count);
00085                int QueryPerformanceFrequency (ulong *frequency);
00086 
00087                VOID Sleep (DWORD millisecs);
00088                }
00089         }
00090 
00091 version (Posix)
00092         {
00093         private import std.c.linux.linux;
00094 
00095         extern (C) char *strerror (int);
00096         extern (C) int strlen (char *);
00097         extern (C) int getErrno ();
00098         }
00099 
00100 /*******************************************************************************
00101 
00102         Ensure we're running in a known environment
00103 
00104 *******************************************************************************/
00105 
00106 static this()
00107 {
00108         version(Win32){}
00109         else
00110         version (Posix){}
00111         else
00112            throw new Exception ("Unsupported O/S environment (version is not Win32 or Unix).");               
00113 }
00114 
00115 
00116 /*******************************************************************************
00117 
00118         Some system-specific functionality that doesn't belong anywhere 
00119         else. This needs some further thought and refinement.
00120 
00121 *******************************************************************************/
00122 
00123 struct System
00124 {       
00125         private static uint     frequency;
00126         private static ulong    beginTime;
00127         private static ulong    beginCounter;
00128 
00129         /***********************************************************************
00130                 
00131                 Time interval multipliers. All Mango intervals are based
00132                 upon microseconds.
00133 
00134         ***********************************************************************/
00135 
00136         enum Interval   {
00137                         Microsec = 1, 
00138                         Millisec = 1000, 
00139                         Second   = 1_000_000, 
00140                         Minute   = 60_000_000
00141                         };
00142 
00143         /***********************************************************************
00144                 
00145                 Setup the timing information for later use. Note how much 
00146                 effort it takes to get epoch time in Win32 ...
00147 
00148         ***********************************************************************/
00149 
00150         static this ()
00151         {
00152                 version (Posix)       
00153                 {
00154                         timeval tv;
00155 
00156                         if (gettimeofday (&tv, null))
00157                             throw new Exception ("high-resolution timer is not available");
00158                         
00159                         beginTime = tv.tv_sec * 1000;
00160                 }
00161 
00162                 version (Win32)
00163                 {
00164                         SYSTEMTIME      sTime;
00165                         FILETIME        fTime;
00166 
00167                         GetSystemTime (&sTime);
00168                         SystemTimeToFileTime (&sTime, &fTime);
00169                         
00170                         ulong time1 = (cast(long) fTime.dwHighDateTime) << 32 | 
00171                                                   fTime.dwLowDateTime;
00172 
00173                         // first second of 1970 ...
00174                         sTime.wYear = 1969;
00175                         sTime.wMonth = 12;
00176                         sTime.wDayOfWeek = 3;
00177                         sTime.wDay = 31;
00178                         sTime.wHour = 23;
00179                         sTime.wMinute = 0;
00180                         sTime.wSecond = 0;
00181                         sTime.wMilliseconds = 0;
00182                         SystemTimeToFileTime (&sTime, &fTime);
00183 
00184                         ulong time2 = (cast(long) fTime.dwHighDateTime) << 32 | 
00185                                                   fTime.dwLowDateTime;
00186                         
00187                         beginTime = (time1 - time2) / 10_000;
00188 
00189 
00190                         ulong time;
00191                         ulong freq;
00192 
00193                         if (! QueryPerformanceFrequency (&freq))
00194                               throw new Exception ("high-resolution timer is not available");
00195                                
00196                         frequency = freq / 1000;
00197                         QueryPerformanceCounter (&time);
00198                         beginCounter = time / frequency;
00199                 }
00200         }
00201 
00202         /***********************************************************************
00203                 
00204                 Return the number of milliseconds since January 1st 1970
00205 
00206         ***********************************************************************/
00207 
00208         final static ulong getMillisecs ()
00209         {
00210                 version (Posix)       
00211                 {
00212                         timeval tv;
00213 
00214                         gettimeofday (&tv, null);
00215                         return ((cast(ulong) tv.tv_sec) * 1000 + tv.tv_usec / 1000);
00216                 }
00217 
00218                 version (Win32)
00219                 {
00220                         ulong time;
00221 
00222                         QueryPerformanceCounter (&time);
00223                         return ((time / frequency) - beginCounter) + beginTime;
00224                 }
00225         }
00226 
00227         /***********************************************************************
00228                 
00229                 The time this executable started (ms since Jan 1st 1970)
00230 
00231         ***********************************************************************/
00232 
00233         final static ulong getBeginTime ()
00234         {
00235                 return beginTime;
00236         }
00237 
00238         /***********************************************************************
00239         
00240                 Send this thread to sleep for a while. The time interval
00241                 is measured in microseconds. Specifying a period value of
00242                 uint.max will cause the calling thread to sleep forever.
00243 
00244         ***********************************************************************/
00245 
00246         final static void sleep (uint interval = uint.max)
00247         {
00248                 version (Posix)
00249                         {
00250                         do {
00251                            usleep (interval);
00252                            } while (interval == uint.max);
00253                         }
00254 
00255                 version (Win32)
00256                          Sleep (interval / 1000);
00257         }
00258 
00259         /***********************************************************************
00260               
00261                 Create a thread for the given delegate, and optionally start 
00262                 it up.
00263                   
00264         ***********************************************************************/
00265 
00266         final static Thread createThread (int delegate() dg, bool start = false)
00267         {
00268                 Thread t = new Thread (dg);
00269                 if (start)
00270                     t.start ();
00271                 return t;
00272         }
00273 
00274         /***********************************************************************
00275         
00276         ***********************************************************************/
00277 
00278         final static char[] error ()
00279         {
00280                 version (Win32)
00281                          return error (GetLastError);
00282                      else
00283                         return error (getErrno);
00284         }
00285 
00286         /***********************************************************************
00287         
00288         ***********************************************************************/
00289 
00290         final static char[] error (uint errcode)
00291         {
00292                 char[] text;
00293 
00294                 version (Win32)
00295                         {
00296                         DWORD  r;
00297                         LPVOID lpMsgBuf;                        
00298 
00299                         r = FormatMessageA ( 
00300                                 FORMAT_MESSAGE_ALLOCATE_BUFFER | 
00301                                 FORMAT_MESSAGE_FROM_SYSTEM | 
00302                                 FORMAT_MESSAGE_IGNORE_INSERTS,
00303                                 null,
00304                                 errcode,
00305                                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
00306                                 cast(LPTSTR)&lpMsgBuf,
00307                                 0,
00308                                 null);
00309 
00310                         /* Remove \r\n from error string */
00311                         if (r >= 2) r-= 2;
00312                         text = (cast(char *)lpMsgBuf)[0..r].dup;
00313                         LocalFree(cast(HLOCAL)lpMsgBuf);
00314                         }
00315                      else
00316                         {
00317                         uint  r;
00318                         char* pemsg;
00319 
00320                         pemsg = strerror(errcode);
00321                         r = strlen(pemsg);
00322 
00323                         /* Remove \r\n from error string */
00324                         if (pemsg[r-1] == '\n') r--;
00325                         if (pemsg[r-1] == '\r') r--;
00326                         text = pemsg[0..r].dup;
00327                         }
00328                 
00329                 return text;
00330         }
00331 }
00332 

Generated on Tue Jan 25 21:18:23 2005 for Mango by doxygen 1.3.6