c++ - 使用 16 位计数器检测多个窗口/轨道是否与单个窗口重叠
问题描述
我得到多个轨道(称为窗口),具有开始和结束时间戳以及具有相同的窗口。我需要检查是否有任何轨道时间戳与此窗口时间戳匹配。所有时间戳都是 16 位格式。这些时间戳是从同一个单调时钟生成的。
进程_1:
track_start -> get_data(clock_monotonic) & 0xFFFF
track_end -> get_data(clock_monotonic) & 0xFFFF
进程_2:
window_start -> get_data(clock_monotonic) & 0xFFFF
window_end -> get_data(clock_monotonic) & 0xFFFF
进程_3:
检测轨道是否与窗口匹配?
问题是 16 位翻转。下面是我的算法来解决这个问题:
获取 64 位的当前时间戳,称为“当前”
轨道和窗口的所有时间戳都转换为 ('current'&0xFFFFFFFFFFFF0000) | 时间戳,即较低的 16 位 LSB 被时间戳取代。
如果开始 > 结束(翻转问题),我们只使用开始时间戳并添加差异。所以新的结束时间戳 = end + (0xFFFF - start) + end + 1。查看代码中的 remap 函数。
这是有效的,因为 Process_3 将获得最大延迟为 1 分钟的轨道和窗口时间戳。
#include <chrono> #include <cstdint> #include <iostream> #include <thread> #include <stdlib.h> /* srand, rand */ #include <vector> #include <time.h> /* time */ #include <unistd.h> #include <assert.h> using namespace std; auto getTimeStampCount() { struct timespec ts; clock_gettime( CLOCK_MONOTONIC, &ts ); return (uint64_t)ts.tv_sec * 1000000000U + (uint64_t)ts.tv_nsec; } /* returns tuples in this format <16bit start, 16bit end, real 64bit start, real 64bit end> */ auto generateTimeStamp() { auto ms = getTimeStampCount(); int x = ms & 0xFFFF; //generate a random number between 1 and 65535 int randomNumber = rand() % 65535 + 1; int y = (x + randomNumber) & 0xFFFF;/ return make_tuple(x, y, ms, ms + randomNumber); } bool isOverlapping(tuple<int64_t, int64_t> a, tuple<int64_t, int64_t> b) { return get<0>(a) <= get<1>(b) && get<0>(b) <= get<1>(a); } //for printing tuples template<std::size_t> struct int_{}; template <class Tuple, size_t Pos> std::ostream& print_tuple(std::ostream& out, const Tuple& t, int_<Pos> ) { out << std::get< std::tuple_size<Tuple>::value-Pos >(t) << ','; return print_tuple(out, t, int_<Pos-1>()); } template <class Tuple> std::ostream& print_tuple(std::ostream& out, const Tuple& t, int_<1> ) { return out << std::get<std::tuple_size<Tuple>::value-1>(t); } template <class... Args> ostream& operator<<(ostream& out, const std::tuple<Args...>& t) { out << '('; print_tuple(out, t, int_<sizeof...(Args)>()); return out << ')'; } auto remap(int64_t currentTime, tuple<int64_t, int64_t, int64_t, int64_t> t) { int64_t mask = 0xFFFFFFFFFFFF0000; //to remove 16 lsb bits int64_t x = (currentTime & mask) | get<0>(t); int64_t y = (currentTime & mask) | get<1>(t); /* * Normal case: where x is less than y * ____x____________y______ * <--------0xffff--------> * * abnormal case: where x is greater than y * ____y____________x______ * <--------0xffff--------> * In the abnormal case just subtract 0xffff - x) + y + 1 to get the duration by which y increased */ if(x > y) { int64_t increase = (0xFFFF - x) + y + 1; return make_tuple(x, y + increase); } return make_tuple(x, y); } int main () { srand (time(NULL)); //generate the timestamp for SSL vector<tuple<int64_t, int64_t, int64_t, int64_t> > tracks; for (int i = 0; i < rand()%5; i++) { tracks.push_back(generateTimeStamp()); } for (int i = 0; i < tracks.size(); i++) cout << hex << "generated tracks " << tracks[i] << endl; //generate the timestamp for window auto window = generateTimeStamp(); cout << hex << "generated window " << window << endl; auto currentTimeStamp = getTimeStampCount(); cout << hex << "current timestamp " << currentTimeStamp << endl; //make sure currentTimeStamp is greater than current window timestamps and the difference between them is not more than 16 bits(approximately 1 minute) for (int i = 0; i < tracks.size(); i++) { if(currentTimeStamp <= get<3>(tracks[i]) || (get<2>(tracks[i]) - currentTimeStamp) >= 0xFFFF) { cout << "error " << "currentTimeStamp " << currentTimeStamp << "track " << tracks[i] << endl; exit(0); } if(currentTimeStamp <= get<3>(window) || (get<2>(window) - currentTimeStamp) >= 0xFFFF) { cout << "error " << "currentTimeStamp " << currentTimeStamp << "window " << window << endl; exit(0); } } //remapped tracks timestamps std::vector<std::tuple<int64_t, int64_t>> remappedTracks; for (int i = 0; i < tracks.size(); i++) { remappedTracks.push_back(remap(currentTimeStamp, tracks[i])); } //remapped window timestamps auto remappedWindow = remap(currentTimeStamp, window); cout << "remapped window " << hex << remappedWindow << endl; //check if window timestamps overlap with tracks timestamps for (int i = 0; i < tracks.size(); i++) { auto realTrackTimeStamps = make_tuple(get<2>(tracks[i]), get<3>(tracks[i])); auto realWindowTimeStamps = make_tuple(get<2>(window), get<3>(window)); bool shouldBe = isOverlapping(realTrackTimeStamps, realWindowTimeStamps); bool got = isOverlapping(remappedTracks[i], remappedWindow); if (shouldBe != got) { cout << "generated track " << tracks[i] << endl; cout << "generated window " << window << endl; cout << "ramapped track " << remappedTracks[i] << endl; cout << "ramapped window " << remappedWindow << endl; } assert(shouldBe == got); } }
代码:https ://ideone.com/cpUrHL给出一些想法。这是模拟代码以提供视角。
有什么让它变得更好的想法或你能想到的任何错误吗?
注意:无法修改 Process_1 和 2 以传递附加信息,此时也无法更改 api。
解决方案
推荐阅读
- android - ExoPlayer 尝试下载当前曲目时出现问题
- javascript - 使用 getter 返回的 Array.from() 从状态复制数组在 Vuex 上不起作用
- postgresql - postgresql 时间戳到 std::chrono 值
- java - 如何从终端将我的 Gradle 项目作为 JAR 运行
- python - 如何删除气流安装
- flutter - 带有 IndexedStack 的 AnimatedSwitcher
- javascript - react-native-navigation V3 使应用程序崩溃
- android - 如何在 Android Camera API 2 中使用零快门延迟?
- linux - 对 `ldap_msgtype@OPENLDAP_2.4_2' 和许多其他的未定义引用
- spring-security - 如何在本地网络企业中配置 Ldap 认证?