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 
00027                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00028 
00029 
00030         @version        Initial version, March 2004      
00031         @author         Kris
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         Stuff for sysError(), kindly provided by Regan Heath. 
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         Ensure we're running in a known environment
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         Some system-specific functionality that doesn't belong anywhere 
00116         else. This needs some further thought and refinement.
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                 Time interval multipliers. All Mango intervals are based
00129                 upon microseconds.
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                 Setup the timing information for later use. Note how much 
00143                 effort it takes to get epoch time in Win32 ...
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                         // first second of 1970 ...
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                 Return the number of milliseconds since January 1st 1970
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                 The time this executable started (ms since Jan 1st 1970)
00227 
00228         ***********************************************************************/
00229 
00230         final static ulong getBeginTime ()
00231         {
00232                 return beginTime;
00233         }
00234 
00235         /***********************************************************************
00236         
00237                 Send this thread to sleep for a while. The time interval
00238                 is measured in microseconds. Specifying a period value of
00239                 uint.max will cause the calling thread to sleep forever.
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                 Create a thread for the given delegate, and optionally start 
00259                 it up.
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), // Default language
00303                                 cast(LPTSTR)&lpMsgBuf,
00304                                 0,
00305                                 null);
00306 
00307                         /* Remove \r\n from error string */
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                         /* Remove \r\n from error string */
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 

Generated on Sun Nov 7 19:06:53 2004 for Mango by doxygen 1.3.6