mirror of
https://github.com/XRPLF/rippled.git
synced 2026-08-23 15:20:54 +00:00
switch to coroutine2 and remove string caching
Signed-off-by: Pratik Mankawde <3397372+pratikmankawde@users.noreply.github.com>
This commit is contained in:
@@ -17,7 +17,7 @@ find_dependency(Boost
|
||||
chrono
|
||||
container
|
||||
context
|
||||
coroutine
|
||||
coroutine2
|
||||
date_time
|
||||
filesystem
|
||||
program_options
|
||||
|
||||
@@ -22,7 +22,7 @@ target_compile_definitions(
|
||||
BOOST_FILESYSTEM_NO_DEPRECATED
|
||||
>
|
||||
$<$<NOT:$<BOOL:${boost_show_deprecated}>>:
|
||||
BOOST_COROUTINES_NO_DEPRECATION_WARNING
|
||||
BOOST_COROUTINES2_NO_DEPRECATION_WARNING
|
||||
BOOST_BEAST_ALLOW_DEPRECATED
|
||||
BOOST_FILESYSTEM_DEPRECATED
|
||||
>
|
||||
|
||||
@@ -4,13 +4,12 @@ include(XrplSanitizers)
|
||||
find_package(Boost REQUIRED
|
||||
COMPONENTS chrono
|
||||
container
|
||||
coroutine
|
||||
context
|
||||
date_time
|
||||
filesystem
|
||||
json
|
||||
program_options
|
||||
regex
|
||||
system
|
||||
thread)
|
||||
|
||||
add_library(xrpl_boost INTERFACE)
|
||||
@@ -21,7 +20,7 @@ target_link_libraries(
|
||||
INTERFACE Boost::headers
|
||||
Boost::chrono
|
||||
Boost::container
|
||||
Boost::coroutine
|
||||
Boost::context
|
||||
Boost::date_time
|
||||
Boost::filesystem
|
||||
Boost::json
|
||||
|
||||
@@ -56,6 +56,9 @@ class Xrpl(ConanFile):
|
||||
"static": True,
|
||||
"tests": False,
|
||||
"xrpld": False,
|
||||
"boost/*:without_context": False,
|
||||
"boost/*:without_coroutine": True,
|
||||
"boost/*:without_coroutine2": False,
|
||||
"date/*:header_only": True,
|
||||
"ed25519/*:shared": False,
|
||||
"grpc/*:shared": False,
|
||||
@@ -124,6 +127,9 @@ class Xrpl(ConanFile):
|
||||
self.options["boost"].visibility = "global"
|
||||
if self.settings.compiler in ["clang", "gcc"]:
|
||||
self.options["boost"].without_cobalt = True
|
||||
self.options["boost"].without_context = False
|
||||
self.options["boost"].without_coroutine = True
|
||||
self.options["boost"].without_coroutine2 = False
|
||||
|
||||
# Check if environment variable exists
|
||||
if "SANITIZERS" in os.environ:
|
||||
@@ -200,7 +206,8 @@ class Xrpl(ConanFile):
|
||||
"boost::headers",
|
||||
"boost::chrono",
|
||||
"boost::container",
|
||||
"boost::coroutine",
|
||||
"boost::context",
|
||||
"boost::coroutine2",
|
||||
"boost::date_time",
|
||||
"boost::filesystem",
|
||||
"boost::json",
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
namespace beast {
|
||||
|
||||
@@ -159,17 +158,6 @@ public:
|
||||
std::ostream&
|
||||
operator<<(T const& t) const;
|
||||
|
||||
/** Overload for const char* for chained operations.
|
||||
Handles cases like: stream << "text1" << "text2"
|
||||
Converts to std::string to prevent stack-use-after-scope issues.
|
||||
*/
|
||||
std::ostream&
|
||||
operator<<(char const* t) const
|
||||
{
|
||||
m_ostream << std::string(t);
|
||||
return m_ostream;
|
||||
}
|
||||
|
||||
private:
|
||||
Sink& m_sink;
|
||||
Severity const m_level;
|
||||
@@ -250,18 +238,6 @@ public:
|
||||
template <typename T>
|
||||
ScopedStream
|
||||
operator<<(T const& t) const;
|
||||
|
||||
/** Overload for const char* to ensure immediate copy.
|
||||
This prevents stack-use-after-scope issues when the source
|
||||
pointer becomes invalid due to coroutine context switches or
|
||||
stack unwinding. Converts to std::string immediately to copy
|
||||
the data before constructing ScopedStream.
|
||||
*/
|
||||
ScopedStream
|
||||
operator<<(char const* t) const
|
||||
{
|
||||
return t ? ScopedStream(*this, std::string(t)) : ScopedStream(*this, std::string());
|
||||
}
|
||||
/** @} */
|
||||
|
||||
private:
|
||||
|
||||
@@ -18,16 +18,14 @@ JobQueue::Coro::Coro(Coro_create_t, JobQueue& jq, JobType type, std::string cons
|
||||
, type_(type)
|
||||
, name_(name)
|
||||
, running_(false)
|
||||
, coro_(
|
||||
[this, fn = std::forward<F>(f)](boost::coroutines::asymmetric_coroutine<void>::push_type& do_yield) {
|
||||
yield_ = &do_yield;
|
||||
yield();
|
||||
fn(shared_from_this());
|
||||
, coro_([this, fn = std::forward<F>(f)](boost::coroutines2::asymmetric_coroutine<void>::push_type& do_yield) {
|
||||
yield_ = &do_yield;
|
||||
yield();
|
||||
fn(shared_from_this());
|
||||
#ifndef NDEBUG
|
||||
finished_ = true;
|
||||
finished_ = true;
|
||||
#endif
|
||||
},
|
||||
boost::coroutines::attributes(megabytes(4))) // 4MB stack (increased from 1MB)
|
||||
})
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include <xrpl/core/detail/Workers.h>
|
||||
#include <xrpl/json/json_value.h>
|
||||
|
||||
#include <boost/coroutine/all.hpp>
|
||||
#include <boost/coroutine2/all.hpp>
|
||||
|
||||
#include <set>
|
||||
|
||||
@@ -48,8 +48,8 @@ public:
|
||||
std::mutex mutex_;
|
||||
std::mutex mutex_run_;
|
||||
std::condition_variable cv_;
|
||||
boost::coroutines::asymmetric_coroutine<void>::pull_type coro_;
|
||||
boost::coroutines::asymmetric_coroutine<void>::push_type* yield_;
|
||||
boost::coroutines2::asymmetric_coroutine<void>::pull_type coro_;
|
||||
boost::coroutines2::asymmetric_coroutine<void>::push_type* yield_;
|
||||
#ifndef NDEBUG
|
||||
bool finished_ = false;
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
detect_container_overflow=0
|
||||
detect_stack_use_after_return=0
|
||||
detect_stack-buffer-overflow=0
|
||||
debug=true
|
||||
halt_on_error=0
|
||||
halt_on_error=false
|
||||
print_stats=true
|
||||
print_legend=true
|
||||
symbolize=true
|
||||
|
||||
@@ -69,17 +69,13 @@ make_name(std::string const& object, std::string const& field)
|
||||
if (field.empty())
|
||||
return object;
|
||||
|
||||
return object + "." + field;
|
||||
return {object + "." + field};
|
||||
}
|
||||
|
||||
// Note: Store make_name() result in a local variable before string concatenation
|
||||
// to prevent stack-use-after-scope when the temporary is used in chained operations
|
||||
static inline Json::Value
|
||||
not_an_object(std::string const& object, std::string const& field)
|
||||
{
|
||||
auto const fieldName = make_name(object, field);
|
||||
std::string const msg = "Field '" + fieldName + "' is not a JSON object.";
|
||||
return RPC::make_error(rpcINVALID_PARAMS, msg);
|
||||
return RPC::make_error(rpcINVALID_PARAMS, "Field '" + make_name(object, field) + "' is not a JSON object.");
|
||||
}
|
||||
|
||||
static inline Json::Value
|
||||
@@ -97,33 +93,25 @@ not_an_array(std::string const& object)
|
||||
static inline Json::Value
|
||||
unknown_field(std::string const& object, std::string const& field)
|
||||
{
|
||||
auto const fieldName = make_name(object, field);
|
||||
std::string const msg = "Field '" + fieldName + "' is unknown.";
|
||||
return RPC::make_error(rpcINVALID_PARAMS, msg);
|
||||
return RPC::make_error(rpcINVALID_PARAMS, "Field '" + make_name(object, field) + "' is unknown.");
|
||||
}
|
||||
|
||||
static inline Json::Value
|
||||
out_of_range(std::string const& object, std::string const& field)
|
||||
{
|
||||
auto const fieldName = make_name(object, field);
|
||||
std::string const msg = "Field '" + fieldName + "' is out of range.";
|
||||
return RPC::make_error(rpcINVALID_PARAMS, msg);
|
||||
return RPC::make_error(rpcINVALID_PARAMS, "Field '" + make_name(object, field) + "' is out of range.");
|
||||
}
|
||||
|
||||
static inline Json::Value
|
||||
bad_type(std::string const& object, std::string const& field)
|
||||
{
|
||||
auto const fieldName = make_name(object, field);
|
||||
std::string const msg = "Field '" + fieldName + "' has bad type.";
|
||||
return RPC::make_error(rpcINVALID_PARAMS, msg);
|
||||
return RPC::make_error(rpcINVALID_PARAMS, "Field '" + make_name(object, field) + "' has bad type.");
|
||||
}
|
||||
|
||||
static inline Json::Value
|
||||
invalid_data(std::string const& object, std::string const& field)
|
||||
{
|
||||
auto const fieldName = make_name(object, field);
|
||||
std::string const msg = "Field '" + fieldName + "' has invalid data.";
|
||||
return RPC::make_error(rpcINVALID_PARAMS, msg);
|
||||
return RPC::make_error(rpcINVALID_PARAMS, "Field '" + make_name(object, field) + "' has invalid data.");
|
||||
}
|
||||
|
||||
static inline Json::Value
|
||||
@@ -135,17 +123,13 @@ invalid_data(std::string const& object)
|
||||
static inline Json::Value
|
||||
array_expected(std::string const& object, std::string const& field)
|
||||
{
|
||||
auto const fieldName = make_name(object, field);
|
||||
std::string const msg = "Field '" + fieldName + "' must be a JSON array.";
|
||||
return RPC::make_error(rpcINVALID_PARAMS, msg);
|
||||
return RPC::make_error(rpcINVALID_PARAMS, "Field '" + make_name(object, field) + "' must be a JSON array.");
|
||||
}
|
||||
|
||||
static inline Json::Value
|
||||
string_expected(std::string const& object, std::string const& field)
|
||||
{
|
||||
auto const fieldName = make_name(object, field);
|
||||
std::string const msg = "Field '" + fieldName + "' must be a string.";
|
||||
return RPC::make_error(rpcINVALID_PARAMS, msg);
|
||||
return RPC::make_error(rpcINVALID_PARAMS, "Field '" + make_name(object, field) + "' must be a string.");
|
||||
}
|
||||
|
||||
static inline Json::Value
|
||||
|
||||
@@ -179,10 +179,7 @@ AMMLiquidity<TIn, TOut>::getOffer(ReadView const& view, std::optional<Quality> c
|
||||
}
|
||||
catch (std::overflow_error const& e)
|
||||
{
|
||||
// Store e.what() in a local variable to prevent stack-use-after-scope
|
||||
// when the exception's internal storage becomes invalid in coroutine context
|
||||
std::string const errorMsg = e.what();
|
||||
JLOG(j_.error()) << "AMMLiquidity::getOffer overflow " << errorMsg;
|
||||
JLOG(j_.error()) << "AMMLiquidity::getOffer overflow " << e.what();
|
||||
if (!view.rules().enabled(fixAMMOverflowOffer))
|
||||
return maxOffer(balances, view.rules());
|
||||
else
|
||||
@@ -190,10 +187,7 @@ AMMLiquidity<TIn, TOut>::getOffer(ReadView const& view, std::optional<Quality> c
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
// Store e.what() in a local variable to prevent stack-use-after-scope
|
||||
// when the exception's internal storage becomes invalid in coroutine context
|
||||
std::string const errorMsg = e.what();
|
||||
JLOG(j_.error()) << "AMMLiquidity::getOffer exception " << errorMsg;
|
||||
JLOG(j_.error()) << "AMMLiquidity::getOffer exception " << e.what();
|
||||
}
|
||||
return std::nullopt;
|
||||
}();
|
||||
|
||||
Reference in New Issue
Block a user