support for transmitting of capture-semantics closures via Broker, while keeping deprecated functionality

This commit is contained in:
Vern Paxson 2021-01-04 14:29:07 -08:00
parent e531b2a7ca
commit 80f7d36582
5 changed files with 166 additions and 35 deletions

View file

@ -302,24 +302,25 @@ Frame* Frame::SelectiveClone(const IDPList& selection, ScriptFunc* func) const
return other;
}
broker::expected<broker::data> Frame::Serialize(const Frame* target, const IDPList& selection)
broker::expected<broker::data> Frame::SerializeClosureFrame(const IDPList& selection)
{
broker::vector rval;
if ( selection.length() == 0 )
// Easy - no captures, so frame is irrelvant.
return {std::move(rval)};
IDPList us;
// and
IDPList them;
std::unordered_map<std::string, int> new_map;
if ( target->offset_map )
new_map = *(target->offset_map);
OffsetMap new_map;
if ( offset_map )
new_map = *offset_map;
for (const auto& we : selection)
for ( const auto& we : selection )
{
if ( target->IsOuterID(we) )
if ( IsOuterID(we) )
them.append(we);
else
{
@ -330,18 +331,18 @@ broker::expected<broker::data> Frame::Serialize(const Frame* target, const IDPLi
if ( them.length() )
{
if ( ! target->closure )
if ( ! closure )
reporter->InternalError("Attempting to serialize values from a frame that does not exist.");
rval.emplace_back(std::string("ClosureFrame"));
auto ids = SerializeIDList(target->outer_ids);
auto ids = SerializeIDList(outer_ids);
if ( ! ids )
return broker::ec::invalid_data;
rval.emplace_back(*ids);
auto serialized = Frame::Serialize(target->closure, them);
auto serialized = closure->SerializeClosureFrame(them);
if ( ! serialized )
return broker::ec::invalid_data;
@ -358,7 +359,7 @@ broker::expected<broker::data> Frame::Serialize(const Frame* target, const IDPLi
broker::vector body;
for ( int i = 0; i < target->size; ++i )
for ( int i = 0; i < size; ++i )
body.emplace_back(broker::none());
for ( const auto& id : us )
@ -366,10 +367,10 @@ broker::expected<broker::data> Frame::Serialize(const Frame* target, const IDPLi
int location = id->Offset();
auto where = new_map.find(std::string(id->Name()));
if (where != new_map.end())
if ( where != new_map.end() )
location = where->second;
const auto& val = target->frame[location].val;
const auto& val = frame[location].val;
TypeTag tag = val->GetType()->Tag();
@ -386,15 +387,38 @@ broker::expected<broker::data> Frame::Serialize(const Frame* target, const IDPLi
return {std::move(rval)};
}
std::pair<bool, FramePtr> Frame::Unserialize(const broker::vector& data)
broker::expected<broker::data> Frame::SerializeCopyFrame()
{
broker::vector rval;
rval.emplace_back(std::string("CopyFrame"));
broker::vector body;
for ( int i = 0; i < size; ++i )
{
const auto& val = frame[i].val;
auto expected = Broker::detail::val_to_data(val.get());
if ( ! expected )
return broker::ec::invalid_data;
TypeTag tag = val->GetType()->Tag();
broker::vector val_tuple {std::move(*expected),
static_cast<broker::integer>(tag)};
body.emplace_back(broker::none());
body[i] = val_tuple;
}
rval.emplace_back(body);
return {std::move(rval)};
}
std::pair<bool, FramePtr> Frame::Unserialize(const broker::vector& data,
const std::vector<FuncType::Capture*>* captures)
{
if ( data.size() == 0 )
return std::make_pair(true, nullptr);
IDPList outer_ids;
OffsetMap offset_map;
FramePtr closure;
auto where = data.begin();
auto has_name = broker::get_if<std::string>(*where);
@ -403,6 +427,54 @@ std::pair<bool, FramePtr> Frame::Unserialize(const broker::vector& data)
std::advance(where, 1);
if ( captures || *has_name == "CopyFrame" )
{
ASSERT(captures && *has_name == "CopyFrame");
auto has_body = broker::get_if<broker::vector>(*where);
if ( ! has_body )
return std::make_pair(false, nullptr);
broker::vector body = *has_body;
int frame_size = body.size();
auto rf = make_intrusive<Frame>(frame_size, nullptr, nullptr);
rf->closure = nullptr;
for ( int i = 0; i < frame_size; ++i )
{
auto has_vec = broker::get_if<broker::vector>(body[i]);
if ( ! has_vec )
continue;
broker::vector val_tuple = *has_vec;
if ( val_tuple.size() != 2 )
return std::make_pair(false, nullptr);
auto has_type = broker::get_if<broker::integer>(val_tuple[1]);
if ( ! has_type )
return std::make_pair(false, nullptr);
broker::integer g = *has_type;
Type t( static_cast<TypeTag>(g) );
auto val = Broker::detail::data_to_val(std::move(val_tuple[0]), &t);
if ( ! val )
return std::make_pair(false, nullptr);
rf->frame[i].val = std::move(val);
}
return std::make_pair(true, std::move(rf));
}
// Code to support deprecated semantics:
IDPList outer_ids;
OffsetMap offset_map;
FramePtr closure;
if ( *has_name == "ClosureFrame" )
{
auto has_vec = broker::get_if<broker::vector>(*where);
@ -428,7 +500,7 @@ std::pair<bool, FramePtr> Frame::Unserialize(const broker::vector& data)
std::advance(where, 1);
auto closure_pair = Frame::Unserialize(*has_vec);
auto closure_pair = Frame::Unserialize(*has_vec, nullptr);
if ( ! closure_pair.first )
{
for ( auto& i : outer_ids )