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

Generated on Sat Apr 9 20:11:28 2005 for Mango by doxygen 1.3.6