Skip to content

Commit

Permalink
Development/plugin smart interface type (#1694)
Browse files Browse the repository at this point in the history
* [Plugins] Add PluginSmartInterfaceType

* [Plugins] PluginSmartInterfaceType

* [plugins] PluginSmartInterfaceType

* [Plugins] PluginSmartInterfaceType

* [Plugins] PluginSmartInterfaceType

---------

Co-authored-by: Pierre Wielders <[email protected]>
  • Loading branch information
MFransen69 and pwielders authored Jul 16, 2024
1 parent 483d074 commit 021c321
Showing 1 changed file with 195 additions and 13 deletions.
208 changes: 195 additions & 13 deletions Source/plugins/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ namespace PluginHost {
Sink() = delete;
Sink(const Sink&) = delete;
Sink& operator=(const Sink&) = delete;
Sink(Sink&&) = delete;
Sink& operator=(Sink&&) = delete;

Sink(PluginMonitorType<INTERFACE, HANDLER>& parent)
: _adminLock()
Expand All @@ -57,15 +59,19 @@ namespace PluginHost {
{
return (_designated != nullptr);
}
void Register(IShell* controller, const string& callsign)
// set callsign (must be called before Register, cannot be used to change callsign when monitoring active)
void Callsign(const string& callsign)
{
ASSERT(controller != nullptr);
_adminLock.Lock();
_callsign = callsign;
}
void Register(IShell* shell)
{
ASSERT(shell != nullptr);
_adminLock.Lock();
_state = state::REGISTRING;
_adminLock.Unlock();

controller->Register(this);
shell->Register(this);

_adminLock.Lock();
if (_state == state::LOADED) {
Expand All @@ -82,13 +88,13 @@ namespace PluginHost {
}
_adminLock.Unlock();
}
void Unregister(IShell* controller)
void Unregister(IShell* shell)
{
ASSERT(controller != nullptr);
if (controller != nullptr) {
ASSERT(shell != nullptr);
if (shell != nullptr) {

_adminLock.Lock();
controller->Unregister(this);
shell->Unregister(this);
_callsign.clear();

if (_designated != nullptr) {
Expand Down Expand Up @@ -190,6 +196,8 @@ namespace PluginHost {
PluginMonitorType() = delete;
PluginMonitorType(const PluginMonitorType<INTERFACE, HANDLER>&) = delete;
PluginMonitorType<INTERFACE, HANDLER>& operator=(const PluginMonitorType<INTERFACE, HANDLER>&) = delete;
PluginMonitorType(PluginMonitorType<INTERFACE, HANDLER>&&) = delete;
PluginMonitorType<INTERFACE, HANDLER>& operator=(PluginMonitorType<INTERFACE, HANDLER>&&) = delete;

template <typename... Args>
PluginMonitorType(Args&&... args)
Expand All @@ -204,13 +212,23 @@ namespace PluginHost {
{
return (_sink.IsOperational());
}
void Register(PluginHost::IShell* controller, const string& callsign)
// set callsign (must be called before Register, cannot be used to change callsign when monitoring active)
void Callsign(const string& callsign)
{
_sink.Callsign(callsign);
}
void Register(PluginHost::IShell* shell)
{
_sink.Register(controller, callsign);
_sink.Register(shell);
}
void Unregister(PluginHost::IShell* controller)
void Register(PluginHost::IShell* shell, const string& callsign)
{
_sink.Unregister(controller);
_sink.Callsign(callsign);
_sink.Register(shell);
}
void Unregister(PluginHost::IShell* shell)
{
_sink.Unregister(shell);
}
INTERFACE* Interface()
{
Expand All @@ -237,6 +255,16 @@ namespace PluginHost {
};
}


/*
*
* Use the SmartInterfaceType to interact with (a) COMRPC interface(s) exposed by a plugin (identified by its callsign).
* This class will handle the situation where that plugin could be activated and deactivated.
* This class is intended to be used from code which is NOT a plugin.
* If you require this functionality from inside a plugin please see the PluginSmartInterfaceType below.
*
*/

namespace RPC {

template <typename INTERFACE, Core::ProxyType<RPC::IIPCServer> ENGINE() = DefaultInvokeServer>
Expand All @@ -247,8 +275,10 @@ namespace RPC {
public:
SmartInterfaceType(const SmartInterfaceType<INTERFACE, ENGINE>&) = delete;
SmartInterfaceType<INTERFACE, ENGINE>& operator=(const SmartInterfaceType<INTERFACE, ENGINE>&) = delete;
SmartInterfaceType(SmartInterfaceType<INTERFACE, ENGINE>&&) = delete;
SmartInterfaceType<INTERFACE, ENGINE>& operator=(SmartInterfaceType<INTERFACE, ENGINE>&&) = delete;

PUSH_WARNING(DISABLE_WARNING_THIS_IN_MEMBER_INITIALIZER_LIST)
PUSH_WARNING(DISABLE_WARNING_THIS_IN_MEMBER_INITIALIZER_LIST)
SmartInterfaceType()
: _controller(nullptr)
, _administrator()
Expand Down Expand Up @@ -320,10 +350,12 @@ POP_WARNING()
}
PluginHost::IShell* ControllerInterface()
{
_controller->AddRef();
return _controller;
}
const PluginHost::IShell* ControllerInterface() const
{
_controller->AddRef();
return _controller;
}

Expand Down Expand Up @@ -366,6 +398,154 @@ POP_WARNING()
uint32_t _connectionId;
};

/*
*
* Use the PluginSmartInterfaceType to interact with (a) COMRPC interface(s) exposed by a plugin (identified by its callsign).
* This class will handle the situation where that plugin could be activated and deactivated.
* This class is intended to be used from code which is a plugin. It can be used from both an in process as well as an
* out of process plugin.
* WARNING: if you use this class in the out of process part of a plugin this plugin must have a minimum workerpool thread count
* of 2 otherwise deadlocks can occur!!!!
*
* If you require this functionality from code that is NOT a plugin please see the SmartInterfaceType above.
*
*/

template <typename INTERFACE>
class PluginSmartInterfaceType {
private:
using Monitor = PluginHost::PluginMonitorType<INTERFACE, PluginSmartInterfaceType<INTERFACE>&>;

public:
PluginSmartInterfaceType(const PluginSmartInterfaceType<INTERFACE>&) = delete;
PluginSmartInterfaceType<INTERFACE>& operator=(const PluginSmartInterfaceType<INTERFACE>&) = delete;
PluginSmartInterfaceType(PluginSmartInterfaceType<INTERFACE>&&) = delete;
PluginSmartInterfaceType<INTERFACE>& operator=(PluginSmartInterfaceType<INTERFACE>&&) = delete;

PUSH_WARNING(DISABLE_WARNING_THIS_IN_MEMBER_INITIALIZER_LIST)
PluginSmartInterfaceType()
: _shell(nullptr)
, _monitor(*this)
, _job(*this)
{
}
POP_WARNING()
virtual ~PluginSmartInterfaceType()
{
ASSERT(_shell == nullptr);
ASSERT(_job.IsIdle() == true);
}

class RegisterJob {
public:
RegisterJob(RegisterJob&&) = delete;
RegisterJob(const RegisterJob&) = delete;
RegisterJob& operator=(const RegisterJob&) = delete;
RegisterJob& operator=(RegisterJob&&) = delete;

RegisterJob(PluginSmartInterfaceType& parent)
: _parent(parent)
{
}
~RegisterJob() = default;

public:
void Dispatch()
{
_parent.Register();
}

private:
PluginSmartInterfaceType& _parent;
};

using Job = Core::IWorkerPool::JobType<RegisterJob>;

public:
bool IsOperational() const
{
return (_monitor.IsOperational());
}
uint32_t Open(PluginHost::IShell* shell, const string& callsign)
{
ASSERT(_shell == nullptr);
ASSERT(_job.IsIdle() == true);

if(shell != nullptr) {

_shell = shell;
_shell->AddRef();

_monitor.Callsign(callsign);

_job.Submit();

}

return (Core::ERROR_NONE);
}
uint32_t Close()
{
ASSERT(_shell != nullptr);

if(_shell != nullptr) {
_job.Revoke();
_monitor.Unregister(_shell);
_shell->Release();
_shell = nullptr;
}

return (Core::ERROR_NONE);
}

INTERFACE* Interface()
{
return (_monitor.Interface());
}
const INTERFACE* Interface() const
{
return (_monitor.Interface());
}
PluginHost::IShell* PluginInterface()
{
_shell->AddRef();
return _shell;
}
const PluginHost::IShell* PluginInterface() const
{
_shell->AddRef();
return _shell;
}

// Allow a derived class to take action on a new interface, or almost dissapeared interface..
virtual void Operational(const bool upAndRunning)
{
}

private:
friend Monitor;
friend Job;

void Activated(INTERFACE* plugin)
{
Operational(true);
}
void Deactivated()
{
Operational(false);
}

void Register()
{
_monitor.Register(_shell);
}

private:
PluginHost::IShell* _shell;
Monitor _monitor;
Job _job;
};

template <typename INTERFACE, Core::ProxyType<RPC::IIPCServer> ENGINE() = DefaultInvokeServer>
class SmartControllerInterfaceType {

Expand Down Expand Up @@ -444,10 +624,12 @@ POP_WARNING()
}
PluginHost::IShell* ControllerInterface()
{
_controller->AddRef();
return _controller;
}
const PluginHost::IShell* ControllerInterface() const
{
_controller->AddRef();
return _controller;
}

Expand Down

0 comments on commit 021c321

Please sign in to comment.