Libspinscale: Initial top-level SMO port to coroutine framework
We haven't ported everything. Just the top-level methods. We'll dig in to the leaf stuff later. Surprisingly, this all went without any real difficulties. Runs like a charm on first try.
This commit is contained in:
@@ -33,23 +33,27 @@ std::string DeviceManager::readDapSpecFile(const std::string& filename)
|
||||
void DeviceManager::collateAllDapSpecs(void)
|
||||
{
|
||||
OptionParser &options = OptionParser::getOptions();
|
||||
allDapSpecs = options.dapSpecs;
|
||||
DeviceManager &dm = getInstance();
|
||||
dm.s.rsrc.allDapSpecs = options.dapSpecs;
|
||||
|
||||
for (const auto& file : options.dapSpecFiles)
|
||||
{
|
||||
std::string fileContent = readDapSpecFile(file);
|
||||
if (!allDapSpecs.empty()) {
|
||||
allDapSpecs += "||";
|
||||
if (!dm.s.rsrc.allDapSpecs.empty()) {
|
||||
dm.s.rsrc.allDapSpecs += "||";
|
||||
}
|
||||
allDapSpecs += fileContent;
|
||||
dm.s.rsrc.allDapSpecs += fileContent;
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceManager::parseAllDapSpecs(void)
|
||||
{
|
||||
DeviceManager &dm = getInstance();
|
||||
auto file_deleter = [](FILE* f) { if (f) fclose(f); };
|
||||
std::unique_ptr<FILE, decltype(file_deleter)> input(
|
||||
fmemopen((void*)allDapSpecs.c_str(), allDapSpecs.size(), "r"),
|
||||
fmemopen(
|
||||
(void*)dm.s.rsrc.allDapSpecs.c_str(),
|
||||
dm.s.rsrc.allDapSpecs.size(), "r"),
|
||||
file_deleter);
|
||||
|
||||
if (!input)
|
||||
|
||||
@@ -91,7 +91,7 @@ interoceptor_spec:
|
||||
*static_cast<smo::device::InteroceptorDevAttachmentSpec *>($3));
|
||||
|
||||
spec->sensorType = $1;
|
||||
smo::device::DeviceManager::commandLineDASpecs.push_back(*spec);
|
||||
smo::device::DeviceManager::getInstance().s.rsrc.commandLineDASpecs.push_back(*spec);
|
||||
|
||||
delete $3;
|
||||
}
|
||||
@@ -103,7 +103,7 @@ extrospector_spec:
|
||||
*static_cast<smo::device::ExtrospectorDevAttachmentSpec *>($3));
|
||||
|
||||
spec->sensorType = $1;
|
||||
smo::device::DeviceManager::commandLineDASpecs.push_back(*spec);
|
||||
smo::device::DeviceManager::getInstance().s.rsrc.commandLineDASpecs.push_back(*spec);
|
||||
|
||||
delete $3;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,22 +1,20 @@
|
||||
#include <config.h>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <functional>
|
||||
#include <componentThread.h>
|
||||
#include <spinscale/callback.h>
|
||||
#include <deviceManager/deviceReattacher.h>
|
||||
#include <deviceManager/deviceManager.h>
|
||||
#include <marionette/marionetteThread.h>
|
||||
|
||||
namespace smo {
|
||||
namespace device {
|
||||
|
||||
static void reattachmentCb(sscl::AsynchronousLoop& results)
|
||||
{
|
||||
if (results.nTotal == 0) { return; }
|
||||
namespace {
|
||||
|
||||
std::cout << "DeviceReattacher: Successfully reattached "
|
||||
<< results.nSucceeded << " of " << results.nTotal << " devices"
|
||||
<< std::endl;
|
||||
}
|
||||
constexpr unsigned int reattachInFlightStaleThresholdMultiplier = 4;
|
||||
|
||||
} // namespace
|
||||
|
||||
DeviceReattacher::DeviceReattacher(
|
||||
DeviceManager& parent, std::shared_ptr<sscl::ComponentThread> ioThread)
|
||||
@@ -25,6 +23,22 @@ timer(ioThread->getIoService())
|
||||
{
|
||||
}
|
||||
|
||||
mrntt::MrnttNonViralPostingInvoker DeviceReattacher::reattachKnownListCReq(
|
||||
[[maybe_unused]] std::exception_ptr &exceptionPtr,
|
||||
[[maybe_unused]] std::function<void()> callback)
|
||||
{
|
||||
sscl::MultiOperationResultSet results = co_await
|
||||
parent.attachAllUnattachedDevicesFromKnownListCReq();
|
||||
if (results.nTotal > 0)
|
||||
{
|
||||
std::cout << "DeviceReattacher: Successfully reattached "
|
||||
<< results.nSucceeded << " of " << results.nTotal
|
||||
<< " devices" << std::endl;
|
||||
}
|
||||
|
||||
co_return;
|
||||
}
|
||||
|
||||
void DeviceReattacher::start()
|
||||
{
|
||||
shouldContinue = true;
|
||||
@@ -36,6 +50,14 @@ void DeviceReattacher::stop()
|
||||
{
|
||||
sscl::SpinLock::Guard lock(shouldContinueLock);
|
||||
shouldContinue = false;
|
||||
reattachOpInFlight = false;
|
||||
/** EXPLANATION:
|
||||
* Do not call reattachCReqInvoker.reset() here. Forcibly destroying
|
||||
* the invoker would tear down an in-flight reattach coroutine frame
|
||||
* mid-operation. During normal program teardown the optional (and
|
||||
* its invoker) are destroyed with the rest of the binary anyway; leave
|
||||
* a running reattach time to finish if shutdown races with it.
|
||||
*/
|
||||
}
|
||||
|
||||
timer.cancel();
|
||||
@@ -56,6 +78,21 @@ void DeviceReattacher::scheduleNextTimeout()
|
||||
std::bind(&DeviceReattacher::onTimeout, this, std::placeholders::_1));
|
||||
}
|
||||
|
||||
void DeviceReattacher::holdReattachCReq()
|
||||
{
|
||||
reattachOpInFlight = true;
|
||||
lastReattachReqTimestamp = std::chrono::steady_clock::now();
|
||||
|
||||
reattachCReqInvoker.reset();
|
||||
reattachCReqInvoker.emplace(reattachKnownListCReq(
|
||||
reattachLifetimeExceptionPtr,
|
||||
[this]()
|
||||
{
|
||||
sscl::SpinLock::Guard lock(shouldContinueLock);
|
||||
reattachOpInFlight = false;
|
||||
}));
|
||||
}
|
||||
|
||||
void DeviceReattacher::onTimeout(const boost::system::error_code& error)
|
||||
{
|
||||
// Timer was cancelled, which is expected when stopping
|
||||
@@ -75,9 +112,32 @@ void DeviceReattacher::onTimeout(const boost::system::error_code& error)
|
||||
return;
|
||||
}
|
||||
|
||||
const auto staleThreshold = std::chrono::milliseconds(
|
||||
reattachInFlightStaleThresholdMultiplier
|
||||
* CONFIG_MRNTT_DEVMGR_REATTACHER_PERIOD_MS);
|
||||
|
||||
// Attempt to reattach all unattached devices from the known list
|
||||
parent.attachAllUnattachedDevicesFromKnownListReq(
|
||||
{ nullptr, reattachmentCb});
|
||||
if (!reattachOpInFlight)
|
||||
{
|
||||
holdReattachCReq();
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto elapsedSinceLastReattachReq =
|
||||
std::chrono::steady_clock::now() - lastReattachReqTimestamp;
|
||||
|
||||
if (elapsedSinceLastReattachReq >= staleThreshold)
|
||||
{
|
||||
std::cerr << "DeviceReattacher: Reattach op still in flight after "
|
||||
<< std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
elapsedSinceLastReattachReq).count()
|
||||
<< "ms (threshold "
|
||||
<< staleThreshold.count()
|
||||
<< "ms); forcing a new reattach request."
|
||||
<< std::endl;
|
||||
holdReattachCReq();
|
||||
}
|
||||
}
|
||||
|
||||
// Schedule the next timeout
|
||||
scheduleNextTimeout();
|
||||
|
||||
Reference in New Issue
Block a user