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