/*---------------------------------------------------------------------- | NPT_System::SleepUntil +---------------------------------------------------------------------*/ NPT_Result NPT_System::SleepUntil(const NPT_TimeStamp& when) { struct timespec timeout; struct timeval now; int result; // get current time from system if (gettimeofday(&now, NULL)) { return NPT_FAILURE; } // setup timeout NPT_UInt64 limit = (NPT_UInt64)now.tv_sec*1000000000 + (NPT_UInt64)now.tv_usec*1000 + when.ToNanos(); timeout.tv_sec = (time_t)limit/1000000000; timeout.tv_nsec = limit%1000000000; // sleep do { result = pthread_cond_timedwait(&NPT_PosixSystem::System.m_SleepCondition, &NPT_PosixSystem::System.m_SleepMutex, &timeout); if (result == ETIMEDOUT) { return NPT_SUCCESS; } } while (result == EINTR); return NPT_FAILURE; }
/*---------------------------------------------------------------------- | NPT_Win32Thread::EntryPoint +---------------------------------------------------------------------*/ unsigned int __stdcall NPT_Win32Thread::EntryPoint(void* argument) { NPT_Win32Thread* thread = reinterpret_cast<NPT_Win32Thread*>(argument); NPT_LOG_FINER("thread in ======================="); // set random seed per thread NPT_TimeStamp now; NPT_System::GetCurrentTimeStamp(now); NPT_System::SetRandomSeed((NPT_UInt32)(now.ToNanos()) + ::GetCurrentThreadId()); thread->m_ThreadId = (DWORD)::GetCurrentThreadId(); // run the thread thread->Run(); // if the thread is detached, delete it if (thread->m_Detached) { delete thread->m_Delegator; } // done return 0; }
/*---------------------------------------------------------------------- | NPT_System::GetRandomInteger +---------------------------------------------------------------------*/ NPT_UInt32 NPT_System::GetRandomInteger() { static bool seeded = false; if (seeded == false) { NPT_TimeStamp now; GetCurrentTimeStamp(now); SetRandomSeed((NPT_UInt32)now.ToNanos()); seeded = true; } return rand(); }
/*---------------------------------------------------------------------- | NPT_DateTime::ChangeTimeZone +---------------------------------------------------------------------*/ NPT_Result NPT_DateTime::ChangeTimeZone(NPT_Int32 timezone) { if (timezone < -12*60 || timezone > 12*60) { return NPT_ERROR_OUT_OF_RANGE; } NPT_TimeStamp ts; NPT_Result result = ToTimeStamp(ts); if (NPT_FAILED(result)) return result; ts.SetNanos(ts.ToNanos()+(NPT_Int64)timezone*(NPT_Int64)60*(NPT_Int64)1000000000); result = FromTimeStamp(ts); m_TimeZone = timezone; return result; }
/*---------------------------------------------------------------------- | NPT_DateTime::FromTimeStamp +---------------------------------------------------------------------*/ NPT_Result NPT_DateTime::FromTimeStamp(const NPT_TimeStamp& ts, bool local) { // number of seconds from the epoch (positive or negative) NPT_Int64 seconds = ts.ToSeconds(); // check the range (we only allow up to 31 bits of negative range for seconds // in order to have the same lower bound as the 32-bit gmtime() function) if (seconds < 0 && (NPT_Int32)seconds != seconds) return NPT_ERROR_OUT_OF_RANGE; // adjust for the timezone if necessary NPT_Int32 timezone = 0; if (local) { timezone = GetLocalTimeZone(); seconds += timezone*60; } // adjust to the number of seconds since 1900 seconds += (NPT_Int64)NPT_SECONDS_PER_YEAR*70 + (NPT_Int64)(17*NPT_SECONDS_PER_DAY); // 17 leap year between 1900 and 1970 // compute the years since 1900, not adjusting for leap years NPT_UInt32 years_since_1900 = (NPT_UInt32)(seconds/NPT_SECONDS_PER_YEAR); // compute the number of seconds elapsed in the current year seconds -= (NPT_Int64)years_since_1900 * NPT_SECONDS_PER_YEAR; // adjust for leap years bool is_leap_year = false; NPT_UInt32 leap_years_since_1900 = ElapsedLeapYearsSince1900(years_since_1900+1900); if (seconds < (leap_years_since_1900 * NPT_SECONDS_PER_DAY)) { // not enough seconds in the current year to compensate, move one year back seconds += NPT_SECONDS_PER_YEAR; seconds -= leap_years_since_1900 * NPT_SECONDS_PER_DAY; --years_since_1900; if (NPT_TIME_YEAR_IS_LEAP(years_since_1900+1900) ) { seconds += NPT_SECONDS_PER_DAY; is_leap_year = true; } } else { seconds -= leap_years_since_1900 * NPT_SECONDS_PER_DAY; if (NPT_TIME_YEAR_IS_LEAP(years_since_1900+1900) ) { is_leap_year = true; } } // now we know the year m_Year = years_since_1900+1900; // compute the number of days since January 1 (0 - 365) NPT_UInt32 day_of_the_year = (NPT_UInt32)(seconds/NPT_SECONDS_PER_DAY); // compute the number of seconds in the current day seconds -= day_of_the_year * NPT_SECONDS_PER_DAY; // compute the number of months since January (0 - 11) and the day of month (1 - 31) */ const NPT_Int32* month_day = is_leap_year?NPT_TIME_MONTH_DAY_LEAP:NPT_TIME_MONTH_DAY; NPT_UInt32 month; for (month = 1; month_day[month] < (NPT_Int32)day_of_the_year ; month++) {} // now we know the month and day m_Month = month; m_Day = day_of_the_year - month_day[month-1]; // compute the number of hours since midnight (0 - 23), minutes after the hour // (0 - 59), seconds after the minute (0 - 59) and nanoseconds m_Hours = (NPT_Int32)seconds/3600; seconds -= m_Hours * 3600L; m_Minutes = (NPT_Int32)seconds / 60; m_Seconds = (NPT_Int32)seconds - m_Minutes * 60; m_NanoSeconds = (NPT_Int32)(ts.ToNanos()%1000000000); if (local) { m_TimeZone = timezone; } else { m_TimeZone = 0; } return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | TestPerformance +---------------------------------------------------------------------*/ static void TestPerformance() { for (unsigned int i=1; i<10000; i += 1000) { NPT_TimeStamp before; NPT_System::GetCurrentTimeStamp(before); for (unsigned int j=0; j<10; j++) { NPT_Map<NPT_String, NPT_String> map; for (unsigned int k=0; k<i; k++) { char key[64] = "blablabliblibloublou"; unsigned int run = NPT_System::GetRandomInteger()%8; for (unsigned int x=0; x<run; x++) { key[x] = 'A'+NPT_System::GetRandomInteger()%32; } map[key] = "hello"; } } NPT_TimeStamp after; NPT_System::GetCurrentTimeStamp(after); NPT_UInt64 duration = (after.ToNanos()-before.ToNanos())/10; printf("LinearMap insert: %d\t%d ns\t\t%d ns/item\n", i, (NPT_UInt32)duration, (NPT_UInt32)(duration/i)); } for (unsigned int i=1; i<10000; i += 1000) { NPT_TimeStamp before; NPT_System::GetCurrentTimeStamp(before); for (unsigned int j=0; j<100; j++) { NPT_HashMap<NPT_String, NPT_String> map; for (unsigned int k=0; k<i; k++) { char key[64] = "blablabliblibloublou"; unsigned int run = NPT_System::GetRandomInteger()%8; for (unsigned int x=0; x<run; x++) { key[x] = 'A'+NPT_System::GetRandomInteger()%32; } map[key] = "hello"; } } NPT_TimeStamp after; NPT_System::GetCurrentTimeStamp(after); NPT_UInt64 duration = (after.ToNanos()-before.ToNanos())/100; printf("HashMap insert: %d\t%d ns\t\t%d ns/item\n", i, (NPT_UInt32)duration, (NPT_UInt32)(duration/i)); } for (unsigned int i=1; i<10000; i += 1000) { NPT_TimeStamp before; NPT_System::GetCurrentTimeStamp(before); for (unsigned int j=0; j<100; j++) { NPT_HashMap<NPT_String, NPT_String> map; for (unsigned int k=0; k<i; k++) { char key[64] = "blablabliblibloublou"; unsigned int run = NPT_System::GetRandomInteger()%8; for (unsigned int x=0; x<run; x++) { key[x] = 'A'+NPT_System::GetRandomInteger()%32; } map[key] = "hello"; } for (unsigned int k=0; k<i; k++) { char key[64] = "blablabliblibloublou"; unsigned int run = NPT_System::GetRandomInteger()%8; for (unsigned int x=0; x<run; x++) { key[x] = 'A'+NPT_System::GetRandomInteger()%32; } map.Erase(key); } } NPT_TimeStamp after; NPT_System::GetCurrentTimeStamp(after); NPT_UInt64 duration = (after.ToNanos()-before.ToNanos())/100; printf("HashMap insert+erase: %d\t%d ns\t\t%d ns/item\n", i, (NPT_UInt32)duration, (NPT_UInt32)(duration/i)); } }