From 1d028c6a200bb93cf155121d241fc8b3ed1f4396 Mon Sep 17 00:00:00 2001 From: yang li Date: Fri, 19 Apr 2019 14:53:04 +0800 Subject: [PATCH] Use std::forward_list instead of std::list, and implement size concept like boost::container::slist does. --- examples/client/client.cpp | 119 +++++++++++++++++++++++++++++++++++++ include/ascs/base.h | 5 +- include/ascs/container.h | 14 ++--- include/ascs/ext/ext.h | 2 + include/ascs/ext/packer.h | 6 +- include/ascs/list.h | 115 +++++++++++++++++++++++++++++++++++ include/ascs/socket.h | 2 +- 7 files changed, 248 insertions(+), 15 deletions(-) create mode 100644 include/ascs/list.h diff --git a/examples/client/client.cpp b/examples/client/client.cpp index b7d2ed1..895fdbe 100644 --- a/examples/client/client.cpp +++ b/examples/client/client.cpp @@ -169,3 +169,122 @@ int main(int argc, const char* argv[]) return 0; } +/* +#include +using namespace ascs; + +void print_list(const list& l) +{ + if (!l.empty()) + { + for (auto& item : l) + printf("%d ", item); + printf(": %d %Iu\n", l.back(), l.size()); + } + else + printf("empty list: %Iu\n", l.size()); +} + +void test1() +{ + list l; + l.push_back(0); + l.push_back(1); + l.push_back(2); + print_list(l); + + list l2; + l2.push_back(10); + l2.push_back(11); + l2.push_back(12); + print_list(l2); + + l.splice_after(l2); + print_list(l); + print_list(l2); +} + +void test2() +{ + list l; + l.push_back(0); + l.push_back(1); + l.push_back(2); + print_list(l); + + list l2; + l2.push_back(10); + l2.push_back(11); + l2.push_back(12); + print_list(l2); + + l.splice_after_until(l2, std::begin(l2)); + print_list(l); + print_list(l2); +} + +void test3() +{ + list l; + l.push_back(0); + l.push_back(1); + l.push_back(2); + print_list(l); + + list l2; + l2.push_back(10); + l2.push_back(11); + l2.push_back(12); + print_list(l2); + + auto iter = std::begin(l2); + l.splice_after_until(l2, ++iter); + print_list(l); + print_list(l2); +} + +void test4() +{ + list l; + l.push_back(0); + l.push_back(1); + l.push_back(2); + print_list(l); + + list l2; + l2.push_back(10); + l2.push_back(11); + l2.push_back(12); + print_list(l2); + + l.splice_after_until(l2, std::end(l2)); + print_list(l); + print_list(l2); +} + +void test5() +{ + list l, l2; + l2.push_back(10); + l2.push_back(11); + l2.push_back(12); + print_list(l2); + + l.splice_after_until(l2, std::end(l2)); + print_list(l); + print_list(l2); +} + +int main(int argc, const char* argv[]) +{ + typedef void (*TEST_FUN) (); + TEST_FUN tests[] = {&test1, &test2, &test3, &test4, &test5}; + for (size_t i = 0; i < sizeof(tests) / sizeof(TEST_FUN); ++i) + { + (*tests[i])(); + puts(""); + } + + return 0; +} +*/ diff --git a/include/ascs/base.h b/include/ascs/base.h index 0722c2c..1e65554 100644 --- a/include/ascs/base.h +++ b/include/ascs/base.h @@ -16,7 +16,6 @@ #include #include -#include #include #include #include @@ -35,6 +34,7 @@ #include #include "config.h" +#include "list.h" namespace ascs { @@ -159,9 +159,6 @@ protected: buffer_type buffer; }; -//ascs requires that container must take one and only one template argument -template using list = std::list; - //packer concept template class i_packer diff --git a/include/ascs/container.h b/include/ascs/container.h index 76a3c63..4134a4b 100644 --- a/include/ascs/container.h +++ b/include/ascs/container.h @@ -43,15 +43,15 @@ private: std::mutex mutex; //std::mutex is more efficient than std::shared_(timed_)mutex }; -//Container must at least has the following functions (like std::list): +//Container must at least has the following functions (like std::forward_list): // Container() and Container(size_t) constructor // empty, must be thread safe, but doesn't have to be consistent // clear // swap // template emplace_back(const T& item), if you call direct_(sync_)send_msg which accepts other than rvalue reference // template emplace_back(T&& item) -// splice(iter, Container&) -// splice(iter, Container&, iter, iter) +// splice_after(Container&) +// splice_after_until(Container&, iter) // front // pop_front // back @@ -117,7 +117,7 @@ public: else assert(ascs::get_size_in_byte(src) == size_in_byte); - this->splice(this->end(), src); + this->splice_after(src); total_size += size_in_byte; } @@ -127,7 +127,7 @@ public: { if ((size_t) -1 == max_item_num) { - dest.splice(std::end(dest), *this); + dest.splice_after(*this); total_size = 0; } else if (max_item_num > 0) @@ -173,9 +173,9 @@ protected: #endif { if (end_iter == this->end()) - dest.splice(std::end(dest), *this); + dest.splice_after(*this); else - dest.splice(std::end(dest), *this, this->begin(), end_iter); + dest.splice_after_until(*this, end_iter); total_size -= size; } diff --git a/include/ascs/ext/ext.h b/include/ascs/ext/ext.h index 2b44745..03d891a 100644 --- a/include/ascs/ext/ext.h +++ b/include/ascs/ext/ext.h @@ -13,6 +13,8 @@ #ifndef _ASCS_EXT_H_ #define _ASCS_EXT_H_ +#include + #include "../base.h" //the size of the buffer used when receiving msg, must equal to or larger than the biggest msg size, diff --git a/include/ascs/ext/packer.h b/include/ascs/ext/packer.h index e7cf868..5beae79 100644 --- a/include/ascs/ext/packer.h +++ b/include/ascs/ext/packer.h @@ -125,7 +125,7 @@ public: auto head_len = packer_helper::pack_header(len); out.emplace_back((const char*) &head_len, ASCS_HEAD_LEN); - out.splice(std::end(out), in); + out.splice_after(in); return true; } @@ -193,7 +193,7 @@ public: auto raw_msg = new string_buffer(); raw_msg->assign((const char*) &head_len, ASCS_HEAD_LEN); out.emplace_back(raw_msg); - out.splice(std::end(out), in); + out.splice_after(in); return true; } @@ -293,7 +293,7 @@ public: if (!_prefix.empty()) out.emplace_back(_prefix); - out.splice(std::end(out), in); + out.splice_after(in); if (!_suffix.empty()) out.emplace_back(_suffix); diff --git a/include/ascs/list.h b/include/ascs/list.h new file mode 100644 index 0000000..713dfd1 --- /dev/null +++ b/include/ascs/list.h @@ -0,0 +1,115 @@ +/* + * base.h + * + * Created on: 2019-4-18 + * Author: youngwolf + * email: mail2tao@163.com + * QQ: 676218192 + * Community on QQ: 198941541 + * + * forward list, but has size, push_back and emplace_back functions. + */ + +#ifndef _ASCS_LIST_H_ +#define _ASCS_LIST_H_ + +#include + +namespace ascs +{ + +//ascs requires that container must take one and only one template argument +template +class list : protected std::forward_list +{ +private: + typedef std::forward_list super; + +public: + using typename super::value_type; + using typename super::size_type; + using typename super::reference; + using typename super::const_reference; + using typename super::iterator; + using typename super::const_iterator; + + using super::empty; + using super::max_size; + using super::begin; + using super::cbegin; + using super::front; + using super::end; + using super::cend; + +public: + list() {refresh_status();} + list(size_type count) : super(count) {refresh_status();} + + list(super&& other) {swap(other);} + list(const super& other) {*this = other;} + list(list&& other) {refresh_status(); swap(other);} + list(const list& other) {*this = other;} + + list& operator=(super&& other) {super::clear(); swap(other); return *this;} + list& operator=(const super& other) {super::operator=(other); refresh_status(); return *this;} + list& operator=(list&& other) {clear(); swap(other); return *this;} + list& operator=(const list& other) {super::operator=(other); refresh_status(); return *this;} + + void swap(super& other) {super::swap(other); refresh_status();} + void swap(list& other) {super::swap(other); std::swap(s, other.s); std::swap(back_iter, other.back_iter);} + + void refresh_status() + { + s = 0; + back_iter = this->before_begin(); + for (auto iter = std::begin(*this); iter != std::end(*this); ++iter, ++back_iter) + ++s; + } + + void clear() {super::clear(); refresh_status();} + size_type size() const {return s;} + + void push_front(T&& _Val) {super::push_front(std::forward(_Val)); if (1 == ++s) back_iter = std::begin(*this);} + template void emplace_front(_Valty&&... _Val) {super::emplace_front(std::forward<_Valty>(_Val)...); if (1 == ++s) back_iter = std::begin(*this);} + void pop_front() {super::pop_front(); if (0 == --s) back_iter = std::end(*this);} + + void push_back(T&& _Val) {back_iter = this->insert_after(1 == ++s ? this->cbefore_begin() : back_iter, std::forward(_Val));} + template void emplace_back(_Valty&& ... _Val) {back_iter = this->emplace_after(1 == ++s ? this->cbefore_begin() : back_iter, std::forward<_Valty>(_Val)...);} + reference back() {return *back_iter;} + const_reference back() const {return *back_iter;} + + void splice_after(super& other) + { + if (!other.empty()) + { + super::splice_after(empty() ? this->cbefore_begin() : back_iter, other); + refresh_status(); + } + } +#ifdef _MSC_VER + void splice_after(list& other) {splice_after((super&) other); other.refresh_status();} +#else + void splice_after(list& other) + { + if (!other.empty()) + { + s += other.s; + super::splice_after(empty() ? this->cbefore_begin() : back_iter, other); + back_iter = other.back_iter; + + other.refresh_status(); + } + } +#endif + + void splice_after_until(super& other, const_iterator last) {super::splice_after(empty() ? this->cbefore_begin() : back_iter, other, other.cbefore_begin(), last); refresh_status();} + void splice_after_until(list& other, const_iterator last) {splice_after_until((super&) other, last); other.refresh_status();} + +private: + size_type s; + iterator back_iter; //for empty list, this item can be either before_begin() or end(), please note. +}; + +} //namespace + +#endif /* _ASCS_LIST_H_ */ diff --git a/include/ascs/socket.h b/include/ascs/socket.h index 42e35d6..8d3ba2e 100644 --- a/include/ascs/socket.h +++ b/include/ascs/socket.h @@ -246,7 +246,7 @@ public: sr_status = sync_recv_status::REQUESTED; auto re = sync_recv_waiting(lock, duration); if (sync_call_result::SUCCESS == re) - msg_can.splice(std::end(msg_can), temp_msg_can); + msg_can.splice_after(temp_msg_can); sr_status = sync_recv_status::NOT_REQUESTED; sync_recv_cv.notify_one(); -- GitLab