blob: ac56622735cd7b234e95e8e1eaf4ace93f53c59b [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* License); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef COMMON_CONTAINER_LIST_H
#define COMMON_CONTAINER_LIST_H
#include "common/allocator/page_arena.h"
#include "common/error_info/errno_define.h"
namespace common {
#define INVALID_NODE_PTR ((SimpleListNode *)0xABCDEF)
/*
* A very simple list.
* There are such scenarios:
* We prepare all data in the list, and pass the list as immutable
* parameters to other module or caller. We never do delete or complex
* push operations.
* for example:
* SchemaMgr::get_timeseries_by_tsid(TsID, list<ColumnDesc>&)
* SchemaMgr::create_aligned_timeseries(..., const list<char*>
* &measurement_list, ...)
*
* Note: not thread safe!
*/
template <class T>
class SimpleList {
private:
struct SimpleListNode {
T data_;
SimpleListNode *next_;
SimpleListNode() : next_(nullptr) {}
SimpleListNode(const T &data) : data_(data), next_(nullptr) {}
};
public:
class Iterator {
public:
Iterator(SimpleListNode *node) : cur_(node) {}
Iterator() : cur_(INVALID_NODE_PTR) {}
T &get() { return cur_->data_; }
FORCE_INLINE bool is_inited() const { return cur_ != INVALID_NODE_PTR; }
FORCE_INLINE Iterator &operator++(int n) {
if (LIKELY(cur_ != nullptr)) {
cur_ = cur_->next_;
}
return *this;
}
FORCE_INLINE bool operator!=(const Iterator &other) const {
return this->cur_ != other.cur_;
}
FORCE_INLINE bool operator==(const Iterator &other) const {
return this->cur_ == other.cur_;
}
private:
SimpleListNode *cur_;
};
public:
SimpleList(const uint32_t page_size, AllocModID mid)
: head_(nullptr), tail_(nullptr), size_(0) {
own_page_arena_.init(page_size, mid);
page_arena_ = &own_page_arena_;
}
SimpleList(PageArena *page_arena)
: page_arena_(page_arena), head_(nullptr), tail_(nullptr), size_(0) {
// page_arena_ should be destroy outside by caller
}
int push_back(const T &data) {
void *buf = page_arena_->alloc(sizeof(SimpleListNode));
if (UNLIKELY(buf == nullptr)) {
return common::E_OOM;
}
SimpleListNode *node = new (buf) SimpleListNode(data);
if (head_ == nullptr) {
head_ = node;
tail_ = node;
} else {
assert(tail_ != nullptr);
tail_->next_ = node;
tail_ = node;
}
size_++;
return error_info::E_OK;
}
FORCE_INLINE T &front() {
ASSERT(size_ > 0 && head_ != nullptr);
return head_->data_;
}
int remove(T target) {
if (head_ == nullptr) {
return common::E_NOT_EXIST;
}
SimpleListNode *prev = head_;
SimpleListNode *cur = head_->next_;
while (cur && cur->data_ != target) {
cur = cur->next_;
}
if (!cur) {
return common::E_NOT_EXIST;
}
prev->next_ = cur->next_;
size_--;
// cur is allocated from PageArena, it should not reclaim now
return error_info::E_OK;
}
FORCE_INLINE Iterator begin() const { return Iterator(head_); }
FORCE_INLINE Iterator end() const { return Iterator(nullptr); }
FORCE_INLINE bool empty() const { return size_ == 0; }
FORCE_INLINE uint32_t size() const { return size_; }
FORCE_INLINE void clear() {
head_ = nullptr;
tail_ = nullptr;
size_ = 0;
own_page_arena_.destroy();
}
private:
PageArena *page_arena_;
PageArena own_page_arena_;
SimpleListNode *head_;
SimpleListNode *tail_;
uint32_t size_;
};
} // end namespace common
#endif // COMMON_CONTAINER_LIST_H