aboutsummaryrefslogtreecommitdiffstats
path: root/libtransport/includes/hicn/transport/utils
diff options
context:
space:
mode:
Diffstat (limited to 'libtransport/includes/hicn/transport/utils')
-rw-r--r--libtransport/includes/hicn/transport/utils/CMakeLists.txt5
-rw-r--r--libtransport/includes/hicn/transport/utils/conversions.h2
-rw-r--r--libtransport/includes/hicn/transport/utils/enum_iterator.h43
-rw-r--r--libtransport/includes/hicn/transport/utils/event_thread.h63
-rw-r--r--libtransport/includes/hicn/transport/utils/file.h28
-rw-r--r--libtransport/includes/hicn/transport/utils/fixed_block_allocator.h209
-rw-r--r--libtransport/includes/hicn/transport/utils/linux.h4
-rw-r--r--libtransport/includes/hicn/transport/utils/membuf.h32
-rw-r--r--libtransport/includes/hicn/transport/utils/move_wrapper.h39
-rw-r--r--libtransport/includes/hicn/transport/utils/noncopyable.h29
-rw-r--r--libtransport/includes/hicn/transport/utils/object_pool.h25
-rw-r--r--libtransport/includes/hicn/transport/utils/shared_ptr_utils.h28
-rw-r--r--libtransport/includes/hicn/transport/utils/singleton.h39
-rw-r--r--libtransport/includes/hicn/transport/utils/string_utils.h2
14 files changed, 446 insertions, 102 deletions
diff --git a/libtransport/includes/hicn/transport/utils/CMakeLists.txt b/libtransport/includes/hicn/transport/utils/CMakeLists.txt
index 11a9b0f25..7094601f4 100644
--- a/libtransport/includes/hicn/transport/utils/CMakeLists.txt
+++ b/libtransport/includes/hicn/transport/utils/CMakeLists.txt
@@ -31,6 +31,11 @@ list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/fixed_block_allocator.h
${CMAKE_CURRENT_SOURCE_DIR}/event_thread.h
${CMAKE_CURRENT_SOURCE_DIR}/string_utils.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/file.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/shared_ptr_utils.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/move_wrapper.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/noncopyable.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/singleton.h
)
if(NOT WIN32)
diff --git a/libtransport/includes/hicn/transport/utils/conversions.h b/libtransport/includes/hicn/transport/utils/conversions.h
index 24b529206..52d3e3168 100644
--- a/libtransport/includes/hicn/transport/utils/conversions.h
+++ b/libtransport/includes/hicn/transport/utils/conversions.h
@@ -16,8 +16,8 @@
#pragma once
#include <hicn/transport/portability/portability.h>
-
#include <stdio.h>
+
#include <cstdint>
#include <string>
diff --git a/libtransport/includes/hicn/transport/utils/enum_iterator.h b/libtransport/includes/hicn/transport/utils/enum_iterator.h
new file mode 100644
index 000000000..5e108b088
--- /dev/null
+++ b/libtransport/includes/hicn/transport/utils/enum_iterator.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed 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.
+ */
+
+#include <type_traits>
+
+template <typename C, C begin_val, C end_val>
+class Iterator {
+ typedef typename std::underlying_type<C>::type val_t;
+ int val;
+
+ public:
+ Iterator(const C& f) : val(static_cast<val_t>(f)) {}
+
+ Iterator() : val(static_cast<val_t>(begin_val)) {}
+
+ Iterator operator++() {
+ ++val;
+ return *this;
+ }
+
+ C operator*() { return static_cast<C>(val); }
+
+ Iterator begin() { return *this; } // default ctor is good
+
+ Iterator end() {
+ static const Iterator endIter = ++Iterator(end_val); // cache it
+ return endIter;
+ }
+
+ bool operator!=(const Iterator& i) { return val != i.val; }
+}; \ No newline at end of file
diff --git a/libtransport/includes/hicn/transport/utils/event_thread.h b/libtransport/includes/hicn/transport/utils/event_thread.h
index 702c98f8d..bb6ab90ef 100644
--- a/libtransport/includes/hicn/transport/utils/event_thread.h
+++ b/libtransport/includes/hicn/transport/utils/event_thread.h
@@ -17,7 +17,11 @@
#include <hicn/transport/config.h>
#include <hicn/transport/errors/runtime_exception.h>
+#include <hicn/transport/utils/log.h>
+#ifndef ASIO_STANDALONE
+#define ASIO_STANDALONE
+#endif
#include <asio.hpp>
#include <memory>
#include <thread>
@@ -25,36 +29,58 @@
namespace utils {
class EventThread {
- private:
- // No copies
- EventThread(const EventThread&) = delete; // non construction-copyable
- EventThread& operator=(const EventThread&) = delete; // non copyable
-
public:
- explicit EventThread(asio::io_service& io_service)
+ EventThread(asio::io_service& io_service, bool detached = false)
: internal_io_service_(nullptr),
- io_service_(io_service),
+ io_service_(std::ref(io_service)),
work_(std::make_unique<asio::io_service::work>(io_service_)),
- thread_(nullptr) {
+ thread_(nullptr),
+ detached_(detached) {
run();
}
- explicit EventThread()
+ EventThread(bool detached = false)
: internal_io_service_(std::make_unique<asio::io_service>()),
- io_service_(*internal_io_service_),
+ io_service_(std::ref(*internal_io_service_)),
work_(std::make_unique<asio::io_service::work>(io_service_)),
- thread_(nullptr) {
+ thread_(nullptr),
+ detached_(detached) {
run();
}
+ EventThread(const EventThread&) = delete;
+ EventThread& operator=(const EventThread&) = delete;
+
+ EventThread(EventThread&& other)
+ : internal_io_service_(std::move(other.internal_io_service_)),
+ io_service_(std::move(other.io_service_)),
+ work_(std::move(other.work_)),
+ thread_(std::move(other.thread_)),
+ detached_(std::move(other.detached_)) {}
+
+ EventThread& operator=(EventThread&& other) {
+ internal_io_service_ = std::move(other.internal_io_service_);
+ io_service_ = std::move(other.io_service_);
+ work_ = std::move(other.work_);
+ thread_ = std::move(other.thread_);
+ detached_ = other.detached_;
+
+ return *this;
+ }
+
~EventThread() { stop(); }
void run() {
if (stopped()) {
- io_service_.reset();
+ io_service_.get().stopped();
}
- thread_ = std::make_unique<std::thread>([this]() { io_service_.run(); });
+ thread_ =
+ std::make_unique<std::thread>([this]() { io_service_.get().run(); });
+
+ if (detached_) {
+ thread_->detach();
+ }
}
std::thread::id getThreadId() const {
@@ -67,14 +93,12 @@ class EventThread {
template <typename Func>
void add(Func&& f) {
- // If the function f
- // TODO USe post in mac os, asio->post in xenial
- io_service_.post(std::forward<Func&&>(f));
+ io_service_.get().post(std::forward<Func&&>(f));
}
template <typename Func>
void tryRunHandlerNow(Func&& f) {
- io_service_.dispatch(std::forward<Func&&>(f));
+ io_service_.get().dispatch(std::forward<Func&&>(f));
}
void stop() {
@@ -87,15 +111,16 @@ class EventThread {
thread_.reset();
}
- bool stopped() { return io_service_.stopped(); }
+ bool stopped() { return io_service_.get().stopped(); }
asio::io_service& getIoService() { return io_service_; }
private:
std::unique_ptr<asio::io_service> internal_io_service_;
- asio::io_service& io_service_;
+ std::reference_wrapper<asio::io_service> io_service_;
std::unique_ptr<asio::io_service::work> work_;
std::unique_ptr<std::thread> thread_;
+ bool detached_;
};
} // namespace utils \ No newline at end of file
diff --git a/libtransport/includes/hicn/transport/utils/file.h b/libtransport/includes/hicn/transport/utils/file.h
new file mode 100644
index 000000000..4c73f33e8
--- /dev/null
+++ b/libtransport/includes/hicn/transport/utils/file.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed 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.
+ */
+
+#include <sys/stat.h>
+
+namespace utils {
+
+class File {
+ public:
+ static inline bool exists(const std::string& name) {
+ struct stat buffer;
+ return (stat(name.c_str(), &buffer) == 0);
+ }
+};
+
+} // namespace utils
diff --git a/libtransport/includes/hicn/transport/utils/fixed_block_allocator.h b/libtransport/includes/hicn/transport/utils/fixed_block_allocator.h
index 1ade1516e..b1df36493 100644
--- a/libtransport/includes/hicn/transport/utils/fixed_block_allocator.h
+++ b/libtransport/includes/hicn/transport/utils/fixed_block_allocator.h
@@ -5,104 +5,99 @@
#pragma once
#include <hicn/transport/portability/c_portability.h>
+#include <hicn/transport/utils/singleton.h>
#include <hicn/transport/utils/spinlock.h>
-
#include <stdint.h>
+
+#include <cassert>
#include <cstdlib>
#include <memory>
-#include <cassert>
namespace utils {
-template <std::size_t DEFAULT_SIZE = 512, std::size_t OBJECTS = 4096>
-class FixedBlockAllocator {
- FixedBlockAllocator(std::size_t size = DEFAULT_SIZE,
- std::size_t objects = OBJECTS)
- : block_size_(size < sizeof(void*) ? sizeof(long*) : size),
- object_size_(size),
- max_objects_(objects),
- p_head_(NULL),
- pool_index_(0),
- block_count_(0),
- blocks_in_use_(0),
- allocations_(0),
- deallocations_(0) {
- p_pool_ = (uint8_t*)new uint8_t[block_size_ * max_objects_];
- }
+template <std::size_t SIZE = 512, std::size_t OBJECTS = 4096>
+class FixedBlockAllocator
+ : public utils::Singleton<FixedBlockAllocator<SIZE, OBJECTS>> {
+ friend class utils::Singleton<FixedBlockAllocator<SIZE, OBJECTS>>;
public:
- static FixedBlockAllocator* getInstance() {
- if (!instance_) {
- instance_ = std::unique_ptr<FixedBlockAllocator>(
- new FixedBlockAllocator(DEFAULT_SIZE, OBJECTS));
+ ~FixedBlockAllocator() {
+ for (auto& p : p_pools_) {
+ delete[] p;
}
-
- return instance_.get();
}
- ~FixedBlockAllocator() { delete[] p_pool_; }
-
- TRANSPORT_ALWAYS_INLINE void* allocateBlock(size_t size = DEFAULT_SIZE) {
- assert(size <= DEFAULT_SIZE);
+ void* allocateBlock(size_t size = SIZE) {
+ assert(size <= SIZE);
uint32_t index;
+ SpinLock::Acquire locked(lock_);
void* p_block = pop();
if (!p_block) {
- if (pool_index_ < max_objects_) {
- {
- SpinLock::Acquire locked(lock_);
- index = pool_index_++;
- }
- p_block = (void*)(p_pool_ + (index * block_size_));
- } else {
- // TODO Consider increasing pool here instead of throwing an exception
- throw std::runtime_error("No more memory available from packet pool!");
+ if (TRANSPORT_EXPECT_FALSE(current_pool_index_ >= max_objects_)) {
+ // Allocate new memory block
+ TRANSPORT_LOGV("Allocating new block of %zu size", SIZE * OBJECTS);
+ p_pools_.emplace_front(
+ new typename std::aligned_storage<SIZE>::type[max_objects_]);
+ // reset current_pool_index_
+ current_pool_index_ = 0;
}
- }
- blocks_in_use_++;
- allocations_++;
+ auto& latest = p_pools_.front();
+ index = current_pool_index_++;
+ blocks_in_use_++;
+ allocations_++;
+ p_block = (void*)&latest[index];
+ }
return p_block;
}
- TRANSPORT_ALWAYS_INLINE void deallocateBlock(void* pBlock) {
+ void deallocateBlock(void* pBlock) {
+ SpinLock::Acquire locked(lock_);
push(pBlock);
- {
- SpinLock::Acquire locked(lock_);
- blocks_in_use_--;
- deallocations_++;
- }
+ blocks_in_use_--;
+ deallocations_++;
}
- TRANSPORT_ALWAYS_INLINE std::size_t blockSize() { return block_size_; }
+ public:
+ std::size_t blockSize() { return block_size_; }
- TRANSPORT_ALWAYS_INLINE uint32_t blockCount() { return block_count_; }
+ uint32_t blockCount() { return block_count_; }
- TRANSPORT_ALWAYS_INLINE uint32_t blocksInUse() { return blocks_in_use_; }
+ uint32_t blocksInUse() { return blocks_in_use_; }
- TRANSPORT_ALWAYS_INLINE uint32_t allocations() { return allocations_; }
+ uint32_t allocations() { return allocations_; }
- TRANSPORT_ALWAYS_INLINE uint32_t deallocations() { return deallocations_; }
+ uint32_t deallocations() { return deallocations_; }
private:
- TRANSPORT_ALWAYS_INLINE void push(void* p_memory) {
+ FixedBlockAllocator()
+ : block_size_(SIZE),
+ object_size_(SIZE),
+ max_objects_(OBJECTS),
+ p_head_(NULL),
+ current_pool_index_(0),
+ block_count_(0),
+ blocks_in_use_(0),
+ allocations_(0),
+ deallocations_(0) {
+ static_assert(SIZE >= sizeof(long*), "SIZE must be at least 8 bytes");
+ p_pools_.emplace_front(
+ new typename std::aligned_storage<SIZE>::type[max_objects_]);
+ }
+
+ void push(void* p_memory) {
Block* p_block = (Block*)p_memory;
- {
- SpinLock::Acquire locked(lock_);
- p_block->p_next = p_head_;
- p_head_ = p_block;
- }
+ p_block->p_next = p_head_;
+ p_head_ = p_block;
}
- TRANSPORT_ALWAYS_INLINE void* pop() {
+ void* pop() {
Block* p_block = nullptr;
- {
- SpinLock::Acquire locked(lock_);
- if (p_head_) {
- p_block = p_head_;
- p_head_ = p_head_->p_next;
- }
+ if (p_head_) {
+ p_block = p_head_;
+ p_head_ = p_head_->p_next;
}
return (void*)p_block;
@@ -119,8 +114,8 @@ class FixedBlockAllocator {
const std::size_t max_objects_;
Block* p_head_;
- uint8_t* p_pool_;
- uint32_t pool_index_;
+ uint32_t current_pool_index_;
+ std::list<typename std::aligned_storage<SIZE>::type*> p_pools_;
uint32_t block_count_;
uint32_t blocks_in_use_;
uint32_t allocations_;
@@ -133,4 +128,88 @@ template <std::size_t A, std::size_t B>
std::unique_ptr<FixedBlockAllocator<A, B>>
FixedBlockAllocator<A, B>::instance_ = nullptr;
+/**
+ * STL Allocator trait to be used with allocate_shared.
+ */
+template <typename T, typename Pool>
+class STLAllocator {
+ /**
+ * If STLAllocator is rebound to another type (!= T) using copy constructor,
+ * we may need to access private members of the source allocator to copy
+ * memory and pool.
+ */
+ template <typename U, typename P>
+ friend class STLAllocator;
+
+ public:
+ using size_type = std::size_t;
+ using difference_type = ptrdiff_t;
+ using pointer = T*;
+ using const_pointer = const T*;
+ using reference = T&;
+ using const_reference = const T&;
+ using value_type = T;
+
+ STLAllocator(pointer memory, Pool* memory_pool)
+ : memory_(memory), pool_(memory_pool) {
+ TRANSPORT_LOGV("Creating allocator. This: %p, memory: %p, memory_pool: %p",
+ this, memory, memory_pool);
+ }
+
+ ~STLAllocator() {}
+
+ template <typename U>
+ STLAllocator(const STLAllocator<U, Pool>& other) {
+ memory_ = other.memory_;
+ pool_ = other.pool_;
+ }
+
+ template <typename U>
+ struct rebind {
+ typedef STLAllocator<U, Pool> other;
+ };
+
+ pointer address(reference x) const { return &x; }
+ const_pointer address(const_reference x) const { return &x; }
+
+ pointer allocate(size_type n, pointer hint = 0) {
+ TRANSPORT_LOGV(
+ "Allocating memory (%zu). This: %p, memory: %p, memory_pool: %p", n,
+ this, memory_, pool_);
+ return static_cast<pointer>(memory_);
+ }
+
+ void deallocate(pointer p, size_type n) {
+ TRANSPORT_LOGV("Deallocating memory. This: %p, memory: %p, memory_pool: %p",
+ this, memory_, pool_);
+ pool_->deallocateBlock(memory_);
+ }
+
+ template <typename... Args>
+ void construct(pointer p, Args&&... args) {
+ new (static_cast<pointer>(p)) T(std::forward<Args>(args)...);
+ }
+
+ void destroy(pointer p) {
+ TRANSPORT_LOGV("Destroying object. This: %p, memory: %p, memory_pool: %p",
+ this, memory_, pool_);
+ p->~T();
+ }
+
+ private:
+ void* memory_;
+ Pool* pool_;
+};
+
+template <typename T, typename U, typename V>
+inline bool operator==(const STLAllocator<T, V>&, const STLAllocator<U, V>&) {
+ return true;
+}
+
+template <typename T, typename U, typename V>
+inline bool operator!=(const STLAllocator<T, V>& a,
+ const STLAllocator<U, V>& b) {
+ return !(a == b);
+}
+
} // namespace utils \ No newline at end of file
diff --git a/libtransport/includes/hicn/transport/utils/linux.h b/libtransport/includes/hicn/transport/utils/linux.h
index 5820528e1..105196fd2 100644
--- a/libtransport/includes/hicn/transport/utils/linux.h
+++ b/libtransport/includes/hicn/transport/utils/linux.h
@@ -17,14 +17,14 @@
#ifdef __linux__
+#include <arpa/inet.h>
#include <hicn/transport/portability/portability.h>
#include <hicn/transport/utils/log.h>
-
-#include <arpa/inet.h>
#include <ifaddrs.h>
#include <netdb.h>
#include <stdio.h>
#include <sys/socket.h>
+
#include <string>
#define LINK_LOCAL_PREFIX 0xfe80
diff --git a/libtransport/includes/hicn/transport/utils/membuf.h b/libtransport/includes/hicn/transport/utils/membuf.h
index 9fc37dd25..0db87e9dd 100644
--- a/libtransport/includes/hicn/transport/utils/membuf.h
+++ b/libtransport/includes/hicn/transport/utils/membuf.h
@@ -23,6 +23,7 @@
#include <hicn/transport/portability/portability.h>
#include <hicn/transport/utils/branch_prediction.h>
+#include <stdlib.h>
#include <atomic>
#include <cassert>
@@ -35,8 +36,6 @@
#include <type_traits>
#include <vector>
-#include <stdlib.h>
-
#ifndef _WIN32
TRANSPORT_GNU_DISABLE_WARNING("-Wshadow")
#endif
@@ -50,6 +49,8 @@ class MemBuf {
enum TakeOwnershipOp { TAKE_OWNERSHIP };
enum CopyBufferOp { COPY_BUFFER };
+ using Ptr = std::shared_ptr<MemBuf>;
+
typedef void (*FreeFunction)(void* buf, void* userData);
static std::unique_ptr<MemBuf> create(std::size_t capacity);
@@ -106,13 +107,14 @@ class MemBuf {
FreeFunction freeFn = nullptr, void* userData = nullptr,
bool freeOnError = true);
- static std::unique_ptr<MemBuf> wrapBuffer(const void* buf,
+ static std::unique_ptr<MemBuf> wrapBuffer(const void* buf, std::size_t length,
std::size_t capacity);
- static MemBuf wrapBufferAsValue(const void* buf,
+ static MemBuf wrapBufferAsValue(const void* buf, std::size_t length,
std::size_t capacity) noexcept;
- MemBuf(WrapBufferOp op, const void* buf, std::size_t capacity) noexcept;
+ MemBuf(WrapBufferOp op, const void* buf, std::size_t length,
+ std::size_t capacity) noexcept;
/**
* Convenience function to create a new MemBuf object that copies data from a
@@ -147,6 +149,8 @@ class MemBuf {
std::size_t length() const { return length_; }
+ void setLength(std::size_t length) { length_ = length; }
+
std::size_t headroom() const { return std::size_t(data_ - buffer()); }
std::size_t tailroom() const { return std::size_t(bufferEnd() - tail()); }
@@ -689,6 +693,18 @@ class MemBuf {
void* userData = nullptr,
bool freeOnError = true);
+ /**
+ * Ensure the current MemBuf can hold at least capacity bytes and its
+ * memory is contiguous
+ */
+ bool ensureCapacity(std::size_t capacity);
+
+ /**
+ * Ensure packet buffer can hold at least 1500 bytes in contiguous memory and
+ * fill unused memory with placeholder
+ */
+ bool ensureCapacityAndFillUnused(std::size_t capacity, uint8_t placeholder);
+
/*
* Overridden operator new and delete.
* These perform specialized memory management to help support
@@ -700,6 +716,12 @@ class MemBuf {
void operator delete(void* ptr);
void operator delete(void* ptr, void* placement);
+ /**
+ * Override operator == and !=
+ */
+ bool operator ==(const MemBuf &other);
+ bool operator !=(const MemBuf &other);
+
// /**
// * Iteration support: a chain of MemBufs may be iterated through using
// * STL-style iterators over const ByteRanges. Iterators are only
diff --git a/libtransport/includes/hicn/transport/utils/move_wrapper.h b/libtransport/includes/hicn/transport/utils/move_wrapper.h
new file mode 100644
index 000000000..3aba345d6
--- /dev/null
+++ b/libtransport/includes/hicn/transport/utils/move_wrapper.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright 2017 Facebook, Inc.
+ *
+ * Licensed 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.
+ */
+
+#pragma once
+
+#include <type_traits>
+
+namespace utils {
+
+template <typename F>
+struct MoveWrapper : F {
+ MoveWrapper(F&& f) : F(std::move(f)) {}
+
+ MoveWrapper(MoveWrapper&&) = default;
+ MoveWrapper& operator=(MoveWrapper&&) = default;
+
+ MoveWrapper(const MoveWrapper&);
+ MoveWrapper& operator=(const MoveWrapper&);
+};
+
+template <typename T>
+auto moveHandler(T&& t) -> MoveWrapper<typename std::decay<T>::type> {
+ return std::move(t);
+}
+} // namespace utils \ No newline at end of file
diff --git a/libtransport/includes/hicn/transport/utils/noncopyable.h b/libtransport/includes/hicn/transport/utils/noncopyable.h
new file mode 100644
index 000000000..83923e647
--- /dev/null
+++ b/libtransport/includes/hicn/transport/utils/noncopyable.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed 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.
+ */
+
+#pragma once
+
+namespace utils {
+
+class NonCopyable {
+ protected:
+ NonCopyable() = default;
+ ~NonCopyable() = default;
+
+ NonCopyable(const NonCopyable&) = delete;
+ NonCopyable& operator=(const NonCopyable&) = delete;
+};
+
+} // namespace utils
diff --git a/libtransport/includes/hicn/transport/utils/object_pool.h b/libtransport/includes/hicn/transport/utils/object_pool.h
index f78bd2aa2..a5e8b2eef 100644
--- a/libtransport/includes/hicn/transport/utils/object_pool.h
+++ b/libtransport/includes/hicn/transport/utils/object_pool.h
@@ -17,6 +17,7 @@
// TODO
#include <hicn/transport/utils/branch_prediction.h>
+#include <hicn/transport/utils/log.h>
#include <hicn/transport/utils/spinlock.h>
#include <deque>
@@ -33,6 +34,7 @@ class ObjectPool {
void operator()(T *t) {
if (pool_) {
+ TRANSPORT_LOGV("Back in pool");
pool_->add(t);
} else {
delete t;
@@ -44,10 +46,13 @@ class ObjectPool {
};
public:
- using Ptr = std::unique_ptr<T, ObjectDeleter>;
+ using Ptr = std::shared_ptr<T>;
ObjectPool() : destructor_(false) {}
+ // No copies
+ ObjectPool(const ObjectPool &other) = delete;
+
~ObjectPool() {
destructor_ = true;
for (auto &ptr : object_pool_) {
@@ -55,12 +60,17 @@ class ObjectPool {
}
}
+ bool empty() {
+ utils::SpinLock::Acquire locked(object_pool_lock_);
+ return object_pool_.empty();
+ }
+
std::pair<bool, Ptr> get() {
+ utils::SpinLock::Acquire locked(object_pool_lock_);
if (object_pool_.empty()) {
- return std::make_pair<bool, Ptr>(false, makePtr(nullptr));
+ return std::make_pair<bool, Ptr>(false, nullptr);
}
- utils::SpinLock::Acquire locked(object_pool_lock_);
auto ret = std::move(object_pool_.front());
object_pool_.pop_front();
return std::make_pair<bool, Ptr>(true, std::move(ret));
@@ -70,7 +80,7 @@ class ObjectPool {
utils::SpinLock::Acquire locked(object_pool_lock_);
if (TRANSPORT_EXPECT_TRUE(!destructor_)) {
- object_pool_.emplace_back(makePtr(object));
+ object_pool_.emplace_front(makePtr(object));
} else {
delete object;
}
@@ -79,12 +89,9 @@ class ObjectPool {
Ptr makePtr(T *object) { return Ptr(object, ObjectDeleter(this)); }
private:
- // No copies
- ObjectPool(const ObjectPool &other) = delete;
-
utils::SpinLock object_pool_lock_;
std::deque<Ptr> object_pool_;
- bool destructor_;
+ std::atomic<bool> destructor_;
};
-} // namespace utils \ No newline at end of file
+} // namespace utils
diff --git a/libtransport/includes/hicn/transport/utils/shared_ptr_utils.h b/libtransport/includes/hicn/transport/utils/shared_ptr_utils.h
new file mode 100644
index 000000000..3387997b5
--- /dev/null
+++ b/libtransport/includes/hicn/transport/utils/shared_ptr_utils.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ */
+
+#pragma once
+
+#include <memory>
+
+namespace utils {
+
+template <typename Base>
+inline std::shared_ptr<Base> shared_from_base(
+ std::enable_shared_from_this<Base>* base) {
+ return base->shared_from_this();
+}
+
+template <typename Base>
+inline std::shared_ptr<const Base> shared_from_base(
+ std::enable_shared_from_this<Base> const* base) {
+ return base->shared_from_this();
+}
+
+template <typename That>
+inline std::shared_ptr<That> shared_from(That* that) {
+ return std::static_pointer_cast<That>(shared_from_base(that));
+}
+
+} // namespace utils \ No newline at end of file
diff --git a/libtransport/includes/hicn/transport/utils/singleton.h b/libtransport/includes/hicn/transport/utils/singleton.h
new file mode 100644
index 000000000..7fd8b912f
--- /dev/null
+++ b/libtransport/includes/hicn/transport/utils/singleton.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed 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.
+ */
+
+#pragma once
+
+#include <hicn/transport/utils/noncopyable.h>
+
+namespace utils {
+
+template <typename T>
+class Singleton {
+ public:
+ static T& getInstance() {
+ static T instance;
+ return instance;
+ }
+
+ protected:
+ Singleton() {}
+ ~Singleton() {}
+
+ public:
+ Singleton(Singleton const&) = delete;
+ Singleton& operator=(Singleton const&) = delete;
+};
+
+} // namespace utils \ No newline at end of file
diff --git a/libtransport/includes/hicn/transport/utils/string_utils.h b/libtransport/includes/hicn/transport/utils/string_utils.h
index bfda816f1..313c28cc6 100644
--- a/libtransport/includes/hicn/transport/utils/string_utils.h
+++ b/libtransport/includes/hicn/transport/utils/string_utils.h
@@ -72,4 +72,4 @@ static inline std::string trim_copy(std::string s) {
return s;
}
-} \ No newline at end of file
+} // namespace utils \ No newline at end of file