Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c++ > #87220 > unrolled thread
| Started by | Lynn McGuire <lynnmcguire5@gmail.com> |
|---|---|
| First post | 2022-11-03 20:14 -0500 |
| Last post | 2022-11-20 21:30 +0000 |
| Articles | 19 on this page of 39 — 14 participants |
Back to article view | Back to comp.lang.c++
what is the best way to get microseconds of time on Windows in C or C++ ? Lynn McGuire <lynnmcguire5@gmail.com> - 2022-11-03 20:14 -0500
Re: what is the best way to get microseconds of time on Windows in C or C++ ? Lynn McGuire <lynnmcguire5@gmail.com> - 2022-11-04 00:06 -0500
Re: what is the best way to get microseconds of time on Windows in C or C++ ? Christian Gollwitzer <auriocus@gmx.de> - 2022-11-04 08:03 +0100
Re: what is the best way to get microseconds of time on Windows in C or C++ ? Lynn McGuire <lynnmcguire5@gmail.com> - 2022-11-04 14:32 -0500
Re: what is the best way to get microseconds of time on Windows in C or C++ ? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2022-11-04 09:07 -0700
Re: what is the best way to get microseconds of time on Windows in C or C++ ? Lynn McGuire <lynnmcguire5@gmail.com> - 2022-11-04 14:33 -0500
Re: what is the best way to get microseconds of time on Windows in C or C++ ? Opus <ifonly@youknew.org> - 2022-11-06 20:53 +0100
Re: what is the best way to get microseconds of time on Windows in C or C++ ? Michael S <already5chosen@yahoo.com> - 2022-11-06 14:30 -0800
Re: what is the best way to get microseconds of time on Windows in C or C++ ? "Alf P. Steinbach" <alf.p.steinbach@gmail.com> - 2022-11-07 07:48 +0100
Re: what is the best way to get microseconds of time on Windows in C or C++ ? Michael S <already5chosen@yahoo.com> - 2022-11-07 04:11 -0800
Re: what is the best way to get microseconds of time on Windows in C or C++ ? "Alf P. Steinbach" <alf.p.steinbach@gmail.com> - 2022-11-08 18:30 +0100
Re: what is the best way to get microseconds of time on Windows in C or C++ ? Michael S <already5chosen@yahoo.com> - 2022-11-08 15:37 -0800
Re: what is the best way to get microseconds of time on Windows in C or C++ ? Öö Tiib <ootiib@hot.ee> - 2022-11-09 06:14 -0800
Re: what is the best way to get microseconds of time on Windows in C or C++ ? Michael S <already5chosen@yahoo.com> - 2022-11-12 16:21 -0800
Re: what is the best way to get microseconds of time on Windows in C or C++ ? Juha Nieminen <nospam@thanks.invalid> - 2022-11-04 07:35 +0000
Re: what is the best way to get microseconds of time on Windows in C or C++ ? Lynn McGuire <lynnmcguire5@gmail.com> - 2022-11-04 14:24 -0500
Re: what is the best way to get microseconds of time on Windows in C or C++ ? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2022-11-04 19:50 +0000
Re: what is the best way to get microseconds of time on Windows in C or C++ ? Lynn McGuire <lynnmcguire5@gmail.com> - 2022-11-04 15:16 -0500
Re: what is the best way to get microseconds of time on Windows in C or C++ ? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2022-11-04 15:05 -0700
Re: what is the best way to get microseconds of time on Windows in C or C++ ? Lynn McGuire <lynnmcguire5@gmail.com> - 2022-11-04 17:35 -0500
Re: what is the best way to get microseconds of time on Windows in C or C++ ? "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2022-11-04 15:56 -0700
Re: what is the best way to get microseconds of time on Windows in C or C++ ? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2022-11-04 16:15 -0700
Re: what is the best way to get microseconds of time on Windows in C or C++ ? Michael S <already5chosen@yahoo.com> - 2022-11-06 14:41 -0800
Re: what is the best way to get microseconds of time on Windows in C or C++ ? scott@slp53.sl.home (Scott Lurndal) - 2022-11-07 14:39 +0000
Re: what is the best way to get microseconds of time on Windows in C or C++ ? Michael S <already5chosen@yahoo.com> - 2022-11-07 11:03 -0800
Re: what is the best way to get microseconds of time on Windows in C or C++ ? Lynn McGuire <lynnmcguire5@gmail.com> - 2022-11-07 23:26 -0600
Re: what is the best way to get microseconds of time on Windows in C or C++ ? Öö Tiib <ootiib@hot.ee> - 2022-11-04 01:23 -0700
Re: what is the best way to get microseconds of time on Windows in C or C++ ? Juha Nieminen <nospam@thanks.invalid> - 2022-11-07 07:20 +0000
Re: what is the best way to get microseconds of time on Windows in C or C++ ? Öö Tiib <ootiib@hot.ee> - 2022-11-07 07:11 -0800
Re: what is the best way to get microseconds of time on Windows in C or C++ ? Michael S <already5chosen@yahoo.com> - 2022-11-04 03:12 -0700
Re: what is the best way to get microseconds of time on Windows in C or C++ ? Lynn McGuire <lynnmcguire5@gmail.com> - 2022-11-04 14:35 -0500
Re: what is the best way to get microseconds of time on Windows in C or C++ ? scott@slp53.sl.home (Scott Lurndal) - 2022-11-04 13:44 +0000
Re: what is the best way to get microseconds of time on Windows in C or C++ ? Lynn McGuire <lynnmcguire5@gmail.com> - 2022-11-04 14:34 -0500
Re: what is the best way to get microseconds of time on Windows in C or C++ ? Lynn McGuire <lynnmcguire5@gmail.com> - 2022-11-14 16:58 -0600
Re: what is the best way to get microseconds of time on Windows in C or C++ ? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2022-11-14 17:36 -0800
Re: what is the best way to get microseconds of time on Windows in C or C++ ? Lynn McGuire <lynnmcguire5@gmail.com> - 2022-11-15 17:26 -0600
Re: what is the best way to get microseconds of time on Windows in C or C++ ? Andreas <nospam@gmx.de> - 2022-11-16 13:15 +0100
Re: what is the best way to get microseconds of time on Windows in C or C++ ? Bonita Montero <Bonita.Montero@gmail.com> - 2022-11-04 20:49 +0100
Re: what is the best way to get microseconds of time on Windows in C or C++ ? Manu Raju <MR@invalid.invalid> - 2022-11-20 21:30 +0000
Page 2 of 2 — ← Prev page 1 [2]
| From | "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> |
|---|---|
| Date | 2022-11-04 15:56 -0700 |
| Message-ID | <tk45ai$22881$1@dont-email.me> |
| In reply to | #87247 |
On 11/4/2022 3:35 PM, Lynn McGuire wrote: > On 11/4/2022 5:05 PM, Keith Thompson wrote: >> Lynn McGuire <lynnmcguire5@gmail.com> writes: >>> On 11/4/2022 2:35 AM, Juha Nieminen wrote: >>>> In comp.lang.c++ Lynn McGuire <lynnmcguire5@gmail.com> wrote: >>>>> What is the best way to get microseconds of time on Windows in C or >>>>> C++ >>>> It's a bit unclear whether you mean "time in microseconds units" or >>>> "time >>>> at the microseconds resolution". >>>> Because the latter may not be even possible (portable or not). Just >>>> because >>>> some time function returns time "in microseconds" that doesn't mean >>>> that it >>>> uses microsecond resolution (in other words, the value it returns >>>> may well >>>> change at longer intervals than every microsecond; probably >>>> *significantly* >>>> longer intervals). >>>> It is possible to get some kind of timing at the CPU clock cycle >>>> interval >>>> (in most modern CPUs, at least), which is about as accurate as you can >>>> possibly get, but I don't know if there are eg. some system >>>> functions that >>>> will return elapsed clock cycles converted into the equivalent >>>> amount of >>>> microseconds. >>> >>> Get time at the microseconds resolution. My calculation engine >>> creates a bunch of temporary files and I use the time to create unique >>> names for those temporary files. Seconds should be good enough for >>> uniqueness but I like adding microseconds as a guarantee. Something >>> like >>> uniquac1.out.009.20181972.20220912 >> >> An alternative is to keep a counter, incremented for each generated file >> name, and append it to the file name, perhaps resetting to 0 when the >> seconds count advances. If your only requirement is uniqueness, that >> should be good enough. >> >> Digression: I remember an implementation of gettimeofday() that did >> something like that (on SunOS, maybe?). The system clock had a >> resolution of 0.01 second, so the value of tv_usec on successive calls >> might be: >> 420000 >> 420001 >> 420002 >> 430000 >> 430001 >> 430002 >> ... >> I don't remember whether the implicit counter was per-process or >> system-wide. > > The problem is multiple instances of the same program creating the same > name files. Prepend the file names with the PID? Something to make it unique. Perhaps a SHA2-HMAC or something.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2022-11-04 16:15 -0700 |
| Message-ID | <87tu3el3ai.fsf@nosuchdomain.example.com> |
| In reply to | #87247 |
Lynn McGuire <lynnmcguire5@gmail.com> writes:
> On 11/4/2022 5:05 PM, Keith Thompson wrote:
>> Lynn McGuire <lynnmcguire5@gmail.com> writes:
>>> On 11/4/2022 2:35 AM, Juha Nieminen wrote:
>>>> In comp.lang.c++ Lynn McGuire <lynnmcguire5@gmail.com> wrote:
>>>>> What is the best way to get microseconds of time on Windows in C or C++
>>>> It's a bit unclear whether you mean "time in microseconds units" or
>>>> "time
>>>> at the microseconds resolution".
>>>> Because the latter may not be even possible (portable or not). Just
>>>> because
>>>> some time function returns time "in microseconds" that doesn't mean that it
>>>> uses microsecond resolution (in other words, the value it returns may well
>>>> change at longer intervals than every microsecond; probably *significantly*
>>>> longer intervals).
>>>> It is possible to get some kind of timing at the CPU clock cycle
>>>> interval
>>>> (in most modern CPUs, at least), which is about as accurate as you can
>>>> possibly get, but I don't know if there are eg. some system functions that
>>>> will return elapsed clock cycles converted into the equivalent amount of
>>>> microseconds.
>>>
>>> Get time at the microseconds resolution. My calculation engine
>>> creates a bunch of temporary files and I use the time to create unique
>>> names for those temporary files. Seconds should be good enough for
>>> uniqueness but I like adding microseconds as a guarantee. Something
>>> like
>>> uniquac1.out.009.20181972.20220912
>> An alternative is to keep a counter, incremented for each generated
>> file
>> name, and append it to the file name, perhaps resetting to 0 when the
>> seconds count advances. If your only requirement is uniqueness, that
>> should be good enough.
>> Digression: I remember an implementation of gettimeofday() that did
>> something like that (on SunOS, maybe?). The system clock had a
>> resolution of 0.01 second, so the value of tv_usec on successive calls
>> might be:
>> 420000
>> 420001
>> 420002
>> 430000
>> 430001
>> 430002
>> ...
>> I don't remember whether the implicit counter was per-process or
>> system-wide.
>
> The problem is multiple instances of the same program creating the
> same name files.
You could incorporate the process id into the file name.
There's no truly portable way to do that, but one solution for POSIX and
another for Windows is likely to be good enough.
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for XCOM Labs
void Void(void) { Void(); } /* The recursive call of the void */
[toc] | [prev] | [next] | [standalone]
| From | Michael S <already5chosen@yahoo.com> |
|---|---|
| Date | 2022-11-06 14:41 -0800 |
| Message-ID | <da0de836-c587-4f53-a4cc-05d05a916bean@googlegroups.com> |
| In reply to | #87247 |
On Saturday, November 5, 2022 at 12:35:30 AM UTC+2, Lynn McGuire wrote: > On 11/4/2022 5:05 PM, Keith Thompson wrote: > > Lynn McGuire <lynnmc...@gmail.com> writes: > >> On 11/4/2022 2:35 AM, Juha Nieminen wrote: > >>> In comp.lang.c++ Lynn McGuire <lynnmc...@gmail.com> wrote: > >>>> What is the best way to get microseconds of time on Windows in C or C++ > >>> It's a bit unclear whether you mean "time in microseconds units" or > >>> "time > >>> at the microseconds resolution". > >>> Because the latter may not be even possible (portable or not). Just > >>> because > >>> some time function returns time "in microseconds" that doesn't mean that it > >>> uses microsecond resolution (in other words, the value it returns may well > >>> change at longer intervals than every microsecond; probably *significantly* > >>> longer intervals). > >>> It is possible to get some kind of timing at the CPU clock cycle > >>> interval > >>> (in most modern CPUs, at least), which is about as accurate as you can > >>> possibly get, but I don't know if there are eg. some system functions that > >>> will return elapsed clock cycles converted into the equivalent amount of > >>> microseconds. > >> > >> Get time at the microseconds resolution. My calculation engine > >> creates a bunch of temporary files and I use the time to create unique > >> names for those temporary files. Seconds should be good enough for > >> uniqueness but I like adding microseconds as a guarantee. Something > >> like > >> uniquac1.out.009.20181972.20220912 > > > > An alternative is to keep a counter, incremented for each generated file > > name, and append it to the file name, perhaps resetting to 0 when the > > seconds count advances. If your only requirement is uniqueness, that > > should be good enough. > > > > Digression: I remember an implementation of gettimeofday() that did > > something like that (on SunOS, maybe?). The system clock had a > > resolution of 0.01 second, so the value of tv_usec on successive calls > > might be: > > 420000 > > 420001 > > 420002 > > 430000 > > 430001 > > 430002 > > ... > > I don't remember whether the implicit counter was per-process or > > system-wide. > The problem is multiple instances of the same program creating the same > name files. > > Lynn If you decided to keep ideas of your old code* then using __rdtsc() is hand down better than anything else. Of course, don't convert result of __rdtsc() to microseconds, use the number in its entirety. This way you still would not get 100% guarantee against name conflicts between multiple instances, but probability of conflict will be 3-6 orders of magnitude lower than any other time-based method. ------------ * - IMHO, you should not. Posters here suggested at least two better solutions and can suggest more. BTW, are you sure that with modern memory capacity you still need temporary files at all?
[toc] | [prev] | [next] | [standalone]
| From | scott@slp53.sl.home (Scott Lurndal) |
|---|---|
| Date | 2022-11-07 14:39 +0000 |
| Message-ID | <xM8aL.1644$kCk6.909@fx05.iad> |
| In reply to | #87272 |
Michael S <already5chosen@yahoo.com> writes: >On Saturday, November 5, 2022 at 12:35:30 AM UTC+2, Lynn McGuire wrote: >> On 11/4/2022 5:05 PM, Keith Thompson wrote: >> > Lynn McGuire <lynnmc...@gmail.com> writes: >> >> On 11/4/2022 2:35 AM, Juha Nieminen wrote: >> >>> In comp.lang.c++ Lynn McGuire <lynnmc...@gmail.com> wrote: >> >>>> What is the best way to get microseconds of time on Windows in C or C++ >> >>> It's a bit unclear whether you mean "time in microseconds units" or >> >>> "time >> >>> at the microseconds resolution". >> >>> Because the latter may not be even possible (portable or not). Just >> >>> because >> >>> some time function returns time "in microseconds" that doesn't mean that it >> >>> uses microsecond resolution (in other words, the value it returns may well >> >>> change at longer intervals than every microsecond; probably *significantly* >> >>> longer intervals). >> >>> It is possible to get some kind of timing at the CPU clock cycle >> >>> interval >> >>> (in most modern CPUs, at least), which is about as accurate as you can >> >>> possibly get, but I don't know if there are eg. some system functions that >> >>> will return elapsed clock cycles converted into the equivalent amount of >> >>> microseconds. >> >> >> >> Get time at the microseconds resolution. My calculation engine >> >> creates a bunch of temporary files and I use the time to create unique >> >> names for those temporary files. Seconds should be good enough for >> >> uniqueness but I like adding microseconds as a guarantee. Something >> >> like >> >> uniquac1.out.009.20181972.20220912 >> > >> > An alternative is to keep a counter, incremented for each generated file >> > name, and append it to the file name, perhaps resetting to 0 when the >> > seconds count advances. If your only requirement is uniqueness, that >> > should be good enough. >> > >> > Digression: I remember an implementation of gettimeofday() that did >> > something like that (on SunOS, maybe?). The system clock had a >> > resolution of 0.01 second, so the value of tv_usec on successive calls >> > might be: >> > 420000 >> > 420001 >> > 420002 >> > 430000 >> > 430001 >> > 430002 >> > ... >> > I don't remember whether the implicit counter was per-process or >> > system-wide. >> The problem is multiple instances of the same program creating the same >> name files. >> >> Lynn > >If you decided to keep ideas of your old code* then using __rdtsc() is hand >down better than anything else. Of course, don't convert result of >__rdtsc() to microseconds, use the number in its entirety. This way you still >would not get 100% guarantee against name conflicts between multiple >instances, but probability of conflict will be 3-6 orders of magnitude lower >than any other time-based method. If you are using the RDTSC instruction, be aware that the value returned may vary based on the current clock speed; there are some chips where the frequency of the clock RDTSC returns is invariant, others not so much. https://stackoverflow.com/questions/4509727/how-to-detect-if-rdtsc-returns-a-constant-rate-counter-value
[toc] | [prev] | [next] | [standalone]
| From | Michael S <already5chosen@yahoo.com> |
|---|---|
| Date | 2022-11-07 11:03 -0800 |
| Message-ID | <49054d09-8d73-4c82-bcd7-a6f77f5c620bn@googlegroups.com> |
| In reply to | #87277 |
On Monday, November 7, 2022 at 4:39:42 PM UTC+2, Scott Lurndal wrote: > Michael S <already...@yahoo.com> writes: > >On Saturday, November 5, 2022 at 12:35:30 AM UTC+2, Lynn McGuire wrote: > >> On 11/4/2022 5:05 PM, Keith Thompson wrote: > >> > Lynn McGuire <lynnmc...@gmail.com> writes: > >> >> On 11/4/2022 2:35 AM, Juha Nieminen wrote: > >> >>> In comp.lang.c++ Lynn McGuire <lynnmc...@gmail.com> wrote: > >> >>>> What is the best way to get microseconds of time on Windows in C or C++ > >> >>> It's a bit unclear whether you mean "time in microseconds units" or > >> >>> "time > >> >>> at the microseconds resolution". > >> >>> Because the latter may not be even possible (portable or not). Just > >> >>> because > >> >>> some time function returns time "in microseconds" that doesn't mean that it > >> >>> uses microsecond resolution (in other words, the value it returns may well > >> >>> change at longer intervals than every microsecond; probably *significantly* > >> >>> longer intervals). > >> >>> It is possible to get some kind of timing at the CPU clock cycle > >> >>> interval > >> >>> (in most modern CPUs, at least), which is about as accurate as you can > >> >>> possibly get, but I don't know if there are eg. some system functions that > >> >>> will return elapsed clock cycles converted into the equivalent amount of > >> >>> microseconds. > >> >> > >> >> Get time at the microseconds resolution. My calculation engine > >> >> creates a bunch of temporary files and I use the time to create unique > >> >> names for those temporary files. Seconds should be good enough for > >> >> uniqueness but I like adding microseconds as a guarantee. Something > >> >> like > >> >> uniquac1.out.009.20181972.20220912 > >> > > >> > An alternative is to keep a counter, incremented for each generated file > >> > name, and append it to the file name, perhaps resetting to 0 when the > >> > seconds count advances. If your only requirement is uniqueness, that > >> > should be good enough. > >> > > >> > Digression: I remember an implementation of gettimeofday() that did > >> > something like that (on SunOS, maybe?). The system clock had a > >> > resolution of 0.01 second, so the value of tv_usec on successive calls > >> > might be: > >> > 420000 > >> > 420001 > >> > 420002 > >> > 430000 > >> > 430001 > >> > 430002 > >> > ... > >> > I don't remember whether the implicit counter was per-process or > >> > system-wide. > >> The problem is multiple instances of the same program creating the same > >> name files. > >> > >> Lynn > > > >If you decided to keep ideas of your old code* then using __rdtsc() is hand > >down better than anything else. Of course, don't convert result of > >__rdtsc() to microseconds, use the number in its entirety. This way you still > >would not get 100% guarantee against name conflicts between multiple > >instances, but probability of conflict will be 3-6 orders of magnitude lower > >than any other time-based method. > If you are using the RDTSC instruction, be aware that the value returned > may vary based on the current clock speed; there are some chips where the > frequency of the clock RDTSC returns is invariant, others not so much. > > https://stackoverflow.com/questions/4509727/how-to-detect-if-rdtsc-returns-a-constant-rate-counter-value OP appears to wants unique number rather than real microseconds. In today's x86 word RDTSC is based of "official frequency" of given CPU model and is not related to actual current clock speed. It was not universally so up until mid-00s, but we are in 2022. But all that irrelevant for specific use case.
[toc] | [prev] | [next] | [standalone]
| From | Lynn McGuire <lynnmcguire5@gmail.com> |
|---|---|
| Date | 2022-11-07 23:26 -0600 |
| Message-ID | <tkcpb3$3rhh5$1@dont-email.me> |
| In reply to | #87272 |
On 11/6/2022 4:41 PM, Michael S wrote: > On Saturday, November 5, 2022 at 12:35:30 AM UTC+2, Lynn McGuire wrote: >> On 11/4/2022 5:05 PM, Keith Thompson wrote: >>> Lynn McGuire <lynnmc...@gmail.com> writes: >>>> On 11/4/2022 2:35 AM, Juha Nieminen wrote: >>>>> In comp.lang.c++ Lynn McGuire <lynnmc...@gmail.com> wrote: >>>>>> What is the best way to get microseconds of time on Windows in C or C++ >>>>> It's a bit unclear whether you mean "time in microseconds units" or >>>>> "time >>>>> at the microseconds resolution". >>>>> Because the latter may not be even possible (portable or not). Just >>>>> because >>>>> some time function returns time "in microseconds" that doesn't mean that it >>>>> uses microsecond resolution (in other words, the value it returns may well >>>>> change at longer intervals than every microsecond; probably *significantly* >>>>> longer intervals). >>>>> It is possible to get some kind of timing at the CPU clock cycle >>>>> interval >>>>> (in most modern CPUs, at least), which is about as accurate as you can >>>>> possibly get, but I don't know if there are eg. some system functions that >>>>> will return elapsed clock cycles converted into the equivalent amount of >>>>> microseconds. >>>> >>>> Get time at the microseconds resolution. My calculation engine >>>> creates a bunch of temporary files and I use the time to create unique >>>> names for those temporary files. Seconds should be good enough for >>>> uniqueness but I like adding microseconds as a guarantee. Something >>>> like >>>> uniquac1.out.009.20181972.20220912 >>> >>> An alternative is to keep a counter, incremented for each generated file >>> name, and append it to the file name, perhaps resetting to 0 when the >>> seconds count advances. If your only requirement is uniqueness, that >>> should be good enough. >>> >>> Digression: I remember an implementation of gettimeofday() that did >>> something like that (on SunOS, maybe?). The system clock had a >>> resolution of 0.01 second, so the value of tv_usec on successive calls >>> might be: >>> 420000 >>> 420001 >>> 420002 >>> 430000 >>> 430001 >>> 430002 >>> ... >>> I don't remember whether the implicit counter was per-process or >>> system-wide. >> The problem is multiple instances of the same program creating the same >> name files. >> >> Lynn > > If you decided to keep ideas of your old code* then using __rdtsc() is hand > down better than anything else. Of course, don't convert result of > __rdtsc() to microseconds, use the number in its entirety. This way you still > would not get 100% guarantee against name conflicts between multiple > instances, but probability of conflict will be 3-6 orders of magnitude lower > than any other time-based method. > ------------ > * - IMHO, you should not. Posters here suggested at least two better solutions > and can suggest more. BTW, are you sure that with modern memory > capacity you still need temporary files at all? Port to C++ first then improve. Improving inside the porting loop can bring in all kinds of bugs. A couple of the temporary files are related to our inline Fortran interpreter that the users use to add in their own custom calculations. There is some serious juju going on there. Thanks, Lynn
[toc] | [prev] | [next] | [standalone]
| From | Öö Tiib <ootiib@hot.ee> |
|---|---|
| Date | 2022-11-04 01:23 -0700 |
| Message-ID | <41369206-19bc-4a68-8495-9af712215af8n@googlegroups.com> |
| In reply to | #87220 |
On Friday, 4 November 2022 at 03:14:23 UTC+2, Lynn McGuire wrote: > What is the best way to get microseconds of time on Windows in C or C++ > ? I am currently using the following code to get the current time: > > std::time_t t = std::time (0); // get time now > std::tm * now = std::localtime ( & t); > integer iyear = now -> tm_year + 1900; > integer imonth = now -> tm_mon + 1; > integer iday = now -> tm_mday; > integer ihour = now -> tm_hour; > integer imin = now -> tm_min; > integer isec = now -> tm_sec; > integer ihund = 0; I have such code snippet copy-pasted from somewhere about portable since C++11. auto t0 = std::chrono::high_resolution_clock::now(); auto nanosec = t0.time_since_epoch(); std::cout << nanosec.count() << " nanoseconds since epoch\n"; std::cout << nanosec.count() / (1000000000.0 * 60.0 * 60.0) << " hours since epoch\n"; As I rarely need nanoseconds haven't tried it everywhere but at least looks portable.
[toc] | [prev] | [next] | [standalone]
| From | Juha Nieminen <nospam@thanks.invalid> |
|---|---|
| Date | 2022-11-07 07:20 +0000 |
| Message-ID | <tkabkp$1bm8$2@gioia.aioe.org> |
| In reply to | #87225 |
Öö Tiib <ootiib@hot.ee> wrote: > I have such code snippet copy-pasted from somewhere about portable > since C++11. > > auto t0 = std::chrono::high_resolution_clock::now(); > auto nanosec = t0.time_since_epoch(); > > std::cout << nanosec.count() << " nanoseconds since epoch\n"; > std::cout << nanosec.count() / (1000000000.0 * 60.0 * 60.0) << " hours since epoch\n"; > > As I rarely need nanoseconds haven't tried it everywhere > but at least looks portable. I highly doubt that's going to return values at the nanosecond, or even microsecond accuracy. (In other words, it's likely that the returned value will jump by significantly more than a microsecond, at larger time intervals, meaning that if you read the time again within that time interval you'll just get the same value.) Although, of course, this will depend on the target platform. At a very minimum you can't assume the return value will have that resolution. (I don't know what guarantees the standard gives for this. Probably none.)
[toc] | [prev] | [next] | [standalone]
| From | Öö Tiib <ootiib@hot.ee> |
|---|---|
| Date | 2022-11-07 07:11 -0800 |
| Message-ID | <fde8b49c-0c3a-4c78-b0df-3a2900cfd915n@googlegroups.com> |
| In reply to | #87275 |
On Monday, 7 November 2022 at 09:21:15 UTC+2, Juha Nieminen wrote: > Öö Tiib <oot...@hot.ee> wrote: > > I have such code snippet copy-pasted from somewhere about portable > > since C++11. > > > > auto t0 = std::chrono::high_resolution_clock::now(); > > auto nanosec = t0.time_since_epoch(); > > > > std::cout << nanosec.count() << " nanoseconds since epoch\n"; > > std::cout << nanosec.count() / (1000000000.0 * 60.0 * 60.0) << " hours since epoch\n"; > > > > As I rarely need nanoseconds haven't tried it everywhere > > but at least looks portable. > > I highly doubt that's going to return values at the nanosecond, or even > microsecond accuracy. (In other words, it's likely that the returned > value will jump by significantly more than a microsecond, at larger > time intervals, meaning that if you read the time again within that > time interval you'll just get the same value.) In some places it will work well enough for some use cases: <http://coliru.stacked-crooked.com/a/a911aa914ed22a56> As the calls themselves seem to take a microsecond that resolution does not matter indeed. > Although, of course, this will depend on the target platform. > At a very minimum you can't assume the return value will have that > resolution. Anything can be not good enough for our case on some platform. When I tried it worked well enough for what I needed in some places. > (I don't know what guarantees the standard gives for this. Probably > none.) It does not matter as even when standard will give very good guarantees then some of Microsoft, Apple, Intel, IBM, Google, Oracle, Texas Instruments and what are they will anyway ensure that it does do something odd on their platform or with third party compiler on their platform or with their compiler on platform of someone else. The engineers of those do not report to standard but to their peers who report to shareholders. It has been same all those decades.
[toc] | [prev] | [next] | [standalone]
| From | Michael S <already5chosen@yahoo.com> |
|---|---|
| Date | 2022-11-04 03:12 -0700 |
| Message-ID | <cdf55c6c-c418-42f7-a2d2-77258ebacc99n@googlegroups.com> |
| In reply to | #87220 |
On Friday, November 4, 2022 at 3:14:23 AM UTC+2, Lynn McGuire wrote: > What is the best way to get microseconds of time on Windows in C or C++ > ? I am currently using the following code to get the current time: > > std::time_t t = std::time (0); // get time now > std::tm * now = std::localtime ( & t); > integer iyear = now -> tm_year + 1900; > integer imonth = now -> tm_mon + 1; > integer iday = now -> tm_mday; > integer ihour = now -> tm_hour; > integer imin = now -> tm_min; > integer isec = now -> tm_sec; > integer ihund = 0; > > Thanks, > Lynn Are you interested in absolute time or in measuring time intervals for profiling and similar purposes? For the former, usec resolution is obviously impossible, because crystals that drive time measurement in your typical PC are not very good and time adjustments via NTP are not particularly frequent. Not just microseconds, even whole second are typically no good. For the later, as long as measured intervals are relatively short (no more than 10-20 msec) usec resolution is physically possible. The most portable way is std::chrono::steady_clock. Less portable way (unreliable with Windows+gcc under mingw) but good with Windows+MSVC and Linux+gcc, is std::chrono::high_resolution_clock Another good way that is not portable in absolute sense, but very portable between various x86 OSes and environments is __rdtsc(). Except that I am not aware of portable way of figuring out a duration of the tick. Well, except of calibration followed by rounding to nearest 50MHz, but that method is non-satisfactory. In practice, quite often you just know the frequency. And even more often non-portable way of finding it is good enough.
[toc] | [prev] | [next] | [standalone]
| From | Lynn McGuire <lynnmcguire5@gmail.com> |
|---|---|
| Date | 2022-11-04 14:35 -0500 |
| Message-ID | <tk3pik$1va6e$5@dont-email.me> |
| In reply to | #87227 |
On 11/4/2022 5:12 AM, Michael S wrote: > On Friday, November 4, 2022 at 3:14:23 AM UTC+2, Lynn McGuire wrote: >> What is the best way to get microseconds of time on Windows in C or C++ >> ? I am currently using the following code to get the current time: >> >> std::time_t t = std::time (0); // get time now >> std::tm * now = std::localtime ( & t); >> integer iyear = now -> tm_year + 1900; >> integer imonth = now -> tm_mon + 1; >> integer iday = now -> tm_mday; >> integer ihour = now -> tm_hour; >> integer imin = now -> tm_min; >> integer isec = now -> tm_sec; >> integer ihund = 0; >> >> Thanks, >> Lynn > > Are you interested in absolute time or in measuring time intervals > for profiling and similar purposes? > > For the former, usec resolution is obviously impossible, because > crystals that drive time measurement in your typical PC are not > very good and time adjustments via NTP are not particularly frequent. > Not just microseconds, even whole second are typically no good. > > For the later, as long as measured intervals are relatively short > (no more than 10-20 msec) usec resolution is physically possible. > > The most portable way is std::chrono::steady_clock. > > Less portable way (unreliable with Windows+gcc under mingw) > but good with Windows+MSVC and Linux+gcc, is > std::chrono::high_resolution_clock > > Another good way that is not portable in absolute sense, but > very portable between various x86 OSes and environments > is __rdtsc(). Except that I am not aware of portable way of > figuring out a duration of the tick. Well, except of calibration > followed by rounding to nearest 50MHz, but that method is > non-satisfactory. > In practice, quite often you just know the frequency. And > even more often non-portable way of finding it is good enough. Both measuring time intervals and the current time. Thanks ! Lynn
[toc] | [prev] | [next] | [standalone]
| From | scott@slp53.sl.home (Scott Lurndal) |
|---|---|
| Date | 2022-11-04 13:44 +0000 |
| Message-ID | <KG89L.4244$KkB2.2249@fx47.iad> |
| In reply to | #87220 |
Lynn McGuire <lynnmcguire5@gmail.com> writes: >What is the best way to get microseconds of time on Windows in C or C++ >? I am currently using the following code to get the current time: > > std::time_t t = std::time (0); // get time now > std::tm * now = std::localtime ( & t); > integer iyear = now -> tm_year + 1900; > integer imonth = now -> tm_mon + 1; > integer iday = now -> tm_mday; > integer ihour = now -> tm_hour; > integer imin = now -> tm_min; > integer isec = now -> tm_sec; > integer ihund = 0; > >Thanks, >Lynn First answer here: https://stackoverflow.com/questions/10905892/equivalent-of-gettimeday-for-windows
[toc] | [prev] | [next] | [standalone]
| From | Lynn McGuire <lynnmcguire5@gmail.com> |
|---|---|
| Date | 2022-11-04 14:34 -0500 |
| Message-ID | <tk3pfh$1va6e$4@dont-email.me> |
| In reply to | #87228 |
On 11/4/2022 8:44 AM, Scott Lurndal wrote: > Lynn McGuire <lynnmcguire5@gmail.com> writes: >> What is the best way to get microseconds of time on Windows in C or C++ >> ? I am currently using the following code to get the current time: >> >> std::time_t t = std::time (0); // get time now >> std::tm * now = std::localtime ( & t); >> integer iyear = now -> tm_year + 1900; >> integer imonth = now -> tm_mon + 1; >> integer iday = now -> tm_mday; >> integer ihour = now -> tm_hour; >> integer imin = now -> tm_min; >> integer isec = now -> tm_sec; >> integer ihund = 0; >> >> Thanks, >> Lynn > > First answer here: > > https://stackoverflow.com/questions/10905892/equivalent-of-gettimeday-for-windows Thanks ! Lynn
[toc] | [prev] | [next] | [standalone]
| From | Lynn McGuire <lynnmcguire5@gmail.com> |
|---|---|
| Date | 2022-11-14 16:58 -0600 |
| Message-ID | <tkuh77$1rt0u$1@dont-email.me> |
| In reply to | #87228 |
On 11/4/2022 8:44 AM, Scott Lurndal wrote: > Lynn McGuire <lynnmcguire5@gmail.com> writes: >> What is the best way to get microseconds of time on Windows in C or C++ >> ? I am currently using the following code to get the current time: >> >> std::time_t t = std::time (0); // get time now >> std::tm * now = std::localtime ( & t); >> integer iyear = now -> tm_year + 1900; >> integer imonth = now -> tm_mon + 1; >> integer iday = now -> tm_mday; >> integer ihour = now -> tm_hour; >> integer imin = now -> tm_min; >> integer isec = now -> tm_sec; >> integer ihund = 0; >> >> Thanks, >> Lynn > > First answer here: > > https://stackoverflow.com/questions/10905892/equivalent-of-gettimeday-for-windows "Nowadys I would use the following for gettimeofday() on Windows, which is using GetSystemTimePreciseAsFileTime() if compiled for Windows 8 or higher and GetSystemTimeAsFileTime() otherwise:" I used the gettimeofday function. Works well ! Thanks, Lynn
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2022-11-14 17:36 -0800 |
| Message-ID | <87zgctj8wz.fsf@nosuchdomain.example.com> |
| In reply to | #87379 |
Lynn McGuire <lynnmcguire5@gmail.com> writes:
> On 11/4/2022 8:44 AM, Scott Lurndal wrote:
>> Lynn McGuire <lynnmcguire5@gmail.com> writes:
>>> What is the best way to get microseconds of time on Windows in C or C++
>>> ? I am currently using the following code to get the current time:
>>>
>>> std::time_t t = std::time (0); // get time now
>>> std::tm * now = std::localtime ( & t);
>>> integer iyear = now -> tm_year + 1900;
>>> integer imonth = now -> tm_mon + 1;
>>> integer iday = now -> tm_mday;
>>> integer ihour = now -> tm_hour;
>>> integer imin = now -> tm_min;
>>> integer isec = now -> tm_sec;
>>> integer ihund = 0;
>>>
>>> Thanks,
>>> Lynn
>> First answer here:
>> https://stackoverflow.com/questions/10905892/equivalent-of-gettimeday-for-windows
>
> "Nowadys I would use the following for gettimeofday() on Windows,
> which is using GetSystemTimePreciseAsFileTime() if compiled for
> Windows 8 or higher and GetSystemTimeAsFileTime() otherwise:"
>
> I used the gettimeofday function. Works well !
Be aware that POSIX says gettimeofday() is obsolescent, and recommends
clock_gettime() instead.
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for XCOM Labs
void Void(void) { Void(); } /* The recursive call of the void */
[toc] | [prev] | [next] | [standalone]
| From | Lynn McGuire <lynnmcguire5@gmail.com> |
|---|---|
| Date | 2022-11-15 17:26 -0600 |
| Message-ID | <tl176i$25jh1$1@dont-email.me> |
| In reply to | #87384 |
On 11/14/2022 7:36 PM, Keith Thompson wrote:
> Lynn McGuire <lynnmcguire5@gmail.com> writes:
>> On 11/4/2022 8:44 AM, Scott Lurndal wrote:
>>> Lynn McGuire <lynnmcguire5@gmail.com> writes:
>>>> What is the best way to get microseconds of time on Windows in C or C++
>>>> ? I am currently using the following code to get the current time:
>>>>
>>>> std::time_t t = std::time (0); // get time now
>>>> std::tm * now = std::localtime ( & t);
>>>> integer iyear = now -> tm_year + 1900;
>>>> integer imonth = now -> tm_mon + 1;
>>>> integer iday = now -> tm_mday;
>>>> integer ihour = now -> tm_hour;
>>>> integer imin = now -> tm_min;
>>>> integer isec = now -> tm_sec;
>>>> integer ihund = 0;
>>>>
>>>> Thanks,
>>>> Lynn
>>> First answer here:
>>> https://stackoverflow.com/questions/10905892/equivalent-of-gettimeday-for-windows
>>
>> "Nowadys I would use the following for gettimeofday() on Windows,
>> which is using GetSystemTimePreciseAsFileTime() if compiled for
>> Windows 8 or higher and GetSystemTimeAsFileTime() otherwise:"
>>
>> I used the gettimeofday function. Works well !
>
> Be aware that POSIX says gettimeofday() is obsolescent, and recommends
> clock_gettime() instead.
This works fine for me:
// from:
//
https://stackoverflow.com/questions/10905892/equivalent-of-gettimeday-for-windows
struct timezone {
int tz_minuteswest;
int tz_dsttime;
};
int mygettimeofday (struct timeval *tv, struct timezone *tz)
{
if (tv) {
FILETIME filetime; /* 64-bit value representing the
number of 100-nanosecond intervals since January 1, 1601 00:00 UTC */
ULARGE_INTEGER x;
ULONGLONG usec;
static const ULONGLONG epoch_offset_us = 11644473600000000ULL; /*
microseconds betweeen Jan 1,1601 and Jan 1,1970 */
#if _WIN32_WINNT >= _WIN32_WINNT_WIN8
GetSystemTimePreciseAsFileTime ( & filetime);
#else
GetSystemTimeAsFileTime ( & filetime);
#endif
x.LowPart = filetime.dwLowDateTime;
x.HighPart = filetime.dwHighDateTime;
usec = x.QuadPart / 10 - epoch_offset_us;
tv->tv_sec = (time_t) (usec / 1000000ULL);
tv->tv_usec = (long) (usec % 1000000ULL);
}
if (tz) {
TIME_ZONE_INFORMATION timezone;
GetTimeZoneInformation(&timezone);
tz->tz_minuteswest = timezone.Bias;
tz->tz_dsttime = 0;
}
return 0;
}
Thanks,
Lynn
[toc] | [prev] | [next] | [standalone]
| From | Andreas <nospam@gmx.de> |
|---|---|
| Date | 2022-11-16 13:15 +0100 |
| Message-ID | <tl2k84$2beqi$1@dont-email.me> |
| In reply to | #87403 |
Am 16.11.2022 um 00:26 schrieb Lynn McGuire:
> This works fine for me:
>
> // from:
> //
> https://stackoverflow.com/questions/10905892/equivalent-of-gettimeday-for-windows
>
> struct timezone {
> int tz_minuteswest;
> int tz_dsttime;
> };
>
> int mygettimeofday (struct timeval *tv, struct timezone *tz)
> {
> if (tv) {
> FILETIME filetime; /* 64-bit value representing
> the number of 100-nanosecond intervals since January 1, 1601 00:00 UTC */
> ULARGE_INTEGER x;
> ULONGLONG usec;
> static const ULONGLONG epoch_offset_us = 11644473600000000ULL;
Wrong value. Correct value is 116444736000000000ULL (9 trailing zeros).
Rough estimation (1970-1601)*365*24*60*60 = 11'636'784'000 seconds
(ignoring Feb 29 in leap years). Additional 6 zeros to convert seconds
to microseconds.
> /* microseconds betweeen Jan 1,1601 and Jan 1,1970 */
>
> #if _WIN32_WINNT >= _WIN32_WINNT_WIN8
> GetSystemTimePreciseAsFileTime ( & filetime);
> #else
> GetSystemTimeAsFileTime ( & filetime);
> #endif
> x.LowPart = filetime.dwLowDateTime;
> x.HighPart = filetime.dwHighDateTime;
> usec = x.QuadPart / 10 - epoch_offset_us;
> tv->tv_sec = (time_t) (usec / 1000000ULL);
> tv->tv_usec = (long) (usec % 1000000ULL);
> }
> if (tz) {
> TIME_ZONE_INFORMATION timezone;
> GetTimeZoneInformation(&timezone);
> tz->tz_minuteswest = timezone.Bias;
> tz->tz_dsttime = 0;
> }
> return 0;
> }
>
> Thanks,
> Lynn
>
[toc] | [prev] | [next] | [standalone]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2022-11-04 20:49 +0100 |
| Message-ID | <tk3qci$112r$1@gioia.aioe.org> |
| In reply to | #87220 |
Am 04.11.2022 um 02:14 schrieb Lynn McGuire:
> What is the best way to get microseconds of time on Windows in C or C++
> ? I am currently using the following code to get the current time:
>
> std::time_t t = std::time (0); // get time now
> std::tm * now = std::localtime ( & t);
> integer iyear = now -> tm_year + 1900;
> integer imonth = now -> tm_mon + 1;
> integer iday = now -> tm_mday;
> integer ihour = now -> tm_hour;
> integer imin = now -> tm_min;
> integer isec = now -> tm_sec;
> integer ihund = 0;
>
> Thanks,
> Lynn
Use GetSystemTimeAsFileTime() and FileTimeToLocalFileTime() on
Windows or the time_t-capable Functions on Unix and this class:
Header:
#pragma once
#if defined(_MSC_VER)
#define NOMINMAX
#include <Windows.h>
#endif
#include <cstdint>
#include <compare>
#include <ctime>
#include <stdexcept>
#include <compare>
#include <memory>
#include <mutex>
#include <algorithm>
#include <vector>
#include <functional>
#include <atomic>
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable: 26812) // prefer enum class over enum
#pragma warning(disable: 26495) // members not intitialized
#endif
struct st_timestamp
{
constexpr st_timestamp() = default;
st_timestamp( st_timestamp const & ) = default;
constexpr st_timestamp( std::uint64_t timestamp ) noexcept;
constexpr operator std::uint64_t() const noexcept;
constexpr explicit operator std::int64_t() const noexcept;
constexpr explicit operator bool() const noexcept;
constexpr st_timestamp &operator =( st_timestamp const & ) = default;
constexpr st_timestamp &operator =( std::uint64_t timestamp ) noexcept;
private:
std::uint64_t m_timestamp;
};
struct system_time
{
std::uint16_t year;
std::uint8_t weekday, month, day;
std::uint8_t hour, minute, second;
std::uint32_t ns100;
enum reason_t : uint8_t
{
TIMESTAMP_BEYOND_63_BIT = 1,
YEAR_OUT_OF_RANGE,
MONTH_OUT_OF_RANGE,
DAY_OUT_OF_RANGE,
HOUR_OUT_OF_RANGE,
MINUTE_OUT_OF_RANGE,
SECOND_OUT_OF_RANGE,
NS100_OUT_OF_RANGE,
TIMESTAMP_BEFORE_TIME_T,
WRONG_LEAP_SECOND
};
struct leap_second_t
{
std::uint16_t year;
bool jun30, dec31;
};
struct date_error : public std::invalid_argument
{
reason_t reason();
date_error() = delete;
date_error( date_error const & ) = delete;
private:
friend struct system_time;
date_error( reason_t reason );
reason_t m_reason;
};
system_time() {}
system_time( system_time const & ) = default;
system_time( std::uint16_t year, std::uint8_t month, std::uint8_t day,
std::uint8_t hour, std::uint8_t minute, std::uint8_t second,
std::uint32_t ns100 );
explicit system_time( st_timestamp ts );
system_time( struct tm const &tm );
#if defined(_MSC_VER)
system_time( SYSTEMTIME const &st );
#endif
operator st_timestamp() const;
st_timestamp to_timestamp( reason_t *reason = nullptr ) const noexcept;
system_time &operator =( st_timestamp ts );
void from_timestamp( st_timestamp ts, reason_t *reason = nullptr )
noexcept;
system_time &operator =( system_time const & ) = default;
operator tm() const;
struct tm to_tm( reason_t *reason ) const noexcept;
system_time &operator =( struct tm const &tm );
bool from_tm( struct tm const &tm, reason_t *reason ) noexcept;
#if defined(_MSC_VER)
operator SYSTEMTIME() const;
SYSTEMTIME to_systemtime( reason_t *reason ) const noexcept;
system_time &operator =( SYSTEMTIME const &st );
bool from_systemtime( SYSTEMTIME const &st, reason_t *reason ) noexcept;
#endif
bool adjust_weekday( reason_t *reason = nullptr ) noexcept;
static std::uint8_t get_weekday( st_timestamp timestamp ) noexcept;
static_assert(sizeof(time_t) == 8, "time_t must be 64 bit");
static time_t timestamp_to_time_t( st_timestamp ts, reason_t *reason =
nullptr ) noexcept;
static st_timestamp time_t_to_timestamp( time_t time, reason_t *reason
= nullptr ) noexcept;
static void leap_seconds( std::function<leap_second_t ( bool )> const
&fn );
private:
friend struct st_timestamp;
static std::atomic<std::shared_ptr<std::vector<leap_second_t>>>
g_leapSeconds;
static constexpr std::uint64_t
MILLISECOND = 10'000,
SECOND = 1'000 * MILLISECOND,
MINUTE = 60 * SECOND,
HOUR = 60 * MINUTE,
DAY = 24 * HOUR,
WEEK = 7 * DAY,
NON_LEAP_YEAR = 365 * DAY,
LEAP_YEAR = 366 * DAY,
FOUR_YEARS_W_LJ = LEAP_YEAR + 3 * NON_LEAP_YEAR,
FOUR_YEARS_WO_LJ = 4 * NON_LEAP_YEAR,
FIRST_QUARTER_CENTURY = 25 * FOUR_YEARS_W_LJ,
REMAINING_QUARTER_CENUTRIES = 25 * FOUR_YEARS_W_LJ - DAY,
FOUR_HUNDRED_YEARS = FIRST_QUARTER_CENTURY + 3 *
REMAINING_QUARTER_CENUTRIES,
TIME_T_IN_TIMESTAMP_BEGIN = 0x19DB1DED53E800,
LAST_TIMESTAMP_IN_TIME_T = 0xD69433CCD5,
LEAP_SECOND_BIT = std::numeric_limits<int64_t>::min();
};
constexpr st_timestamp::st_timestamp( std::uint64_t timestamp ) noexcept :
m_timestamp( timestamp )
{
}
constexpr st_timestamp::operator std::uint64_t() const noexcept
{
return m_timestamp & ~system_time::LEAP_SECOND_BIT;
}
constexpr st_timestamp::operator std::int64_t() const noexcept
{
return m_timestamp;
}
constexpr st_timestamp::operator bool() const noexcept
{
return m_timestamp & system_time::LEAP_SECOND_BIT;
}
constexpr st_timestamp &st_timestamp::operator =( std::uint64_t
timestamp ) noexcept
{
m_timestamp = timestamp;
return *this;
}
// may throw invalid_argument
inline system_time::system_time( st_timestamp ts )
{
*this = ts;
}
// may throw invalid_argument
inline system_time &system_time::operator =( st_timestamp ts )
{
reason_t reason;
from_timestamp( ts, &reason );
if( reason ) [[likely]]
throw date_error( reason );
return *this;
}
inline system_time::system_time( struct tm const &tm )
{
*this = tm;
}
#if defined(_MSC_VER)
inline system_time::system_time( SYSTEMTIME const &st )
{
*this = st;
}
#endif
inline typename system_time::reason_t system_time::date_error::reason()
{
return m_reason;
}
inline uint8_t system_time::get_weekday( st_timestamp ts ) noexcept
{
using namespace std;
return (uint32_t)(((uint64_t)ts - (uint64_t)ts / WEEK * WEEK) / DAY +
1) % 7;
}
// may throw date_error
inline std::strong_ordering operator <=>( system_time const &left,
system_time const &right )
{
return (std::uint64_t)(st_timestamp)left <=> (uint64_t)(st_timestamp)right;
}
// may throw date_error
inline std::strong_ordering operator <=>( system_time const &left,
st_timestamp right )
{
return (std::uint64_t)(st_timestamp)left <=> (std::uint64_t)right;
}
// may throw date_error
inline std::strong_ordering operator <=>( st_timestamp left, system_time
const &right )
{
return (std::uint64_t)left <=> (std::uint64_t)(st_timestamp)left;
}
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
// .cpp:
#include <stdexcept>
#include <cassert>
#include <limits>
#include <algorithm>
#include <array>
#include <system_error>
#include <functional>
#if defined(__cpp_lib_hardware_interference_size)
#include <new>
#endif
#include "system_time.h"
using namespace std;
#if defined(__cpp_lib_hardware_interference_size)
constexpr size_t CL_SIZE = std::hardware_destructive_interference_size;
#else
constexpr size_t CL_SIZE = 64;
#endif
constexpr bool SYSTEM_TIME_BINARY_SEARCH = false;
// may throw date_error
system_time::system_time( std::uint16_t year, std::uint8_t month,
std::uint8_t day, std::uint8_t hour, std::uint8_t minute, std::uint8_t
second, std::uint32_t ns100 )
{
this->year = year;
this->month = month;
this->day = day;
this->hour = hour;
this->minute = minute;
this->second = second;
this->ns100 = ns100;
this->weekday = get_weekday( (st_timestamp)*this );
}
// may throw date_error
void system_time::from_timestamp( st_timestamp ts, reason_t *reason )
noexcept
{
auto reasonableErr = [&]( reason_t retReason ) -> void
{
if( reason ) [[likely]]
*reason = retReason;
memset( this, 0, sizeof *this );
};
uint64_t tsCalc = (uint64_t)ts;
bool leapSecond = (bool)ts;
weekday = get_weekday( ts );
tsCalc += LEAP_YEAR; // 1601 - 1600 = leap year
uint16_t y400, y100, y4, y;
y400 = (uint16_t)(tsCalc / FOUR_HUNDRED_YEARS);
tsCalc -= y400 * FOUR_HUNDRED_YEARS;
bool isLeapYear;
auto leapQuad = [&]()
{
if( tsCalc >= LEAP_YEAR ) [[likely]]
// y >= 1
tsCalc -= LEAP_YEAR,
y = (uint16_t)(1 + tsCalc / NON_LEAP_YEAR), // 1 ... 3
tsCalc -= tsCalc / NON_LEAP_YEAR * NON_LEAP_YEAR,
isLeapYear = false;
else
// y == 0
y = 0,
isLeapYear = true;
};
if( tsCalc >= FIRST_QUARTER_CENTURY ) [[likely]]
{
// (y % 400) >= 100
y100 = (uint16_t)(1 + (tsCalc - FIRST_QUARTER_CENTURY) /
REMAINING_QUARTER_CENUTRIES); // 1 ... 3
tsCalc -= FIRST_QUARTER_CENTURY + (tsCalc - FIRST_QUARTER_CENTURY) /
REMAINING_QUARTER_CENUTRIES * REMAINING_QUARTER_CENUTRIES;
if( tsCalc >= FOUR_YEARS_WO_LJ ) [[likely]]
// (y % 400) >= 100 && (y % 100) >= 4
y4 = (uint16_t)(1 + (tsCalc - FOUR_YEARS_WO_LJ) / FOUR_YEARS_W_LJ),
// 1 ... 24
tsCalc -= FOUR_YEARS_WO_LJ + (tsCalc - FOUR_YEARS_WO_LJ) /
FOUR_YEARS_W_LJ * FOUR_YEARS_W_LJ,
leapQuad();
else
// (y % 400) >= 100 && (y % 100) < 4
y4 = 0,
y = (uint16_t)(tsCalc / NON_LEAP_YEAR),
tsCalc -= tsCalc / NON_LEAP_YEAR * NON_LEAP_YEAR,
isLeapYear = false;
}
else
// (y % 400) < 100
y100 = 0,
y4 = (uint16_t)(tsCalc / FOUR_YEARS_W_LJ),
tsCalc -= tsCalc / FOUR_YEARS_W_LJ * FOUR_YEARS_W_LJ,
leapQuad();
year = 1600 + 400 * y400 + 100 * y100 + 4 * y4 + y;
{
static uint64_t const monthOffsets[2][12 + 1] alignas(CL_SIZE) =
{
{ 0 * DAY, 31 * DAY, 59 * DAY, 90 * DAY, 120 * DAY, 151 * DAY, 181 *
DAY, 212 * DAY, 243 * DAY, 273 * DAY, 304 * DAY, 334 * DAY, 999 * DAY },
{ 0 * DAY, 31 * DAY, 60 * DAY, 91 * DAY, 121 * DAY, 152 * DAY, 182 *
DAY, 213 * DAY, 244 * DAY, 274 * DAY, 305 * DAY, 335 * DAY, 999 * DAY }
};
uint64_t const *pMonthOffsets = monthOffsets[isLeapYear];
size_t moHit;
if constexpr( !SYSTEM_TIME_BINARY_SEARCH )
for( moHit = 0; tsCalc >= pMonthOffsets[moHit + 1]; ++moHit );
else
{
size_t lower = 0, upper = 12, mid;
moHit = -1;
do
{
mid = (lower + upper) / 2;
if( pMonthOffsets[mid] <= tsCalc )
moHit = mid,
lower = mid + 1;
else
upper = mid;
} while( lower != upper );
assert( moHit != -1 );
}
uint64_t mo = pMonthOffsets[moHit];
uint8_t dy = (uint8_t)((tsCalc - mo) / DAY);
tsCalc -= mo + dy * DAY;
month = 1 + (uint8_t)moHit;
day = 1 + dy;
}
hour = (uint8_t)(tsCalc / HOUR);
tsCalc %= HOUR;
minute = (uint8_t)(tsCalc / MINUTE);
tsCalc %= MINUTE;
second = (uint8_t)(tsCalc / SECOND);
if( leapSecond ) [[unlikely]]
{
if( second != 59 || minute != 59 || hour != 23 || (month != 6 || day
!= 30) && (month != 12 || day != 31) ) [[unlikely]]
return reasonableErr( WRONG_LEAP_SECOND );
shared_ptr leapSeconds( g_leapSeconds.load( memory_order_relaxed ) );
size_t lower = 0, upper = leapSeconds->size();
for( ; ; )
{
size_t mid = (lower + upper) / 2;
leap_second_t const &ls = (*leapSeconds)[mid];
if( ls.year == year ) [[unlikely]]
if( month == 6 && ls.jun30 || month == 12 && ls.dec31 ) [[likely]]
{
++second;
break;
}
else
return reasonableErr( WRONG_LEAP_SECOND );
bool midIsLower = ls.year < year;
(midIsLower ? lower : upper) = mid + midIsLower;
if( lower == upper ) [[unlikely]]
return reasonableErr( WRONG_LEAP_SECOND );
}
}
tsCalc %= SECOND;
ns100 = (uint32_t)tsCalc;
}
// may throw date_error
// may throw system_error
// may throw bad_alloc
extern system_time::leap_second_t const leapSecondsInit2016[26];
st_timestamp system_time::to_timestamp( reason_t *reason ) const noexcept
{
using namespace std;
auto reasonableErr = [&]( reason_t retReason ) -> st_timestamp
{
if( reason ) [[likely]]
*reason = retReason;
return st_timestamp( -1 );
};
if( year < 1601 || year > 30828 ) [[unlikely]]
return reasonableErr( YEAR_OUT_OF_RANGE );
if( month < 1 || month > 12 ) [[unlikely]]
return reasonableErr( MONTH_OUT_OF_RANGE );
bool isLeapYear = year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
static uint8_t const monthLengths[2][1 + 12] alignas(CL_SIZE) =
{
{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
{ 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
};
if( day == 0 || day > monthLengths[isLeapYear][month] ) [[unlikely]]
return reasonableErr( DAY_OUT_OF_RANGE );
if( hour >= 24 ) [[unlikely]]
return reasonableErr( HOUR_OUT_OF_RANGE );
if( minute >= 60 ) [[unlikely]]
return reasonableErr( MINUTE_OUT_OF_RANGE );
uint8_t sec = second;
uint64_t leapSecondBit = 0;
if( sec >= 60 ) [[unlikely]]
{
if( sec != 60 || minute != 59 || hour == 23 || (month != 6 || day !=
30) && (month != 12 || day != 31) ) [[unlikely]]
return reasonableErr( SECOND_OUT_OF_RANGE );
shared_ptr leapSeconds( g_leapSeconds.load( memory_order_relaxed ) );
if( !leapSeconds ) [[unlikely]]
{
size_t i = 0;
leap_seconds(
[&]( bool reset ) -> leap_second_t
{
i = !reset ? i : 0;
if( i != size( ::leapSecondsInit2016 ) ) [[likely]]
return ::leapSecondsInit2016[i++];
else
return leap_second_t { 0xFFFFu, false, false };
} );
leapSeconds = g_leapSeconds.load( memory_order_relaxed );
}
size_t lower = 0, upper = leapSeconds->size();
for( ; ; )
{
size_t mid = (lower + upper) / 2;
leap_second_t const &ls = (*leapSeconds)[mid];
if( ls.year == year ) [[unlikely]]
if( month == 6 && ls.jun30 || month == 12 && ls.dec31 ) [[likely]]
{
--sec, leapSecondBit = LEAP_SECOND_BIT;
break;
}
else
return reasonableErr( SECOND_OUT_OF_RANGE );
bool midIsLower = ls.year < year;
(midIsLower ? lower : upper) = mid + midIsLower;
if( lower == upper ) [[unlikely]]
return reasonableErr( SECOND_OUT_OF_RANGE );
}
}
if( ns100 >= 10'000'000 ) [[unlikely]]
return reasonableErr( NS100_OUT_OF_RANGE );
uint16_t yr = year - 1600;
uint64_t timestamp = yr / 400 * FOUR_HUNDRED_YEARS;
yr %= 400;
auto leapQuad = [&]()
{
timestamp += yr / 4 * FOUR_YEARS_W_LJ;
yr %= 4;
if( yr >= 1 ) [[likely]]
timestamp += LEAP_YEAR + (yr - 1) * NON_LEAP_YEAR;
};
if( yr >= 100 ) [[likely]]
{
timestamp += FIRST_QUARTER_CENTURY;
yr -= 100;
timestamp += yr / 100 * REMAINING_QUARTER_CENUTRIES;
yr %= 100;
if( yr >= 4 ) [[likely]]
timestamp += FOUR_YEARS_WO_LJ,
yr -= 4,
leapQuad();
else
timestamp += yr * NON_LEAP_YEAR;
}
else
leapQuad();
timestamp -= LEAP_YEAR; // - (1.1.1601 - 1.1.1600)
static uint16_t const monthOffsets[2][1 + 12] alignas(CL_SIZE) =
{
{ 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 },
{ 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }
};
timestamp += (monthOffsets[isLeapYear][month] + day - 1) * DAY;
timestamp += hour * HOUR;
timestamp += minute * MINUTE;
timestamp += sec * SECOND;
timestamp += ns100;
if( timestamp > (uint64_t)numeric_limits<int64_t>::max() ) [[unlikely]]
return reasonableErr( TIMESTAMP_BEYOND_63_BIT );
if( reason ) [[likely]]
*reason = (reason_t)0;
return timestamp | leapSecondBit;
}
// may throw date_error
system_time::operator st_timestamp() const
{
reason_t reason;
st_timestamp ts = to_timestamp( &reason );
if( reason ) [[unlikely]]
throw date_error( reason );
return ts;
}
#if defined(_MSC_VER)
// may throw date_error
system_time::operator SYSTEMTIME() const
{
reason_t reason;
SYSTEMTIME st = to_systemtime( &reason );
if( reason ) [[unlikely]]
throw date_error( reason );
return st;
}
SYSTEMTIME system_time::to_systemtime( reason_t *reason ) const noexcept
{
SYSTEMTIME st;
st.wYear = year;
st.wDay = day;
st.wHour = hour;
st.wMinute = minute;
st.wSecond = second;
st.wMilliseconds = (WORD)(ns100 / 10'000);
reason_t lReason;
st_timestamp timestamp = to_timestamp( &lReason );
if( lReason ) [[unlikely]]
{
if( reason ) [[likely]]
*reason = lReason;
memset( &st, 0, sizeof st );
return st;
}
st.wDayOfWeek = get_weekday( timestamp );;
return st;
}
// may throw date_error
system_time &system_time::operator =( SYSTEMTIME const &st )
{
reason_t reason;
from_systemtime( st, &reason );
if( reason ) [[unlikely]]
throw date_error( reason );
return *this;
}
bool system_time::from_systemtime( SYSTEMTIME const &st, reason_t
*reason ) noexcept
{
system_time stAux;
stAux.year = st.wYear;
stAux.month = (uint8_t)st.wMonth;
stAux.day = (uint8_t)st.wDay;
stAux.hour = (uint8_t)st.wHour;
stAux.minute = (uint8_t)st.wMinute;
stAux.second = (uint8_t)st.wSecond;
stAux.ns100 = (uint32_t)st.wMilliseconds * 10'000;
reason_t lReason;
st_timestamp timestamp = to_timestamp( &lReason );
if( lReason ) [[unlikely]]
{
if( reason ) [[likely]]
*reason = lReason;
return false;
}
stAux.weekday = get_weekday( timestamp );
*this = stAux;
return true;
}
#endif
// may throw date_error
system_time::operator tm() const
{
reason_t reason;
struct tm tm( to_tm( &reason ) );
if( reason ) [[unlikely]]
throw date_error( reason );
return tm;
}
struct tm system_time::to_tm( reason_t *reason ) const noexcept
{
using namespace std;
auto reasonableErr = [&]( reason_t retReason ) -> struct tm
{
if( reason ) [[likely]]
*reason = retReason;
return tm( -1 );
};
if( year < 1900 || year - 1900u > (unsigned)numeric_limits<int>::max()
) [[unlikely]]
return reasonableErr( YEAR_OUT_OF_RANGE );
reason_t lReason;
uint64_t timestamp = to_timestamp( &lReason );
if( lReason ) [[unlikely]]
return reasonableErr( lReason );
uint8_t wd = get_weekday( timestamp );
struct tm tm;
tm.tm_year = year - 1900;
tm.tm_mon = month - 1;
tm.tm_mday = day;
uint16_t const monthOffsets[2][1 + 12] alignas(CL_SIZE) =
{
{ 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 },
{ 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }
};
tm.tm_yday = monthOffsets[year % 4 == 0 && year % 100 != 0 || year %
400 == 0][month] + day - 1;
tm.tm_hour = hour;
tm.tm_min = minute;
tm.tm_sec = second;
tm.tm_wday = wd;
return tm;
}
// may throw date_error
system_time &system_time::operator =( struct tm const &tm )
{
reason_t reason;
if( !from_tm( tm, &reason ) ) [[unlikely]]
throw date_error( reason );
return *this;
}
bool system_time::from_tm( struct tm const &tm, reason_t *reason ) noexcept
{
auto reasonableErr = [&]( reason_t retReason ) -> bool
{
if( reason ) [[unlikely]]
*reason = retReason;
return false;
};
if( tm.tm_year < 1601 - 1900 || tm.tm_year > 30828 - 1900 ) [[unlikely]]
return reasonableErr( YEAR_OUT_OF_RANGE );
system_time stAux;
stAux.year = tm.tm_year + 1900;
stAux.month = tm.tm_mon + 1;
stAux.day = tm.tm_mday;
stAux.hour = tm.tm_hour;
stAux.minute = tm.tm_min;
stAux.second = tm.tm_sec;
stAux.ns100 = 0;
reason_t lReason;
uint64_t timestamp = stAux.to_timestamp( &lReason );
if( lReason ) [[unlikely]]
return reasonableErr( lReason );
stAux.weekday = get_weekday( timestamp );
*this = stAux;
return true;
}
// may throw date_error
time_t system_time::timestamp_to_time_t( st_timestamp ts, reason_t
*reason ) noexcept
{
if( (uint64_t)ts < TIME_T_IN_TIMESTAMP_BEGIN ) [[unlikely]]
{
if( reason ) [[likely]]
*reason = TIMESTAMP_BEFORE_TIME_T;
return -1;
}
return ((uint64_t)ts - TIME_T_IN_TIMESTAMP_BEGIN) / SECOND;
}
// may throw date_error
st_timestamp system_time::time_t_to_timestamp( time_t time, reason_t
*reason ) noexcept
{
if( time > LAST_TIMESTAMP_IN_TIME_T ) [[unlikely]]
{
if( reason ) [[likely]]
*reason = TIMESTAMP_BEYOND_63_BIT;
return -1;
}
return st_timestamp( TIME_T_IN_TIMESTAMP_BEGIN + time * SECOND );
}
// may throw date_error
inline bool system_time::adjust_weekday( reason_t *reason ) noexcept
{
reason_t lReason;
uint64_t timestamp = to_timestamp( &lReason );
if( lReason ) [[unlikely]]
{
if( reason ) [[likely]]
*reason = lReason;
return false;
}
weekday = get_weekday( timestamp );
return true;
}
system_time::date_error::date_error( reason_t reason ) :
invalid_argument(
[]( reason_t reason ) -> char const *
{
static struct err_map_t
{
reason_t reason;
char const *what;
} const errMaps[] =
{
err_map_t { TIMESTAMP_BEYOND_63_BIT, "system_time - timestamp beyond
63 bit (14.9.30828 22:48:5.4775807)" },
err_map_t { YEAR_OUT_OF_RANGE, "system_time - year out of range" },
err_map_t { MONTH_OUT_OF_RANGE, "system_time - month out of range" },
err_map_t { DAY_OUT_OF_RANGE, "system_time - day out of range" },
err_map_t { HOUR_OUT_OF_RANGE, "system_time - hour out of range" },
err_map_t { MINUTE_OUT_OF_RANGE, "system_time - minute out of range" },
err_map_t { SECOND_OUT_OF_RANGE, "system_time - second out of range" },
err_map_t { NS100_OUT_OF_RANGE, "system_time - 100ns-steps out of
range" },
err_map_t { TIMESTAMP_BEFORE_TIME_T, "system_time - timestamp before
time_t (1.1.1970 00:00.0)" }
};
for( err_map_t const &errMap : errMaps )
if( errMap.reason == reason ) [[unlikely]]
return errMap.what;
return "";
}( reason ) ),
m_reason( reason )
{
}
// may throw bad_alloc
// may throw invalid_argument if there's a duplicate leap year from the
feeder
// may throw date_error if a year is out of range (< 1601 || > 30828)
// may throw invalid_argument if leap year from feeder has no leaps
void system_time::leap_seconds( std::function<leap_second_t ( bool )>
const &feeder )
{
using namespace std;
auto feedLoop = [&]<typename Fn>( Fn fn ) -> size_t
requires requires( Fn fn, leap_second_t const &ls ) { { fn( ls ) }; }
{
size_t i = 0;
for( leap_second_t ls; (ls = feeder( i++ == 0 )).year != 0xFFFFu; fn(
ls ) );
return i;
};
vector<leap_second_t> leaps;
leaps.reserve( feedLoop( [&]( leap_second_t const & ) { } ) );
feedLoop( [&]( leap_second_t const &ls ) { leaps.emplace_back( ls ); } );
sort( leaps.begin(), leaps.end(),
[]( leap_second_t &lhs, leap_second_t &rhs ) -> bool { return lhs.year
< rhs.year; } );
for( leap_second_t const &lp : leaps )
if( &lp != &leaps[0] && lp.year == (&lp)[-1].year ) [[unlikely]]
throw invalid_argument( "duplicate leap year" );
else if( lp.year < 1601 || lp.year > 30828 ) [[unlikely]]
throw date_error( YEAR_OUT_OF_RANGE );
else if( !lp.jun30 && !lp.dec31 ) [[unlikely]]
throw invalid_argument( "leap year without leaps" );
g_leapSeconds.store( make_shared<vector<leap_second_t>>( move( leaps )
), memory_order_release );
}
atomic<shared_ptr<vector<system_time::leap_second_t>>>
system_time::g_leapSeconds;
static system_time::leap_second_t const leapSecondsInit2016[26] =
{
{ 1972, true, true },
{ 1973, false, true },
{ 1974, false, true },
{ 1975, false, true },
{ 1976, false, true },
{ 1977, false, true },
{ 1978, false, true },
{ 1979, false, true },
{ 1981, true, false },
{ 1982, true, false },
{ 1983, true, false },
{ 1985, true, false },
{ 1987, false, true },
{ 1989, false, true },
{ 1990, false, true },
{ 1992, true, false },
{ 1993, true, false },
{ 1994, true, false },
{ 1995, false, true },
{ 1997, true, false },
{ 1998, false, true },
{ 2005, false, true },
{ 2008, false, true },
{ 2012, true, false },
{ 2015, true, false },
{ 2016, false, true }
};
This is similar to Windows' FILETIME (100ns-intervals since 1.1.1601
00:00:00.0) and you can convert the C-timestamps also to st_timestamp.
st_timestamp is a 64 bit timestamp which uses the highes bit to indi-
cate if the timestamp is within a leap-second. If you - implicitly
or explicitly - convert the st_timestamp to an uint64_t the highest
bit is stripped and you can calculate with it like with a Unix-time-
stamp, but with a higher resolution. You can implicitly or explicitly
convert back an uint64_t-value to a st_timestamp independently on if
the highest bit is set or not. The bit is only honored if you convert
this timestamp to a system_time object, i.e. the second-part is set
to 60 if the st_timestamp corresponds to a legal leap-second.
[toc] | [prev] | [next] | [standalone]
| From | Manu Raju <MR@invalid.invalid> |
|---|---|
| Date | 2022-11-20 21:30 +0000 |
| Message-ID | <tle6q7$3jlpa$1@dont-email.me> |
| In reply to | #87220 |
On 04/11/2022 01:14, Lynn McGuire wrote:
> What is the best way to get microseconds of time on Windows in C or
> C++ ? I am currently using the following code to get the current time:
>
> std::time_t t = std::time (0); // get time now
> std::tm * now = std::localtime ( & t);
> integer iyear = now -> tm_year + 1900;
> integer imonth = now -> tm_mon + 1;
> integer iday = now -> tm_mday;
> integer ihour = now -> tm_hour;
> integer imin = now -> tm_min;
> integer isec = now -> tm_sec;
> integer ihund = 0;
>
> Thanks,
> Lynn
In c# I can use this code and it works:
DateTime test = DateTime.Now;
Console.WriteLine($"Day: {test.Day}");
Console.WriteLine($"Month: {test.Month}");
Console.WriteLine($"Year: {test.Year}");
Console.WriteLine($"Hour: {test.Hour}");
Console.WriteLine($"Minute: {test.Minute}");
Console.WriteLine($"Second: {test.Second}");
Console.WriteLine($"Microseconds: {test.Microsecond}");
Console.WriteLine($"Nanoseconds: {test.Nanosecond}");
Console.WriteLine($"Ticks: {test.Ticks}");
[toc] | [prev] | [standalone]
Page 2 of 2 — ← Prev page 1 [2]
Back to top | Article view | comp.lang.c++
csiph-web