162 lines
4.7 KiB
C++
Executable File
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
|