Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions yasio/array_buffer.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#pragma once

#include "yasio/vector.hpp"
#include "yasio/buffer_alloc.hpp"
#include <type_traits>

namespace yasio
{
// alias: array_buffer
template <typename _Ty, typename _Alloc = yasio::crt_buffer_allocator<_Ty>>
using array_buffer = typename std::enable_if<std::is_trivially_copyable<_Ty>::value, ::yasio::vector<_Ty, _Alloc>>::type;
} // namespace yasio
13 changes: 8 additions & 5 deletions yasio/bindings/yasio_axlua.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,11 @@ SOFTWARE.
# if !__has_attribute(format)
# undef __has_attribute
# endif
#include "cocos2d.h"
using namespace cocos2d;

#include "axmol/base/Director.h"
#include "axmol/base/Scheduler.h"

using namespace ax;

namespace lyasio
{
Expand Down Expand Up @@ -72,7 +75,7 @@ static TIMER_ID loop(unsigned int n, float interval, vcallback_t callback)

auto timerId = reinterpret_cast<TIMER_ID>(++TimerObject::s_timerId);

std::string key = StringUtils::format("LSTMR#%p", timerId);
std::string key = fmt::format("LSTMR#{}", fmt::ptr(timerId));

Director::getInstance()->getScheduler()->schedule(
[timerObj](
Expand All @@ -93,7 +96,7 @@ static TIMER_ID delay(float delay, vcallback_t callback)
yasio::ref_ptr<TimerObject> timerObj(new TimerObject(std::move(callback)));
auto timerId = reinterpret_cast<TIMER_ID>(++TimerObject::s_timerId);

std::string key = StringUtils::format("LSTMR#%p", timerId);
std::string key = fmt::format("LSTMR#{}", fmt::ptr(timerId));
Director::getInstance()->getScheduler()->schedule(
[timerObj](
float /*dt*/) { // lambda expression hold the reference of timerObj automatically.
Expand All @@ -108,7 +111,7 @@ static TIMER_ID delay(float delay, vcallback_t callback)

static void kill(TIMER_ID timerId)
{
std::string key = StringUtils::format("LSTMR#%p", timerId);
std::string key = fmt::format("LSTMR#{}", fmt::ptr(timerId));
Director::getInstance()->getScheduler()->unschedule(key, STIMER_TARGET_VALUE);
}
YASIO_LUA_API void clear()
Expand Down
108 changes: 38 additions & 70 deletions yasio/buffer_alloc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,83 +36,51 @@ SOFTWARE.
#include "yasio/compiler/feature_test.hpp"
#include "yasio/type_traits.hpp"

#define _YASIO_VERIFY_RANGE(cond, mesg) \
do \
{ \
if (cond) \
; /* contextually convertible to bool paranoia */ \
else \
{ \
throw std::out_of_range(mesg); \
} \
\
} while (false)

namespace yasio
{
template <typename _Alty>
struct buffer_allocator_traits {
using value_type = typename _Alty::value_type;
using size_type = size_t;
static YASIO__CONSTEXPR size_type max_size() { return static_cast<size_type>(-1) / sizeof(value_type); }
static value_type* reallocate(void* block, size_t size, size_t new_size)
{
return static_cast<value_type*>(_Alty::reallocate(block, size, new_size * sizeof(value_type)));
}
static void deallocate(void* block, size_t size) { _Alty::deallocate(block, size); }
};
template <typename _Ty, enable_if_t<std::is_trivially_copyable<_Ty>::value, int> = 0>
struct buffer_allocator {
using value_type = _Ty;
static value_type* reallocate(void* block, size_t /*size*/, size_t new_size)
{
return static_cast<value_type*>(::realloc(block, new_size * sizeof(value_type)));
}
static void deallocate(void* block, size_t /*size*/) { ::free(block); }
};
template <typename _Ty, enable_if_t<std::is_trivially_copyable<_Ty>::value, int> = 0>
struct std_buffer_allocator {
using value_type = _Ty;
static value_type* reallocate(void* block, size_t size, size_t new_size)
{
if (!block)
return new (std::nothrow) value_type[new_size];
void* new_block = nullptr;
if (new_size)
{
if (new_size <= size)
return block;
new_block = new (std::nothrow) value_type[new_size];
if (new_block)
memcpy(new_block, block, size);
}
delete[] (value_type*)block;
return (value_type*)new_block;
}
static void deallocate(void* block, size_t /*size*/) { delete[] (value_type*)block; }
};
template <typename _Ty, bool = true>
struct construct_helper {
template <typename... Args>
static _Ty* construct_at(_Ty* p, Args&&... args)
template <typename T>
struct crt_buffer_allocator {
using value_type = T;
using pointer = T*;
using const_pointer = const T*;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;

// allocate n elements using CRT malloc
pointer allocate(size_type n)
{
return ::new (static_cast<void*>(p)) _Ty(std::forward<Args>(args)...);
if (n > max_size())
throw std::bad_alloc();
void* p = ::malloc(n * sizeof(T));
if (!p)
throw std::bad_alloc();
return static_cast<pointer>(p);
}
};
template <typename _Ty>
struct construct_helper<_Ty, false> {
template <typename... Args>
static _Ty* construct_at(_Ty* p, Args&&... args)

// deallocate memory using CRT free
void deallocate(pointer p, size_type /*n*/) noexcept { ::free(p); }

// optional reallocate (non-standard, but useful for vector)
pointer reallocate(pointer p, size_type old_count, size_type new_count)
{
return ::new (static_cast<void*>(p)) _Ty{std::forward<Args>(args)...};
void* np = ::realloc(p, new_count * sizeof(T));
if (!np)
throw std::bad_alloc();
return static_cast<pointer>(np);
}
};

template <typename _Ty, typename... Args>
inline _Ty* construct_at(_Ty* p, Args&&... args)
{
return construct_helper<_Ty, std::is_constructible<_Ty, Args&&...>::value>::construct_at(p, std::forward<Args>(args)...);
}
// max_size consistent with std::allocator
size_type max_size() const noexcept { return static_cast<size_type>(-1) / sizeof(T); }

// equality operators required by standard
template <class U>
struct rebind {
using other = crt_buffer_allocator<U>;
};

bool operator==(const crt_buffer_allocator&) const noexcept { return true; }
bool operator!=(const crt_buffer_allocator&) const noexcept { return false; }
};

} // namespace yasio

Expand Down
8 changes: 4 additions & 4 deletions yasio/byte_buffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ SOFTWARE.
*/
#ifndef YASIO__BYTE_BUFFER_HPP
#define YASIO__BYTE_BUFFER_HPP
#include "yasio/pod_vector.hpp"
#include "yasio/array_buffer.hpp"

namespace yasio
{

template <typename _Ty, typename _Alloc = buffer_allocator<_Ty>, enable_if_t<is_byte_type<_Ty>::value, int> = 0>
using basic_byte_buffer = array_buffer<_Ty, _Alloc>;
// basic_byte_buffer restricted to byte types
template <typename _Ty, typename _Alloc = yasio::crt_buffer_allocator<_Ty>>
using basic_byte_buffer = typename std::enable_if<is_byte_type<_Ty>::value, array_buffer<_Ty, _Alloc>>::type;

using sbyte_buffer = basic_byte_buffer<char>;
using byte_buffer = basic_byte_buffer<unsigned char>;
Expand Down
8 changes: 4 additions & 4 deletions yasio/impl/poll_io_watcher.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// Copyright (c) 2012-2025 HALX99 (halx99 at live dot com)
#ifndef YASIO__POLL_IO_WATCHER_HPP
#define YASIO__POLL_IO_WATCHER_HPP
#include "yasio/pod_vector.hpp"
#include "yasio/vector.hpp"
#include "yasio/impl/socket.hpp"
#include "yasio/impl/select_interrupter.hpp"

Expand Down Expand Up @@ -77,7 +77,7 @@ class poll_io_watcher {
}
return underlying_events;
}
static void pollfd_mod(yasio::pod_vector<pollfd>& fdset, socket_native_type fd, int add_events, int remove_events)
static void pollfd_mod(yasio::vector<pollfd>& fdset, socket_native_type fd, int add_events, int remove_events)
{
auto it = std::find_if(fdset.begin(), fdset.end(), [fd](const pollfd& pfd) { return pfd.fd == fd; });
if (it != fdset.end())
Expand All @@ -96,8 +96,8 @@ class poll_io_watcher {
}

protected:
yasio::pod_vector<pollfd> events_;
yasio::pod_vector<pollfd> revents_;
yasio::vector<pollfd> events_;
yasio::vector<pollfd> revents_;

select_interrupter interrupter_;
};
Expand Down
144 changes: 142 additions & 2 deletions yasio/memory.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//////////////////////////////////////////////////////////////////////////////////////////
// A multi-platform support c++11 library with focus on asynchronous socket I/O for any
// A multi-platform support c++11 library with focus on asynchronous socket I/O for any
// client application.
//////////////////////////////////////////////////////////////////////////////////////////
/*
Expand Down Expand Up @@ -35,11 +35,151 @@ SOFTWARE.
#if !YASIO__HAS_CXX14
namespace cxx14
{
template <typename _Ty, typename... _Args> std::unique_ptr<_Ty> make_unique(_Args&&... args)
template <typename _Ty, typename... _Args>
std::unique_ptr<_Ty> make_unique(_Args&&... args)
{
return std::unique_ptr<_Ty>(new _Ty(std::forward<_Args>(args)...));
}
} // namespace cxx14
#endif

namespace yasio
{
template <typename _Ty, bool = true>
struct construct_helper {
template <typename... Args>
static _Ty* construct_at(_Ty* p, Args&&... args)
{
return ::new (static_cast<void*>(p)) _Ty(std::forward<Args>(args)...);
}
};
template <typename _Ty>
struct construct_helper<_Ty, false> {
template <typename... Args>
static _Ty* construct_at(_Ty* p, Args&&... args)
{
return ::new (static_cast<void*>(p)) _Ty{std::forward<Args>(args)...};
}
};

template <typename _Ty, typename... Args>
inline _Ty* construct_at(_Ty* p, Args&&... args)
{
return construct_helper<_Ty, std::is_constructible<_Ty, Args&&...>::value>::construct_at(p, std::forward<Args>(args)...);
}

/** compressed_pair
* stores two objects, but applies Empty Base Optimization(EBO) when one of them is an empty type.
* This reduces memory overhead.
*/
template <class _Ty1, class _Ty2, bool = std::is_empty_v<_Ty1> && !std::is_final_v<_Ty1>, bool = std::is_empty_v<_Ty2> && !std::is_final_v<_Ty2>>
class compressed_pair;

// Case 1: neither empty
template <class _Ty1, class _Ty2>
class compressed_pair<_Ty1, _Ty2, false, false> {
_Ty1 _Myval1;
_Ty2 _Myval2;

public:
// constructors
constexpr compressed_pair() = default;

constexpr compressed_pair(const _Ty1& v1, const _Ty2& v2) noexcept(std::is_nothrow_copy_constructible_v<_Ty1> && std::is_nothrow_copy_constructible_v<_Ty2>)
: _Myval1(v1), _Myval2(v2)
{}

constexpr compressed_pair(_Ty1&& v1, _Ty2&& v2) noexcept(std::is_nothrow_move_constructible_v<_Ty1> && std::is_nothrow_move_constructible_v<_Ty2>)
: _Myval1(std::move(v1)), _Myval2(std::move(v2))
{}

template <class U1, class U2>
constexpr compressed_pair(U1&& v1, U2&& v2) noexcept(std::is_nothrow_constructible_v<_Ty1, U1&&> && std::is_nothrow_constructible_v<_Ty2, U2&&>)
: _Myval1(std::forward<U1>(v1)), _Myval2(std::forward<U2>(v2))
{}

// accessors
constexpr _Ty1& first() noexcept { return _Myval1; }
constexpr const _Ty1& first() const noexcept { return _Myval1; }
constexpr _Ty2& second() noexcept { return _Myval2; }
constexpr const _Ty2& second() const noexcept { return _Myval2; }
};

// Case 2: First empty
template <class _Ty1, class _Ty2>
class compressed_pair<_Ty1, _Ty2, true, false> : private _Ty1 {
_Ty2 _Myval2;

public:
constexpr compressed_pair() = default;

constexpr compressed_pair(const _Ty1& v1, const _Ty2& v2) noexcept(std::is_nothrow_copy_constructible_v<_Ty2>) : _Ty1(v1), _Myval2(v2) {}

constexpr compressed_pair(_Ty1&& v1, _Ty2&& v2) noexcept(std::is_nothrow_move_constructible_v<_Ty2>) : _Ty1(std::move(v1)), _Myval2(std::move(v2)) {}

template <class U1, class U2>
constexpr compressed_pair(U1&& v1, U2&& v2) noexcept(std::is_nothrow_constructible_v<_Ty2, U2&&>) : _Ty1(std::forward<U1>(v1)), _Myval2(std::forward<U2>(v2))
{}

constexpr _Ty1& first() noexcept { return *this; }
constexpr const _Ty1& first() const noexcept { return *this; }
constexpr _Ty2& second() noexcept { return _Myval2; }
constexpr const _Ty2& second() const noexcept { return _Myval2; }
};

// Case 3: Second empty
template <class _Ty1, class _Ty2>
class compressed_pair<_Ty1, _Ty2, false, true> : private _Ty2 {
_Ty1 _Myval1;

public:
constexpr compressed_pair() = default;

constexpr compressed_pair(const _Ty1& v1, const _Ty2& v2) noexcept(std::is_nothrow_copy_constructible_v<_Ty1>) : _Myval1(v1), _Ty2(v2) {}

constexpr compressed_pair(_Ty1&& v1, _Ty2&& v2) noexcept(std::is_nothrow_move_constructible_v<_Ty1>) : _Myval1(std::move(v1)), _Ty2(std::move(v2)) {}

template <class U1, class U2>
constexpr compressed_pair(U1&& v1, U2&& v2) noexcept(std::is_nothrow_constructible_v<_Ty1, U1&&>) : _Myval1(std::forward<U1>(v1)), _Ty2(std::forward<U2>(v2))
{}

constexpr _Ty1& first() noexcept { return _Myval1; }
constexpr const _Ty1& first() const noexcept { return _Myval1; }
constexpr _Ty2& second() noexcept { return *this; }
constexpr const _Ty2& second() const noexcept { return *this; }
};

// Case 4: both empty
template <class _Ty1, class _Ty2>
class compressed_pair<_Ty1, _Ty2, true, true> : private _Ty1, private _Ty2 {
public:
constexpr compressed_pair() = default;

constexpr compressed_pair(const _Ty1& v1, const _Ty2& v2) : _Ty1(v1), _Ty2(v2) {}

constexpr compressed_pair(_Ty1&& v1, _Ty2&& v2) : _Ty1(std::move(v1)), _Ty2(std::move(v2)) {}

template <class U1, class U2>
constexpr compressed_pair(U1&& v1, U2&& v2) : _Ty1(std::forward<U1>(v1)), _Ty2(std::forward<U2>(v2))
{}

constexpr _Ty1& first() noexcept { return *this; }
constexpr const _Ty1& first() const noexcept { return *this; }
constexpr _Ty2& second() noexcept { return *this; }
constexpr const _Ty2& second() const noexcept { return *this; }
};
} // namespace yasio

#define _YASIO_VERIFY_RANGE(cond, mesg) \
do \
{ \
if (cond) \
; /* contextually convertible to bool paranoia */ \
else \
{ \
throw std::out_of_range(mesg); \
} \
\
} while (false)

#endif
Loading
Loading