如何解决使用 16 位计数器检测多个窗口/轨道是否与单个窗口重叠
我得到多个轨道(称为窗口),具有开始和结束时间戳以及具有相同窗口的窗口。我需要检查是否有任何曲目时间戳与此窗口时间戳匹配。所有时间戳均为 16 位格式。这些时间戳是从同一个单调时钟生成的。
Process_1:
track_start -> get_data(clock_monotonic) & 0xFFFF
track_end -> get_data(clock_monotonic) & 0xFFFF
Process_2:
window_start -> get_data(clock_monotonic) & 0xFFFF
window_end -> get_data(clock_monotonic) & 0xFFFF
Process_3:
检测轨道是否与窗口匹配?
问题是 16 位翻转。下面是我解决这个问题的算法:
-
获取名为“当前”的 64 位当前时间戳
-
轨道和窗口的所有时间戳都被转换为 ('current'&0xFFFFFFFFFFFF0000) |时间戳,即较低的 16 位 LSB 被时间戳替换。
-
如果开始>结束(翻转问题),我们只使用开始时间戳并添加差异。所以new end timestamp = 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,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,int_<sizeof...(Args)>()); return out << ')'; } auto remap(int64_t currentTime,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> > 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。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。