Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use std::unique_ptr instead of forward_list to hold ExchangePrivate memory #537

Merged
merged 2 commits into from
Mar 20, 2024
Merged
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
50 changes: 28 additions & 22 deletions src/api/interface/include/exchange.hpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#pragma once

#include <memory>
#include <optional>
#include <string_view>
#include <type_traits>

#include "cct_exception.hpp"
#include "currencycode.hpp"
Expand Down Expand Up @@ -29,9 +31,10 @@ class Exchange {
Exchange(const ExchangeConfig &exchangeConfig, ExchangePublic &exchangePublic);

/// Build a Exchange with both private and public exchanges
Exchange(const ExchangeConfig &exchangeConfig, ExchangePublic &exchangePublic, ExchangePrivate &exchangePrivate);
Exchange(const ExchangeConfig &exchangeConfig, ExchangePublic &exchangePublic,
std::unique_ptr<ExchangePrivate> exchangePrivate);

std::string_view name() const { return _exchangePublic.name(); }
std::string_view name() const { return apiPublic().name(); }
std::string_view keyName() const { return apiPrivate().keyName(); }

ExchangeName createExchangeName() const {
Expand All @@ -41,63 +44,63 @@ class Exchange {
return ExchangeName(name());
}

ExchangePublic &apiPublic() { return _exchangePublic; }
const ExchangePublic &apiPublic() const { return _exchangePublic; }
ExchangePublic &apiPublic() { return *_pExchangePublic; }
const ExchangePublic &apiPublic() const { return *_pExchangePublic; }

ExchangePrivate &apiPrivate() {
if (hasPrivateAPI()) {
return *_pExchangePrivate;
return *_exchangePrivate;
}
throw exception("No private key associated to exchange {}", name());
}

const ExchangePrivate &apiPrivate() const {
if (hasPrivateAPI()) {
return *_pExchangePrivate;
return *_exchangePrivate;
}
throw exception("No private key associated to exchange {}", name());
}

const ExchangeConfig &exchangeConfig() const { return _exchangeConfig; }
const ExchangeConfig &exchangeConfig() const { return *_pExchangeConfig; }

bool hasPrivateAPI() const { return _pExchangePrivate != nullptr; }
bool hasPrivateAPI() const { return static_cast<bool>(_exchangePrivate); }

bool healthCheck() { return _exchangePublic.healthCheck(); }
bool healthCheck() { return apiPublic().healthCheck(); }

CurrencyExchangeFlatSet queryTradableCurrencies() {
return hasPrivateAPI() ? _pExchangePrivate->queryTradableCurrencies() : _exchangePublic.queryTradableCurrencies();
return hasPrivateAPI() ? _exchangePrivate->queryTradableCurrencies() : apiPublic().queryTradableCurrencies();
}

CurrencyExchange convertStdCurrencyToCurrencyExchange(CurrencyCode currencyCode) {
return _exchangePublic.convertStdCurrencyToCurrencyExchange(currencyCode);
return apiPublic().convertStdCurrencyToCurrencyExchange(currencyCode);
}

MarketSet queryTradableMarkets() { return _exchangePublic.queryTradableMarkets(); }
MarketSet queryTradableMarkets() { return apiPublic().queryTradableMarkets(); }

MarketPriceMap queryAllPrices() { return _exchangePublic.queryAllPrices(); }
MarketPriceMap queryAllPrices() { return apiPublic().queryAllPrices(); }

MonetaryAmountByCurrencySet queryWithdrawalFees() {
return hasPrivateAPI() ? _pExchangePrivate->queryWithdrawalFees() : _exchangePublic.queryWithdrawalFees();
return hasPrivateAPI() ? _exchangePrivate->queryWithdrawalFees() : apiPublic().queryWithdrawalFees();
}

std::optional<MonetaryAmount> queryWithdrawalFee(CurrencyCode currencyCode) {
return hasPrivateAPI() ? _pExchangePrivate->queryWithdrawalFee(currencyCode)
: _exchangePublic.queryWithdrawalFee(currencyCode);
return hasPrivateAPI() ? _exchangePrivate->queryWithdrawalFee(currencyCode)
: apiPublic().queryWithdrawalFee(currencyCode);
}

MarketOrderBookMap queryAllApproximatedOrderBooks(int depth = ExchangePublic::kDefaultDepth) {
return _exchangePublic.queryAllApproximatedOrderBooks(depth);
return apiPublic().queryAllApproximatedOrderBooks(depth);
}

MarketOrderBook queryOrderBook(Market mk, int depth = ExchangePublic::kDefaultDepth);

MonetaryAmount queryLast24hVolume(Market mk) { return _exchangePublic.queryLast24hVolume(mk); }
MonetaryAmount queryLast24hVolume(Market mk) { return apiPublic().queryLast24hVolume(mk); }

/// Retrieve an ordered vector of recent last trades
PublicTradeVector queryLastTrades(Market mk, int nbTrades = ExchangePublic::kNbLastTradesDefault);

/// Retrieve the last price of given market.
MonetaryAmount queryLastPrice(Market mk) { return _exchangePublic.queryLastPrice(mk); }
MonetaryAmount queryLastPrice(Market mk) { return apiPublic().queryLastPrice(mk); }

bool canWithdraw(CurrencyCode currencyCode, const CurrencyExchangeFlatSet &currencyExchangeSet) const;

Expand All @@ -109,10 +112,13 @@ class Exchange {

void updateCacheFile() const;

/// unique_ptr is always trivially relocatable whatever the underlying type.
using trivially_relocatable = std::true_type;

private:
ExchangePublic &_exchangePublic;
ExchangePrivate *_pExchangePrivate = nullptr;
const ExchangeConfig &_exchangeConfig;
ExchangePublic *_pExchangePublic;
std::unique_ptr<ExchangePrivate> _exchangePrivate;
const ExchangeConfig *_pExchangeConfig;
};

} // namespace cct
26 changes: 0 additions & 26 deletions src/api/interface/include/exchangepool.hpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
#pragma once

#include <forward_list>
#include <span>
#include <string_view>

#include "binancepublicapi.hpp"
#include "bithumbpublicapi.hpp"
Expand All @@ -21,13 +19,6 @@ class CoincenterInfo;
class FiatConverter;

namespace api {
class BinancePrivate;
class BithumbPrivate;
class HuobiPrivate;
class KrakenPrivate;
class KucoinPrivate;
class UpbitPrivate;

class CommonAPI;
class APIKeysProvider;
} // namespace api
Expand All @@ -37,13 +28,6 @@ class ExchangePool {
ExchangePool(const CoincenterInfo& coincenterInfo, FiatConverter& fiatConverter, api::CommonAPI& commonAPI,
const api::APIKeysProvider& apiKeyProvider);

ExchangePool(const ExchangePool&) = delete;
ExchangePool(ExchangePool&&) = delete;
ExchangePool& operator=(const ExchangePool&) = delete;
ExchangePool& operator=(ExchangePool&&) = delete;

~ExchangePool();

std::span<Exchange> exchanges() { return _exchanges; }
std::span<const Exchange> exchanges() const { return _exchanges; }

Expand All @@ -63,16 +47,6 @@ class ExchangePool {
api::KucoinPublic _kucoinPublic;
api::UpbitPublic _upbitPublic;

// Private exchanges (based on provided keys)
// Use std::forward_list to guarantee validity of the iterators and pointers, as we give them to Exchange object as
// pointers
std::forward_list<api::BinancePrivate> _binancePrivates;
std::forward_list<api::BithumbPrivate> _bithumbPrivates;
std::forward_list<api::HuobiPrivate> _huobiPrivates;
std::forward_list<api::KrakenPrivate> _krakenPrivates;
std::forward_list<api::KucoinPrivate> _kucoinPrivates;
std::forward_list<api::UpbitPrivate> _upbitPrivates;

ExchangeVector _exchanges;
};

Expand Down
28 changes: 13 additions & 15 deletions src/api/interface/src/exchange.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,20 @@
#include "exchangeconfig.hpp"
#include "exchangeprivateapi.hpp"
#include "exchangepublicapi.hpp"
#include "marketorderbook.hpp"
#include "public-trade-vector.hpp"

namespace cct {

Exchange::Exchange(const ExchangeConfig &exchangeConfig, api::ExchangePublic &exchangePublic,
api::ExchangePrivate &exchangePrivate)
: _exchangePublic(exchangePublic),
_pExchangePrivate(std::addressof(exchangePrivate)),
_exchangeConfig(exchangeConfig) {}
Exchange::Exchange(const ExchangeConfig &exchangeConfig, ExchangePublic &exchangePublic)
: Exchange(exchangeConfig, exchangePublic, std::unique_ptr<ExchangePrivate>()) {}

Exchange::Exchange(const ExchangeConfig &exchangeConfig, api::ExchangePublic &exchangePublic)
: _exchangePublic(exchangePublic), _exchangeConfig(exchangeConfig) {}
Exchange::Exchange(const ExchangeConfig &exchangeConfig, ExchangePublic &exchangePublic,
std::unique_ptr<ExchangePrivate> exchangePrivate)
: _pExchangePublic(std::addressof(exchangePublic)),
_exchangePrivate(std::move(exchangePrivate)),
_pExchangeConfig(std::addressof(exchangeConfig)) {}

bool Exchange::canWithdraw(CurrencyCode currencyCode, const CurrencyExchangeFlatSet &currencyExchangeSet) const {
if (_exchangeConfig.excludedCurrenciesWithdrawal().contains(currencyCode)) {
if (_pExchangeConfig->excludedCurrenciesWithdrawal().contains(currencyCode)) {
return false;
}
auto lb = currencyExchangeSet.find(currencyCode);
Expand All @@ -43,17 +41,17 @@ bool Exchange::canDeposit(CurrencyCode currencyCode, const CurrencyExchangeFlatS
return lb->canDeposit();
}

MarketOrderBook Exchange::queryOrderBook(Market mk, int depth) { return _exchangePublic.queryOrderBook(mk, depth); }
MarketOrderBook Exchange::queryOrderBook(Market mk, int depth) { return apiPublic().queryOrderBook(mk, depth); }

/// Retrieve an ordered vector of recent last trades
PublicTradeVector Exchange::queryLastTrades(Market mk, int nbTrades) {
return _exchangePublic.queryLastTrades(mk, nbTrades);
return apiPublic().queryLastTrades(mk, nbTrades);
}

void Exchange::updateCacheFile() const {
_exchangePublic.updateCacheFile();
if (_pExchangePrivate != nullptr) {
_pExchangePrivate->updateCacheFile();
apiPublic().updateCacheFile();
if (_exchangePrivate) {
_exchangePrivate->updateCacheFile();
}
}
} // namespace cct
20 changes: 10 additions & 10 deletions src/api/interface/src/exchangepool.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
#include "exchangepool.hpp"

#include <memory>
#include <string_view>

#include "apikey.hpp"
#include "apikeysprovider.hpp"
#include "binanceprivateapi.hpp"
#include "bithumbprivateapi.hpp"
#include "bithumbpublicapi.hpp"
#include "cct_const.hpp"
#include "cct_exception.hpp"
#include "cct_log.hpp"
Expand Down Expand Up @@ -53,21 +55,21 @@ ExchangePool::ExchangePool(const CoincenterInfo& coincenterInfo, FiatConverter&
const ExchangeConfig& exchangeConfig = _coincenterInfo.exchangeConfig(exchangePublic->name());
if (canUsePrivateExchange) {
for (std::string_view keyName : _apiKeyProvider.getKeyNames(exchangeStr)) {
api::ExchangePrivate* exchangePrivate;
std::unique_ptr<api::ExchangePrivate> exchangePrivate;
ExchangeName exchangeName(exchangeStr, keyName);
const api::APIKey& apiKey = _apiKeyProvider.get(exchangeName);
if (exchangePublic == &_binancePublic) {
exchangePrivate = &_binancePrivates.emplace_front(_coincenterInfo, _binancePublic, apiKey);
exchangePrivate = std::make_unique<api::BinancePrivate>(_coincenterInfo, _binancePublic, apiKey);
} else if (exchangePublic == &_bithumbPublic) {
exchangePrivate = &_bithumbPrivates.emplace_front(_coincenterInfo, _bithumbPublic, apiKey);
exchangePrivate = std::make_unique<api::BithumbPrivate>(_coincenterInfo, _bithumbPublic, apiKey);
} else if (exchangePublic == &_huobiPublic) {
exchangePrivate = &_huobiPrivates.emplace_front(_coincenterInfo, _huobiPublic, apiKey);
exchangePrivate = std::make_unique<api::HuobiPrivate>(_coincenterInfo, _huobiPublic, apiKey);
} else if (exchangePublic == &_krakenPublic) {
exchangePrivate = &_krakenPrivates.emplace_front(_coincenterInfo, _krakenPublic, apiKey);
exchangePrivate = std::make_unique<api::KrakenPrivate>(_coincenterInfo, _krakenPublic, apiKey);
} else if (exchangePublic == &_kucoinPublic) {
exchangePrivate = &_kucoinPrivates.emplace_front(_coincenterInfo, _kucoinPublic, apiKey);
exchangePrivate = std::make_unique<api::KucoinPrivate>(_coincenterInfo, _kucoinPublic, apiKey);
} else if (exchangePublic == &_upbitPublic) {
exchangePrivate = &_upbitPrivates.emplace_front(_coincenterInfo, _upbitPublic, apiKey);
exchangePrivate = std::make_unique<api::UpbitPrivate>(_coincenterInfo, _upbitPublic, apiKey);
} else {
throw exception("Unsupported platform {}", exchangeStr);
}
Expand All @@ -81,7 +83,7 @@ ExchangePool::ExchangePool(const CoincenterInfo& coincenterInfo, FiatConverter&
}
}

_exchanges.emplace_back(exchangeConfig, *exchangePublic, *exchangePrivate);
_exchanges.emplace_back(exchangeConfig, *exchangePublic, std::move(exchangePrivate));
}
} else {
_exchanges.emplace_back(exchangeConfig, *exchangePublic);
Expand All @@ -90,6 +92,4 @@ ExchangePool::ExchangePool(const CoincenterInfo& coincenterInfo, FiatConverter&
_exchanges.shrink_to_fit();
}

ExchangePool::~ExchangePool() = default;

} // namespace cct
Loading