Files
qt5-legatus-legacy/Lts/Plugins/AudioVideoManagement/Data/avm_exercise_context.h
T
2026-08-13 18:33:10 +02:00

162 lines
4.7 KiB
C++
Executable File

/**
* @RDE_HEADER@
* AvmExerciseContext
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Fröbel, NLSE, 2018-07-30
*/
#pragma once
#include <map>
#include <functional>
#include <memory>
namespace LtsSession
{
class LtsSessionDataDds;
}
namespace OperatorManagement
{
namespace Interface
{
class Dtc;
}
}
namespace ExerciseManagement
{
namespace Interface
{
class Dtc;
}
}
namespace InfrastructureManagement
{
namespace Interface
{
class Dtc;
}
}
namespace AudioVideoManagement
{
namespace Interface
{
class Dtc;
class Ftc;
}
class StreamNameMapping;
/**
* For each Exercise -- as defined by its Id -- AvmExerciseContextManager manages
* an associated ExerciseContext. The ExerciseContext just holds all necessary entities.
* The idea is that any number of PluginInterface-instances with the same exerciseId
* share the same ExerciseContext.
* For example, all PluginInterface-instances for Exercise 42 can share the *same* Dtc or Ftc.
* Thus Dtc and Ftc are part of the ExerciseContext.
*
* The lifetime of an ExerciseContext can be longer than the lifetime of a PluginInterface-instance.
* AvsSessionContext uses (references) entities from the ExerciseContext.
* This is ok as it is guaranteed that the lifetime of the ExerciseContext is at least as long
* as the lifetime of AvsSessionContext.
* Actually they have the same lifetime -- if an AvsSessionContext exists.
*
* The difference is that there can be at most one AvsSessionContext at the same time.
* But there can be at most one ExerciseContext *for each* exerciseId at the same time.
* For the global exercise (exerciseId 0) there is never an AvsSessionContext.
*
* The following picuture illustrates the lifetimes:
*
* App1 (42) --------- ---------
* App2 (42) --------- ---------
* App3 (35) =========
*
* ExerciseContext (42) --------- --------------- ---------
* ExerciseContext (35) =========
*
* AvsSessionContext (42) --------- ---------------
* AvsSessionContext (35) =========
*
* PluginInterface-instance 1 (42) ---------
* PluginInterface-instance 2 (42) ---------
* PluginInterface-instance 3 (42) ---------
* PluginInterface-instance 4 (35) =========
* PluginInterface-instance 5 (42) ---------
*
* @see AvsSessionContext
* @author Christian Fröbel
*/
class AvmExerciseContextManager
{
public:
struct ExerciseContext;
~AvmExerciseContextManager();
/**
* Don't use directly; use AvmExerciseContextHandle instead.
*/
///@{
ExerciseContext *acquire(int exerciseId, LtsSession::LtsSessionDataDds *session);
void release(int exerciseId, ExerciseContext *composite);
///@}
private:
/**
* Small internal helper class in order to keep track of the refCount.
* Here, the refCount denotes the number of PluginInterface-Instances for the same Exercise.
*/
struct RefCountedContext
{
explicit RefCountedContext(std::unique_ptr<ExerciseContext> &&context);
RefCountedContext(RefCountedContext &&) noexcept;
~RefCountedContext();
int refCount{1};
std::unique_ptr<ExerciseContext> context;
};
using ExerciseId = int;
std::map<ExerciseId, RefCountedContext> m_activeContexts;
};
/**
* Helper class to automatically call AvmExerciseContextManager::acquire()
* and AvmExerciseContextManager::release() in the ctor and dtor respectively.
* Instances can be moved but not copied.
*
* @author Christian Fröbel
*/
class AvmExerciseContextHandle
{
public:
AvmExerciseContextHandle();
AvmExerciseContextHandle(AvmExerciseContextManager *context, int exerciseId, LtsSession::LtsSessionDataDds *session);
operator bool() const { return m_context.get(); }
/** Only available when not in global Exercise */
StreamNameMapping *streamNameMapping() const;
const std::shared_ptr<Interface::Dtc> &dtc() const;
const std::shared_ptr<Interface::Ftc> &ftc() const;
OperatorManagement::Interface::Dtc *opmDtc() const;
ExerciseManagement::Interface::Dtc *exmDtc() const;
InfrastructureManagement::Interface::Dtc *ismDtc() const;
private:
using Releaser = std::function<void (AvmExerciseContextManager::ExerciseContext *)>;
std::unique_ptr<AvmExerciseContextManager::ExerciseContext, Releaser> m_context;
};
} // namespace AudioVideoManagement