TQueue: initial commit

GitOrigin-RevId: 63b50677be3f051bc3cd1ba92010beb6ba65003f
This commit is contained in:
Arseny Smirnov 2019-08-05 18:50:55 +03:00
parent c4ed5ce140
commit 3b1eeb001b
2 changed files with 124 additions and 0 deletions

View File

@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR)
#SOURCE SETS
set(TD_TEST_SOURCE
${CMAKE_CURRENT_SOURCE_DIR}/tqueue.cpp
${CMAKE_CURRENT_SOURCE_DIR}/db.cpp
${CMAKE_CURRENT_SOURCE_DIR}/http.cpp
${CMAKE_CURRENT_SOURCE_DIR}/mtproto.cpp

123
test/tqueue.cpp Normal file
View File

@ -0,0 +1,123 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "td/utils/int_types.h"
#include "td/utils/Status.h"
#include "td/utils/Slice.h"
#include "td/utils/Span.h"
#include "td/utils/VectorQueue.h"
#include "td/utils/HashMap.h"
#include "td/utils/misc.h"
#include "td/utils/tests.h"
namespace td {
using EventId = int32;
using TQueueId = int64;
struct Event {
EventId id;
Slice data;
double expire_at;
};
class TQueue {
public:
EventId push(TQueueId queue_id, Slice data, double expire_at) {
auto &q = queues_[queue_id];
if (q.events.empty()) {
q.head_id = 1;
}
EventId event_id = narrow_cast<EventId>(q.head_id + q.events.size());
q.events.push<RawEvent>({data.str(), expire_at});
return event_id;
}
EventId get_head(TQueueId queue_id) {
auto it = queues_.find(queue_id);
if (it == queues_.end()) {
return 0;
}
auto &q = it->second;
if (q.events.empty()) {
return 0;
}
return q.head_id;
}
Result<EventId> get_tail(TQueueId queue_id) {
auto it = queues_.find(queue_id);
if (it == queues_.end()) {
return 0;
}
auto &q = it->second;
if (q.events.empty()) {
return 0;
}
return narrow_cast<EventId>(q.head_id + q.events.size() - 1);
}
Result<size_t> get(TQueueId queue_id, EventId from_id, double now, MutableSpan<Event> events) {
auto it = queues_.find(queue_id);
if (it == queues_.end()) {
return 0;
}
auto &q = it->second;
while (!q.events.empty() && q.head_id < from_id) {
q.head_id++;
q.events.pop();
}
if (q.events.empty()) {
return 0;
}
auto from_events = q.events.as_span();
size_t res_n = 0;
for (size_t i = 0; i < from_events.size(); i++) {
auto &from = from_events[i];
if (from.expire_at < now) {
continue;
}
auto &to = events[res_n];
to.data = from.data;
to.id = narrow_cast<EventId>(q.head_id + i);
to.expire_at = from.expire_at;
res_n++;
if (res_n == events.size()) {
break;
}
}
return res_n;
}
struct RawEvent {
string data;
double expire_at{0};
};
struct Queue {
EventId head_id{0};
VectorQueue<RawEvent> events;
};
HashMap<TQueueId, Queue> queues_;
};
TEST(TQueue, hands) {
Event events[100];
auto events_span = MutableSpan<Event>(events, 100);
TQueue tqueue;
auto qid = 12;
ASSERT_EQ(0, tqueue.get_head(qid));
ASSERT_EQ(0, tqueue.get_tail(qid));
tqueue.push(qid, "hello", 0);
auto head = tqueue.get_head(qid);
ASSERT_EQ(head, tqueue.get_tail(qid));
ASSERT_EQ(1, tqueue.get(qid, head, 0, events_span).move_as_ok());
}
} // namespace td