/* Copyright 2016, Ableton AG, Berlin. All rights reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* If you would like to incorporate Link into a proprietary software application,
* please contact .
*/
#pragma once
#include
#include
namespace ableton
{
namespace platforms
{
namespace asio
{
template
struct PooledHandlerContext
{
PooledHandlerContext(util::Injected io)
: mIo(std::move(io))
{
// initialize the handler free store
mFreeStack.reserve(MaxNumHandlers);
for (std::size_t i = 0; i < MaxNumHandlers; ++i)
{
mFreeStack.push_back(reinterpret_cast(mRaw + i));
}
}
template
void async(Handler handler)
{
try
{
mIo->async(HandlerWrapper{*this, std::move(handler)});
}
catch (std::bad_alloc)
{
warning(mIo->log()) << "Handler dropped due to low memory pool";
}
}
template
struct HandlerWrapper
{
HandlerWrapper(PooledHandlerContext& context, Handler handler)
: mContext(context)
, mHandler(std::move(handler))
{
}
void operator()()
{
mHandler();
}
// Use pooled allocation so that posting handlers will not cause
// system allocation
friend void* asio_handler_allocate(
const std::size_t size, HandlerWrapper* const pHandler)
{
if (size > MaxHandlerSize || pHandler->mContext.mFreeStack.empty())
{
// Going over the max handler size is a programming error, as
// this is not a dynamically variable value.
assert(size <= MaxHandlerSize);
throw std::bad_alloc();
}
else
{
const auto p = pHandler->mContext.mFreeStack.back();
pHandler->mContext.mFreeStack.pop_back();
return p;
}
}
friend void asio_handler_deallocate(
void* const p, std::size_t, HandlerWrapper* const pHandler)
{
pHandler->mContext.mFreeStack.push_back(p);
}
PooledHandlerContext& mContext;
Handler mHandler;
};
using MemChunk = typename std::aligned_storage::value>::type;
MemChunk mRaw[MaxNumHandlers];
std::vector mFreeStack;
util::Injected mIo;
};
} // namespace asio
} // namespace platforms
} // namespace ableton