Remove homebrew List implementation
Use std::list instead of gestures::List
Include helper function where needed for .at needs
Changed LookaheadFilterInterpreter::free_list_ to be a vector
Added QStateList test for coverage improvement
BUG=b:270612476
TEST=USE="coverage" FEATURES="test noclean" emerge-brya chromeos-base/gestures
Change-Id: I0857ff48f8d386f15b887d25349c734f2710f946
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/gestures/+/4303073
Auto-Submit: Denis Brockus <dbrockus@chromium.org>
Code-Coverage: Henry Barnor <hbarnor@chromium.org>
Commit-Queue: Denis Brockus <dbrockus@chromium.org>
Reviewed-by: Harry Cutts <hcutts@chromium.org>
Tested-by: Denis Brockus <dbrockus@chromium.org>
diff --git a/Android.bp b/Android.bp
index eb7d8ac..8be85fa 100644
--- a/Android.bp
+++ b/Android.bp
@@ -132,7 +132,6 @@
"src/immediate_interpreter_unittest.cc",
"src/integral_gesture_filter_interpreter_unittest.cc",
"src/interpreter_unittest.cc",
- "src/list_unittest.cc",
"src/logging_filter_interpreter_unittest.cc",
"src/lookahead_filter_interpreter_unittest.cc",
"src/mouse_interpreter_unittest.cc",
diff --git a/Makefile b/Makefile
index 53c9d66..d04ce98 100644
--- a/Makefile
+++ b/Makefile
@@ -60,7 +60,6 @@
$(OBJDIR)/immediate_interpreter_unittest.o \
$(OBJDIR)/integral_gesture_filter_interpreter_unittest.o \
$(OBJDIR)/interpreter_unittest.o \
- $(OBJDIR)/list_unittest.o \
$(OBJDIR)/logging_filter_interpreter_unittest.o \
$(OBJDIR)/lookahead_filter_interpreter_unittest.o \
$(OBJDIR)/non_linearity_filter_interpreter_unittest.o \
diff --git a/include/list.h b/include/list.h
index d5d94c4..c822e7a 100644
--- a/include/list.h
+++ b/include/list.h
@@ -5,104 +5,27 @@
#ifndef GESTURES_LIST_H__
#define GESTURES_LIST_H__
+#include <list>
#include "include/logging.h"
#include "include/memory_manager.h"
namespace gestures {
-// Elt must have the following members:
-// Elt* next_;
-// Elt* prev_;
-
template<typename Elt>
-class List {
+class MemoryManagedList : public std::list<Elt*> {
public:
- List() { Init(); }
- ~List() { DeleteAll(); }
-
- // inserts new_elt before existing. Assumes existing is in list already.
- void InsertBefore(Elt *existing, Elt* new_elt) {
- size_++;
- Elt* pre_new = existing->prev_;
- pre_new->next_ = new_elt;
- new_elt->prev_ = pre_new;
- new_elt->next_ = existing;
- existing->prev_ = new_elt;
- }
-
- Elt* Unlink(Elt* existing) {
- if (Empty()) {
- Err("Can't pop from empty list!");
- return NULL;
- }
- size_--;
- existing->prev_->next_ = existing->next_;
- existing->next_->prev_ = existing->prev_;
- existing->prev_ = existing->next_ = NULL;
- return existing;
- }
-
- void PushFront(Elt* elt) { InsertBefore(sentinel_.next_, elt); }
- Elt* PopFront() { return Unlink(sentinel_.next_); }
- void PushBack(Elt* elt) { InsertBefore(&sentinel_, elt); }
- Elt* PopBack() { return Unlink(sentinel_.prev_); }
-
- virtual void DeleteAll() {
- while (!Empty())
- delete PopFront();
- }
-
- Elt* Head() const { return sentinel_.next_; }
- Elt* Tail() const { return sentinel_.prev_; }
- size_t size() const { return size_; }
- bool Empty() const { return size() == 0; }
-
- // Iterator-like methods
- Elt* Begin() const { return Head(); }
- Elt* End() const { return const_cast<Elt*>(&sentinel_); }
-
- void Init() {
- size_ = 0;
- sentinel_.next_ = sentinel_.prev_ = &sentinel_;
- }
-
- private:
- // sentinel element
- Elt sentinel_;
-
- size_t size_;
-};
-
-
-template<typename Elt>
-class MemoryManagedList : public List<Elt> {
- public:
- using List<Elt>::Empty;
- using List<Elt>::PopBack;
- using List<Elt>::PopFront;
- using List<Elt>::PushBack;
- using List<Elt>::PushFront;
-
MemoryManagedList() { };
- ~MemoryManagedList() { DeleteAll(); }
+ ~MemoryManagedList() { clear(); }
void Init(MemoryManager<Elt>* memory_manager) {
memory_manager_ = memory_manager;
- List<Elt>::Init();
- }
-
- Elt* NewElt() {
- Elt* elt = memory_manager_->Allocate();
- AssertWithReturnValue(elt, NULL);
- elt->next_ = elt->prev_ = NULL;
- return elt;
}
Elt* PushNewEltBack() {
AssertWithReturnValue(memory_manager_, NULL);
Elt* elt = NewElt();
AssertWithReturnValue(elt, NULL);
- PushBack(elt);
+ this->push_back(elt);
return elt;
}
@@ -110,26 +33,35 @@
AssertWithReturnValue(memory_manager_, NULL);
Elt* elt = NewElt();
AssertWithReturnValue(elt, NULL);
- PushFront(elt);
+ this->push_front(elt);
return elt;
}
void DeleteFront() {
AssertWithReturn(memory_manager_);
- memory_manager_->Free(PopFront());
+ memory_manager_->Free(this->front());
+ this->pop_front();
}
void DeleteBack() {
AssertWithReturn(memory_manager_);
- memory_manager_->Free(PopBack());
+ memory_manager_->Free(this->pop_back());
}
- virtual void DeleteAll() {
- while (!Empty())
+ void clear() {
+ while (!this->empty())
DeleteFront();
}
+
private:
MemoryManager<Elt>* memory_manager_;
+
+ Elt* NewElt() {
+ Elt* elt = memory_manager_->Allocate();
+ AssertWithReturnValue(elt, NULL);
+ elt->next_ = elt->prev_ = NULL;
+ return elt;
+ }
};
diff --git a/include/lookahead_filter_interpreter.h b/include/lookahead_filter_interpreter.h
index 33dcc9b..31aefe4 100644
--- a/include/lookahead_filter_interpreter.h
+++ b/include/lookahead_filter_interpreter.h
@@ -3,15 +3,16 @@
// found in the LICENSE file.
#include <algorithm>
+#include <list>
#include <map>
#include <memory>
+#include <vector>
#include <gtest/gtest.h> // For FRIEND_TEST
#include "include/filter_interpreter.h"
#include "include/finger_metrics.h"
#include "include/gestures.h"
-#include "include/list.h"
#include "include/prop_registry.h"
#include "include/tracer.h"
@@ -33,6 +34,8 @@
FRIEND_TEST(LookaheadFilterInterpreterTest, SimpleTest);
FRIEND_TEST(LookaheadFilterInterpreterTest, SpuriousCallbackTest);
FRIEND_TEST(LookaheadFilterInterpreterTest, VariableDelayTest);
+ FRIEND_TEST(LookaheadFilterInterpreterTest, QStateListTest);
+
public:
LookaheadFilterInterpreter(PropRegistry* prop_reg, Interpreter* next,
Tracer* tracer);
@@ -108,8 +111,12 @@
stime_t ExtraVariableDelay() const;
- List<QState> queue_;
- List<QState> free_list_;
+ class QStateList : public std::list<QState*> {
+ public:
+ QState* at(int offset);
+ } queue_;
+
+ std::vector<QState*> free_list_;
// The last id assigned to a contact (part of drumroll suppression)
short last_id_;
diff --git a/src/list_unittest.cc b/src/list_unittest.cc
deleted file mode 100644
index 9c8ea74..0000000
--- a/src/list_unittest.cc
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2011 The ChromiumOS Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <algorithm>
-#include <set>
-
-#include <gtest/gtest.h>
-
-#include "include/list.h"
-#include "include/util.h"
-
-namespace gestures {
-
-class ListTest : public ::testing::Test {};
-
-namespace {
-struct Node {
- explicit Node() : val_(-1) {}
- explicit Node(int val) : val_(val) {}
- int val_;
- Node* next_;
- Node* prev_;
-};
-
-void VerifyList(List<Node>& list) {
- Node* first = list.Head()->prev_; // sentinel
- Node* second = list.Head(); // next elt (sentinel or first element)
- std::set<Node*> seen_nodes;
- if (!list.Empty())
- EXPECT_NE(first, second);
- else
- EXPECT_EQ(first, second);
- seen_nodes.insert(second);
- for (size_t i = 0; i <= list.size(); ++i) {
- EXPECT_EQ(first->next_, second);
- EXPECT_EQ(second->prev_, first);
- if (i < list.size()) {
- first = second;
- second = second->next_;
- EXPECT_FALSE(SetContainsValue(seen_nodes, second));
- seen_nodes.insert(second);
- }
- }
- EXPECT_EQ(seen_nodes.size(), list.size() + 1);
- // second should now be sentinal tail
- Node* sen_tail = list.Tail()->next_;
- EXPECT_EQ(second, sen_tail);
-}
-}
-
-TEST(ListTest, SimpleTest) {
- List<Node> list;
- VerifyList(list);
- EXPECT_TRUE(list.Empty());
- EXPECT_EQ(0, list.size());
- list.PushFront(new Node(4));
- VerifyList(list);
- EXPECT_FALSE(list.Empty());
- EXPECT_EQ(1, list.size());
- list.PushFront(new Node(5));
- VerifyList(list);
- EXPECT_EQ(2, list.size());
- EXPECT_EQ(4, list.Tail()->val_);
- EXPECT_EQ(5, list.Head()->val_);
- list.PushBack(new Node(3));
- VerifyList(list);
- EXPECT_EQ(3, list.size());
-
- Node* node = list.PopFront();
- VerifyList(list);
- ASSERT_TRUE(node);
- EXPECT_EQ(5, node->val_);
- delete node;
-
- node = list.PopBack();
- VerifyList(list);
- ASSERT_TRUE(node);
- EXPECT_EQ(3, node->val_);
- delete node;
-
- node = list.PopBack();
- VerifyList(list);
- ASSERT_TRUE(node);
- EXPECT_EQ(4, node->val_);
- delete node;
-
- node = list.PopBack();
- VerifyList(list);
- EXPECT_EQ(NULL, node);
-}
-
-} // namespace gestures
diff --git a/src/lookahead_filter_interpreter.cc b/src/lookahead_filter_interpreter.cc
index f7abaf5..f60b0f5 100644
--- a/src/lookahead_filter_interpreter.cc
+++ b/src/lookahead_filter_interpreter.cc
@@ -19,9 +19,12 @@
static const stime_t kMaxDelay = 0.09; // 90ms
}
+static const size_t kMaxQNodes = 16;
+
LookaheadFilterInterpreter::LookaheadFilterInterpreter(
PropRegistry* prop_reg, Interpreter* next, Tracer* tracer)
: FilterInterpreter(NULL, next, tracer, false),
+ free_list_(kMaxQNodes),
last_id_(0), max_fingers_per_hwstate_(0), interpreter_due_(-1.0),
last_interpreted_time_(-1.0),
min_nonsuppress_speed_(prop_reg, "Input Queue Min Nonsuppression Speed",
@@ -46,40 +49,42 @@
void LookaheadFilterInterpreter::SyncInterpretImpl(HardwareState* hwstate,
stime_t* timeout) {
// Push back into queue
- if (free_list_.Empty()) {
+ if (free_list_.empty()) {
Err("Can't accept new hwstate b/c we're out of nodes!");
Err("Now: %f, interpreter_due_ %f", hwstate->timestamp, interpreter_due_);
Err("Dump of queue:");
- for (QState* it = queue_.Begin(); it != queue_.End(); it = it->next_)
- Err("Due: %f%s", it->due_, it->completed_ ? " (c)" : "");
+ for (const auto& element : queue_)
+ Err("Due: %f%s", element->due_, element->completed_ ? " (c)" : "");
return;
}
- QState* node = free_list_.PopFront();
+ QState* node = free_list_.back();
+ free_list_.pop_back();
node->set_state(*hwstate);
double delay = max(0.0, min<stime_t>(kMaxDelay, min_delay_.val_));
node->due_ = hwstate->timestamp + delay;
node->completed_ = false;
- if (queue_.Empty())
+ if (queue_.empty())
node->output_ids_.clear();
else
- node->output_ids_ = queue_.Tail()->output_ids_;
- // At this point, if ExtraVariableDelay() > 0, queue_.Tail()->due_ may have
+ node->output_ids_ = queue_.back()->output_ids_;
+ // At this point, if ExtraVariableDelay() > 0, queue_.back()->due_ may have
// ExtraVariableDelay() applied, but node->due_ does not, yet.
- if (!queue_.Empty() &&
- (queue_.Tail()->due_ - node->due_ > ExtraVariableDelay())) {
+ if (!queue_.empty() &&
+ (queue_.back()->due_ - node->due_ > ExtraVariableDelay())) {
Err("Clock changed backwards. Flushing queue.");
stime_t next_timeout = NO_DEADLINE;
- QState* q_node = queue_.Head();
+ auto q_node_iter = queue_.begin();
do {
- if (!q_node->completed_)
- next_->SyncInterpret(&q_node->state_, &next_timeout);
- q_node = q_node->next_;
- free_list_.PushBack(queue_.PopFront());
- } while (!queue_.Empty());
+ if (!(*q_node_iter)->completed_)
+ next_->SyncInterpret(&(*q_node_iter)->state_, &next_timeout);
+ ++q_node_iter;
+ free_list_.push_back(queue_.front());
+ queue_.pop_front();
+ } while (!queue_.empty());
interpreter_due_ = -1.0;
last_interpreted_time_ = -1.0;
}
- queue_.PushBack(node);
+ queue_.push_back(node);
AssignTrackingIds();
AttemptInterpolation();
UpdateInterpreterDue(interpreter_due_ < 0.0 ?
@@ -88,7 +93,7 @@
HandleTimerImpl(hwstate->timestamp, timeout);
// Copy finger flags for upstream filters.
- QState* q_node = queue_.Head();
+ QState* q_node = queue_.front();
if (q_node->state_.SameFingersAs(*hwstate)) {
for (size_t i = 0; i < hwstate->finger_cnt; i++) {
hwstate->fingers[i].flags = q_node->state_.fingers[i].flags;
@@ -143,7 +148,7 @@
// Always reassign trackingID on the very first hwstate so that
// the next hwstate can inherit the trackingID mapping.
if (queue_.size() == 1) {
- QState* tail = queue_.Tail();
+ QState* tail = queue_.back();
HardwareState* hs = &tail->state_;
for (size_t i = 0; i < hs->finger_cnt; i++) {
FingerState* fs = &hs->fingers[i];
@@ -156,11 +161,11 @@
return;
}
- QState* tail = queue_.Tail();
+ auto tail = queue_.at(-1);
HardwareState* hs = &tail->state_;
- QState* prev_qs = queue_.size() < 2 ? NULL : tail->prev_;
+ QState* prev_qs = queue_.size() < 2 ? NULL : queue_.at(-2);
HardwareState* prev_hs = prev_qs ? &prev_qs->state_ : NULL;
- QState* prev2_qs = queue_.size() < 3 ? NULL : prev_qs->prev_;
+ QState* prev2_qs = queue_.size() < 3 ? NULL : queue_.at(-3);
HardwareState* prev2_hs = prev2_qs ? &prev2_qs->state_ : NULL;
RemoveMissingIdsFromMap(&tail->output_ids_, *hs);
@@ -356,11 +361,12 @@
return;
if (queue_.size() < 2)
return; // Not enough data to know
- HardwareState& hs = queue_.Tail()->state_;
- if (queue_.Tail()->state_.timestamp != now)
+ HardwareState& hs = queue_.back()->state_;
+ if (queue_.back()->state_.timestamp != now)
return; // We didn't push a new hardware state now
- // See if latest hwstate has finger that previous doesn't
- HardwareState& prev_hs = queue_.Tail()->prev_->state_;
+ // See if latest hwstate has finger that previous doesn't.
+ // Get the state_ of back->prev
+ HardwareState& prev_hs = queue_.at(-2)->state_;
if (hs.finger_cnt > prev_hs.finger_cnt) {
// Finger was added.
ProduceGesture(Gesture(kGestureFling, prev_hs.timestamp, hs.timestamp,
@@ -396,18 +402,20 @@
void LookaheadFilterInterpreter::AttemptInterpolation() {
if (queue_.size() < 2)
return;
- QState* new_node = queue_.Tail();
- QState* prev = new_node->prev_;
+ QState* new_node = queue_.at(-1);
+ QState* prev = queue_.at(-2);
if (new_node->state_.timestamp - prev->state_.timestamp <
- split_min_period_.val_)
+ split_min_period_.val_) {
return; // Nodes came in too quickly to need interpolation
+ }
if (!prev->state_.SameFingersAs(new_node->state_))
return;
- QState* node = free_list_.PopFront();
- if (!node) {
+ if (free_list_.empty()) {
Err("out of nodes?");
return;
}
+ QState* node = free_list_.back();
+ free_list_.pop_back();
node->state_.fingers = node->fs_.get();
node->completed_ = false;
Interpolate(prev->state_, new_node->state_, &node->state_);
@@ -418,11 +426,10 @@
if (node->state_.timestamp <= last_interpreted_time_) {
// Time wouldn't seem monotonically increasing w/ this new event, so
// discard it.
- free_list_.PushBack(node);
- return;
+ free_list_.push_back(node);
+ } else {
+ queue_.insert(--queue_.end(), node);
}
-
- queue_.InsertBefore(new_node, node);
}
void LookaheadFilterInterpreter::HandleTimerImpl(stime_t now,
@@ -440,12 +447,16 @@
last_interpreted_time_ = now;
next_->HandleTimer(now, &next_timeout);
} else {
- if (queue_.Empty())
+ if (queue_.empty())
break;
// Get next uncompleted and overdue hwstate
- QState* node = queue_.Head();
- while (node != queue_.Tail() && node->completed_)
- node = node->next_;
+ auto node = queue_.back();
+ for (auto state : queue_) {
+ if (!state->completed_) {
+ node = state;
+ break;
+ }
+ }
if (node->completed_ || node->due_ > now)
break;
next_timeout = NO_DEADLINE;
@@ -471,8 +482,10 @@
next_->SyncInterpret(&hs_copy, &next_timeout);
// Clear previously completed nodes, but keep at least two nodes.
- while (queue_.size() > 2 && queue_.Head()->completed_)
- free_list_.PushBack(queue_.PopFront());
+ while (queue_.size() > 2 && queue_.front()->completed_) {
+ free_list_.push_back(queue_.front());
+ queue_.pop_front();
+ }
// Mark current node completed. This should be the only completed
// node in the queue.
@@ -489,7 +502,7 @@
}
void LookaheadFilterInterpreter::ConsumeGesture(const Gesture& gesture) {
- QState* node = queue_.Head();
+ QState* node = queue_.front();
float distance_sq = 0.0;
// Slow movements should potentially be suppressed
@@ -516,10 +529,11 @@
return;
}
// Speed is slow. Suppress if fingers have changed.
- for (QState* iter = node->next_; iter != queue_.End(); iter = iter->next_)
- if (!node->state_.SameFingersAs(iter->state_) ||
- (node->state_.buttons_down != iter->state_.buttons_down))
+ for (auto iter = ++queue_.begin(); iter != queue_.end(); ++iter) {
+ if (!node->state_.SameFingersAs((*iter)->state_) ||
+ (node->state_.buttons_down != (*iter)->state_.buttons_down))
return; // suppress
+ }
ProduceGesture(gesture);
}
@@ -532,11 +546,10 @@
// timeout, so we use -DBL_MAX as the invalid value.
stime_t next_hwstate_timeout = -DBL_MAX;
// Scan queue_ to find when next hwstate is due.
- for (QState* node = queue_.Begin(); node != queue_.End();
- node = node->next_) {
- if (node->completed_)
+ for (auto elem : queue_) {
+ if (elem->completed_)
continue;
- next_hwstate_timeout = node->due_ - now;
+ next_hwstate_timeout = elem->due_ - now;
break;
}
@@ -557,12 +570,11 @@
MetricsProperties* mprops,
GestureConsumer* consumer) {
FilterInterpreter::Initialize(hwprops, NULL, mprops, consumer);
- const size_t kMaxQNodes = 16;
- queue_.DeleteAll();
- free_list_.DeleteAll();
+ queue_.clear();
+ free_list_.clear();
for (size_t i = 0; i < kMaxQNodes; ++i) {
QState* node = new QState(hwprops_->max_finger_cnt);
- free_list_.PushBack(node);
+ free_list_.push_back(node);
}
}
@@ -603,4 +615,25 @@
state_.msc_timestamp = new_state.msc_timestamp;
}
+LookaheadFilterInterpreter::QState*
+LookaheadFilterInterpreter::QStateList::at(int offset) {
+ // Traverse to the appropriate offset
+ if (offset < 0) {
+ // negative offset is from end to begin
+ auto count = size();
+ for (auto iter = --end(); count > 0; --count, --iter) {
+ if (++offset == 0)
+ return *iter;
+ }
+ } else {
+ // positive offset is from begin to end
+ for (auto elem : *this) {
+ if (offset-- == 0)
+ return elem;
+ }
+ }
+ // invalid offset returns NULL
+ return nullptr;
+}
+
} // namespace gestures
diff --git a/src/lookahead_filter_interpreter_unittest.cc b/src/lookahead_filter_interpreter_unittest.cc
index 788d785..1c84eb4 100644
--- a/src/lookahead_filter_interpreter_unittest.cc
+++ b/src/lookahead_filter_interpreter_unittest.cc
@@ -788,42 +788,42 @@
wrapper.Reset(interpreter.get());
stime_t timeout = NO_DEADLINE;
- List<LookaheadFilterInterpreter::QState>* queue = &interpreter->queue_;
+ const auto& queue = interpreter->queue_;
// Pushing the first event
wrapper.SyncInterpret(&hs[0], &timeout);
- EXPECT_EQ(queue->size(), 1);
- EXPECT_EQ(queue->Tail()->fs_[0].tracking_id, 1);
+ EXPECT_EQ(queue.size(), 1);
+ EXPECT_EQ(queue.back()->fs_[0].tracking_id, 1);
// Expecting Drumroll detected and ID reassigned 1 -> 2.
wrapper.SyncInterpret(&hs[1], &timeout);
- EXPECT_EQ(queue->size(), 2);
- EXPECT_EQ(queue->Tail()->fs_[0].tracking_id, 2);
+ EXPECT_EQ(queue.size(), 2);
+ EXPECT_EQ(queue.back()->fs_[0].tracking_id, 2);
// Expecting Drumroll detected and ID reassigned 1 -> 3.
wrapper.SyncInterpret(&hs[2], &timeout);
- EXPECT_EQ(queue->size(), 3);
- EXPECT_EQ(queue->Tail()->fs_[0].tracking_id, 3);
+ EXPECT_EQ(queue.size(), 3);
+ EXPECT_EQ(queue.back()->fs_[0].tracking_id, 3);
// Removing the touch.
wrapper.SyncInterpret(&hs[3], &timeout);
- EXPECT_EQ(queue->size(), 4);
+ EXPECT_EQ(queue.size(), 4);
// New event comes, old events removed from the queue.
// New finger tracking ID assigned 2 - > 4.
wrapper.SyncInterpret(&hs[4], &timeout);
- EXPECT_EQ(queue->size(), 2);
- EXPECT_EQ(queue->Tail()->fs_[0].tracking_id, 4);
+ EXPECT_EQ(queue.size(), 2);
+ EXPECT_EQ(queue.back()->fs_[0].tracking_id, 4);
// Expecting Drumroll detected and ID reassigned 2 -> 5.
wrapper.SyncInterpret(&hs[5], &timeout);
- EXPECT_EQ(queue->Tail()->fs_[0].tracking_id, 5);
+ EXPECT_EQ(queue.back()->fs_[0].tracking_id, 5);
// Expecting Quick movement detected and ID correction 5 -> 4.
wrapper.SyncInterpret(&hs[6], &timeout);
- EXPECT_EQ(queue->Tail()->fs_[0].tracking_id, 4);
- EXPECT_EQ(queue->Tail()->prev_->fs_[0].tracking_id, 4);
- EXPECT_EQ(queue->Tail()->prev_->prev_->fs_[0].tracking_id, 4);
+ EXPECT_EQ(interpreter->queue_.at(-1)->fs_[0].tracking_id, 4);
+ EXPECT_EQ(interpreter->queue_.at(-2)->fs_[0].tracking_id, 4);
+ EXPECT_EQ(interpreter->queue_.at(-3)->fs_[0].tracking_id, 4);
}
struct QuickSwipeTestInputs {
@@ -1263,16 +1263,79 @@
wrapper.Reset(interpreter.get());
stime_t timeout = NO_DEADLINE;
- List<LookaheadFilterInterpreter::QState>* queue = &interpreter->queue_;
+ const auto& queue = interpreter->queue_;
wrapper.SyncInterpret(&hs[0], &timeout);
- EXPECT_EQ(queue->Tail()->fs_[0].tracking_id, 20);
+ EXPECT_EQ(queue.back()->fs_[0].tracking_id, 20);
// Test if the fingers in queue have the same tracking ids from input.
for (size_t i = 1; i < arraysize(hs); i++) {
wrapper.SyncInterpret(&hs[i], &timeout);
- EXPECT_EQ(queue->Tail()->fs_[0].tracking_id, 20); // the same input id
- EXPECT_EQ(queue->Tail()->fs_[1].tracking_id, 21);
+ EXPECT_EQ(queue.back()->fs_[0].tracking_id, 20); // the same input id
+ EXPECT_EQ(queue.back()->fs_[1].tracking_id, 21);
}
}
+
+TEST(LookaheadFilterInterpreterTest, QStateListTest) {
+ LookaheadFilterInterpreterTestInterpreter* base_interpreter = NULL;
+ std::unique_ptr<LookaheadFilterInterpreter> interpreter;
+
+ HardwareProperties hwprops = {
+ 0, 0, 100, 100, // left, top, right, bottom
+ 1, // x res (pixels/mm)
+ 1, // y res (pixels/mm)
+ 25, 25, // scrn DPI X, Y
+ -1, // orientation minimum
+ 2, // orientation maximum
+ 2, 5, // max fingers, max_touch
+ 1, 1, 0, // t5r2, semi, button pad
+ 0, 0, // has wheel, vertical wheel is high resolution
+ 0, // haptic pad
+ };
+ TestInterpreterWrapper wrapper(interpreter.get(), &hwprops);
+
+ base_interpreter = new LookaheadFilterInterpreterTestInterpreter;
+ interpreter.reset(new LookaheadFilterInterpreter(
+ NULL, base_interpreter, NULL));
+ wrapper.Reset(interpreter.get());
+
+ auto& queue = interpreter->queue_;
+ auto& free_list = interpreter->free_list_;
+
+ // Release all of the QStates
+ while (!queue.empty()) {
+ free_list.push_back(queue.front());
+ queue.pop_front();
+ }
+ EXPECT_EQ(queue.size(), 0);
+ EXPECT_EQ(free_list.size(), 16);
+
+ EXPECT_EQ(queue.at(-1), nullptr);
+ EXPECT_EQ(queue.at(queue.size()), nullptr);
+
+ // fill up the QStates
+ while (!free_list.empty()) {
+ queue.push_front(free_list.back());
+ free_list.pop_back();
+ }
+ EXPECT_EQ(queue.size(), 16);
+ EXPECT_EQ(free_list.size(), 0);
+
+ EXPECT_NE(queue.at(-1), nullptr);
+ EXPECT_EQ(queue.at(-1), queue.at(queue.size() - 1));
+
+ EXPECT_EQ(queue.at(queue.size()), nullptr);
+
+ for (int i = 0; i < 16; ++i) {
+ for (int j = 0; j < 16; ++j) {
+ if (i == j) {
+ EXPECT_EQ(queue.at(i), queue.at(j));
+ } else {
+ EXPECT_NE(queue.at(i), queue.at(j));
+ }
+ }
+ }
+
+ LookaheadFilterInterpreter::QState qs;
+}
} // namespace gestures
diff --git a/src/metrics_filter_interpreter.cc b/src/metrics_filter_interpreter.cc
index e608f23..de6ca33 100644
--- a/src/metrics_filter_interpreter.cc
+++ b/src/metrics_filter_interpreter.cc
@@ -142,7 +142,7 @@
RemoveMissingIdsFromMap(&histories_, hwstate, &removed);
for (FingerHistoryMap::const_iterator it =
removed.begin(); it != removed.end(); ++it) {
- it->second->DeleteAll();
+ it->second->clear();
history_mm_.Free(it->second);
}
@@ -171,14 +171,15 @@
bool MetricsFilterInterpreter::DetectNoisyGround(
const FingerHistory* history) {
- MState* current = history->Tail();
+ auto iter = history->end();
+ MState* current = *(--iter);
size_t n_samples = history->size();
// Noise pattern takes 3 samples
if (n_samples < 3)
return false;
- MState* past_1 = current->prev_;
- MState* past_2 = past_1->prev_;
+ MState* past_1 = *(--iter);
+ MState* past_2 = *(--iter);
// Noise pattern needs to happen in a short period of time
if(current->timestamp - past_2->timestamp >
noisy_ground_time_threshold_.val_) {
diff --git a/src/trend_classifying_filter_interpreter.cc b/src/trend_classifying_filter_interpreter.cc
index 45699a9..d6ddd21 100644
--- a/src/trend_classifying_filter_interpreter.cc
+++ b/src/trend_classifying_filter_interpreter.cc
@@ -78,7 +78,7 @@
history->DeleteFront();
// Push the new finger state to the back of buffer
- KState* previous_end = history->Tail();
+ KState* previous_end = history->back();
KState* current = history->PushNewEltBack();
if (!current) {
Err("KState buffer out of space");
@@ -94,10 +94,10 @@
// variance along the way. Complexity is O(|buffer|) per finger.
int tie_n2[KState::n_axes_] = { 0, 0, 0, 0, 0, 0 };
int tie_n3[KState::n_axes_] = { 0, 0, 0, 0, 0, 0 };
- for (KState* it = history->Begin(); it != history->Tail(); it = it->next_)
+ for (auto it = history->begin(); it != history->end(); ++it)
for (size_t i = 0; i < KState::n_axes_; i++)
- if(it != history->Begin() || !KState::IsDelta(i)) {
- UpdateKTValuePair(&it->axes_[i], ¤t->axes_[i],
+ if (it != history->begin() || !KState::IsDelta(i)) {
+ UpdateKTValuePair(&(*it)->axes_[i], ¤t->axes_[i],
&tie_n2[i], &tie_n3[i]);
}
size_t n_samples = history->size();
@@ -136,7 +136,7 @@
RemoveMissingIdsFromMap(&histories_, hwstate, &removed);
for (FingerHistoryMap::const_iterator it =
removed.begin(); it != removed.end(); ++it) {
- it->second->DeleteAll();
+ it->second->clear();
history_mm_.Free(it->second);
}
@@ -159,7 +159,7 @@
// Check if the score demonstrates statistical significance
AddNewStateToBuffer(hp, fs[i]);
- KState* current = hp->Tail();
+ KState* current = hp->back();
size_t n_samples = hp->size();
for (size_t idx = 0; idx < KState::n_axes_; idx++)
if (second_order_enable_.val_ || !KState::IsDelta(idx)) {