Project
Loading...
Searching...
No Matches
TimeStamp.h
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
12//-*- Mode: C++ -*-
13#ifndef TIMESTAMP_H
14#define TIMESTAMP_H
15
20
21#include "Headers/DataHeader.h"
22#include <chrono>
23#include <cassert>
24#include <type_traits> // for std::integral_constant
25
26namespace o2::header
27{
28
29// https://lhc-machine-outreach.web.cern.ch/lhc-machine-outreach/collisions.htm
30// https://www.lhc-closer.es/taking_a_closer_look_at_lhc/0.buckets_and_bunches
31
32namespace lhc_clock_parameter
33{
34// number of bunches and the 40 MHz clock with 25 ns bunch spacing
35// gives revolution time of 89.1 us and 11.223345 kHz
36// this depends on the assumption that the particles are moving effectively
37// at speed of light. There are also documents specifying the orbit time
38// to 89.4 us
39// Note: avoid to define the revolution frequency and use the integral numbers
40// for bunch places and bunch spacing in nano seconds
41// TODO: this eventually needs to be configurable
42static constexpr int gNumberOfBunches = 3564;
43static constexpr int gBunchSpacingNanoSec = 25;
44static constexpr int gOrbitTimeNanoSec = std::ratio<gNumberOfBunches * gBunchSpacingNanoSec>::num;
45
46using OrbitPrecision = std::integral_constant<int, 0>;
47using BunchPrecision = std::integral_constant<int, 1>;
48
49// the type of the clock tick depends on whether to use also the bunches
50// as substructure of the orbit.
51// a trait class to extrat the properties of the clock, namely the type
52// of the tick and the period
53template <typename T>
54struct Property {
55 // the default does not specify anything and is never going to be used
56};
57
58template <>
60 using rep = uint32_t;
61 // avoid rounding errors by using the integral numbers in the std::ratio
62 // template to define the period
63 using period = std::ratio_multiply<std::ratio<gOrbitTimeNanoSec>, std::nano>;
64};
65
66template <>
68 using rep = uint64_t;
69 // this is effectively the LHC clock and the ratio is the
70 // bunch spacing
71 using period = std::ratio_multiply<std::ratio<gBunchSpacingNanoSec>, std::nano>;
72};
73} // namespace lhc_clock_parameter
74
75// a chrono clock implementation
76// - always relative to run start
77// - need run start to calculate the epoch
78// - based on revolution frequency and number of bunches
79// TODO: the reference time is probably the start of the fill
80template <typename RefTimePoint, typename Precision = lhc_clock_parameter::OrbitPrecision>
82{
83 public:
84 LHCClock(const RefTimePoint& start) : mReference(start) {}
86 LHCClock() = delete;
87 ~LHCClock() = default;
88 LHCClock(const LHCClock&) = default;
89 LHCClock& operator=(const LHCClock&) = default;
90
93 using duration = std::chrono::duration<rep, period>;
94 using time_point = std::chrono::time_point<LHCClock>;
95 // this follows the naming convention of std chrono
96 static const bool is_steady = true;
97
100 time_point now() noexcept
101 {
102 // tp1 - tp2 results in a duration, we use to create a time_point with characteristics
103 // of the clock.
104 return time_point(std::chrono::duration_cast<duration>(std::chrono::system_clock::now()) - mReference);
105 }
106
107 private:
109 RefTimePoint mReference;
110};
111
112// TODO: is it correct to define this types always relative to the system clock?
115
117{
118 public:
120 // TODO: type aliases for the types of ticks and subticks
121
122 TimeStamp() = default;
123 TimeStamp(uint64_t ts) : mTimeStamp64(ts) {}
124 TimeStamp(const TimeUnitID& unit, uint32_t tick, uint16_t subtick = 0)
125 : mUnit(unit), mSubTicks(subtick), mTicks(tick) {}
126 ~TimeStamp() = default;
127
128 static TimeUnitID const sClockLHC;
130
131 operator uint64_t() const { return mTimeStamp64; }
132
135 template <class T, typename Rep = typename T::rep, typename Period = typename T::period>
136 auto get() const
137 {
138 static_assert(std::is_same<typename T::rep, Rep>::value && std::is_same<typename T::period, Period>::value,
139 "only clock and duration types defining the rep and period member types are allowed");
140 using duration = std::chrono::duration<Rep, Period>;
141 static_assert(sizeof(mUnit) == sizeof(sClockLHC), "size mismatch of mUnit and sClockLHC");
142 if (memcmp(&mUnit, &sClockLHC, sizeof(sClockLHC)) == 0) {
143 // cast each part individually, if the precision of the return type
144 // is smaller the values are simply truncated
145 return std::chrono::duration_cast<duration>(LHCOrbitClock::duration(mPeriod) + LHCBunchClock::duration(mBCNumber));
146 }
147 static_assert(sizeof(mUnit) == sizeof(sMicroSeconds), "size mismatch of mUnit and sMicroSeconds");
148 if (memcmp(&mUnit, &sMicroSeconds, sizeof(sMicroSeconds)) == 0) {
149 // TODO: is there a better way to mark the subticks invalid for the
150 // micro seconds representation? First step is probably to remove/rename the
151 // variable
152 assert(mSubTicks == 0);
153 return std::chrono::duration_cast<duration>(std::chrono::microseconds(mTicks));
154 }
155 // invalid time unit identifier
156 // TODO: define error policy
157 assert(0);
158 return std::chrono::duration_cast<duration>(std::chrono::seconds(0));
159 }
160
161 // TODO: implement transformation from one unit to the other
162 // void transform(const TimeUnitID& unit) {
163 // if (mUnit == unit) return;
164 // ...
165 //}
166
167 private:
168 union {
169 uint64_t mTimeStamp64;
170 struct {
171 uint16_t mUnit;
172 // the unions are probably not a good idea as the members have too different
173 // meaning depending on the unit, but take it as a fist working assumption
174 union {
175 uint16_t mBCNumber;
176 uint16_t mSubTicks;
177 };
178 union {
179 uint32_t mPeriod;
180 uint32_t mTicks;
181 };
182 };
183 };
184};
185} // namespace o2::header
186
187#endif
LHCClock & operator=(const LHCClock &)=default
LHCClock(const RefTimePoint &start)
Definition TimeStamp.h:84
time_point now() noexcept
Definition TimeStamp.h:100
typename lhc_clock_parameter::Property< Precision >::period period
Definition TimeStamp.h:92
std::chrono::duration< rep, period > duration
Definition TimeStamp.h:93
LHCClock()=delete
forbidden, always need a reference
std::chrono::time_point< LHCClock > time_point
Definition TimeStamp.h:94
static const bool is_steady
Definition TimeStamp.h:96
typename lhc_clock_parameter::Property< Precision >::rep rep
Definition TimeStamp.h:91
LHCClock(const LHCClock &)=default
TimeStamp(const TimeUnitID &unit, uint32_t tick, uint16_t subtick=0)
Definition TimeStamp.h:124
TimeStamp(uint64_t ts)
Definition TimeStamp.h:123
static TimeUnitID const sMicroSeconds
Definition TimeStamp.h:129
static TimeUnitID const sClockLHC
Definition TimeStamp.h:128
GLuint start
Definition glcorearb.h:469
std::integral_constant< int, 1 > BunchPrecision
Definition TimeStamp.h:47
std::integral_constant< int, 0 > OrbitPrecision
Definition TimeStamp.h:46
O2 data header classes and API, v0.1.
Definition DetID.h:49
std::ratio_multiply< std::ratio< gBunchSpacingNanoSec >, std::nano > period
Definition TimeStamp.h:71
std::ratio_multiply< std::ratio< gOrbitTimeNanoSec >, std::nano > period
Definition TimeStamp.h:63