Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Source/Thunder/Controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ namespace Plugin {

class Sink
: public PluginHost::IPlugin::INotification
, public PluginHost::IPlugin::INotificationExtended
, public PluginHost::ISubSystem::INotification {
private:
class Job {
Expand Down Expand Up @@ -109,9 +110,18 @@ namespace Plugin {
{
_parent.NotifyStateChange(callsign, PluginHost::IShell::UNAVAILABLE, plugin->Reason());
}
void Hibernated(const string& callsign, PluginHost::IShell* plugin) override
{
_parent.NotifyStateChange(callsign, PluginHost::IShell::HIBERNATED, plugin->Reason());
}
void Destroyed(const string& callsign, PluginHost::IShell* plugin) override
{
_parent.NotifyStateChange(callsign, PluginHost::IShell::DESTROYED, plugin->Reason());
}

BEGIN_INTERFACE_MAP(Sink)
INTERFACE_ENTRY(PluginHost::IPlugin::INotification)
INTERFACE_ENTRY(PluginHost::IPlugin::INotificationExtended)
END_INTERFACE_MAP

private:
Expand Down
25 changes: 25 additions & 0 deletions Source/Thunder/PluginServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -319,19 +319,43 @@ namespace PluginHost {
void Server::Service::Register(IPlugin::INotification * sink, const Core::OptionalType<string>& callsign) /* override */
{
_administrator.Register(sink, callsign);

IPlugin::INotificationExtended* extended = sink->QueryInterface<IPlugin::INotificationExtended>();
if (extended != nullptr) {
_administrator.Register(extended, callsign);
extended->Release();
}
Comment on lines 319 to +327
}

void Server::Service::Unregister(IPlugin::INotification * sink, const Core::OptionalType<string>& callsign) /* override */
{
IPlugin::INotificationExtended* extended = sink->QueryInterface<IPlugin::INotificationExtended>();
if (extended != nullptr) {
_administrator.Unregister(extended, callsign);
extended->Release();
}

_administrator.Unregister(sink, callsign);
}

void Server::Service::Register(IPlugin::INotification * sink, const uint32_t interface_id)
{
_administrator.Register(sink, interface_id);

IPlugin::INotificationExtended* extended = sink->QueryInterface<IPlugin::INotificationExtended>();
if (extended != nullptr) {
_administrator.Register(extended, interface_id);
extended->Release();
}
}
void Server::Service::Unregister(IPlugin::INotification * sink, const uint32_t interface_id)
{
IPlugin::INotificationExtended* extended = sink->QueryInterface<IPlugin::INotificationExtended>();
if (extended != nullptr) {
_administrator.Unregister(extended, interface_id);
extended->Release();
}

_administrator.Unregister(sink, interface_id);
}

Expand Down Expand Up @@ -797,6 +821,7 @@ namespace PluginHost {
// Both branches are reachable when HIBERNATE_ENABLED is defined.
if (result == Core::ERROR_NONE) {
if (State() == IShell::state::HIBERNATED) {
_administrator.Hibernated(Callsign(), this);
SYSLOG(Logging::Startup, ("Hibernated plugin [%s]:[%s]", ClassName().c_str(), Callsign().c_str()));
} else {
// wakeup occured right after hibernation finished
Expand Down
69 changes: 54 additions & 15 deletions Source/Thunder/PluginServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -960,6 +960,7 @@ namespace PluginHost {
// It's reference counted, so just take it out of the list, state to DESTROYED
// Also unsubscribe all subscribers. They need to go..
State(DESTROYED);
_administrator.Destroyed(Callsign(), this);

Comment on lines 960 to 964
Comment on lines 960 to 964
Unlock();
}
Expand Down Expand Up @@ -2663,6 +2664,7 @@ namespace PluginHost {
};
};

template <typename NOTIFICATION>
class Notifiers
{
public:
Expand All @@ -2688,7 +2690,7 @@ namespace PluginHost {

//return true when added
template <typename... Args>
bool Add(PluginHost::IPlugin::INotification* notification, Args&&... args)
bool Add(NOTIFICATION* notification, Args&&... args)
{
_notificationLock.Lock();

Expand All @@ -2710,16 +2712,16 @@ namespace PluginHost {

// return true when removed
template <typename... Args>
bool Remove(const PluginHost::IPlugin::INotification* const notification, Args&&... args)
bool Remove(const NOTIFICATION* const notification, Args&&... args)
{
bool found = false;

_notificationLock.Lock();

auto range = _notifiers.equal_range(const_cast<PluginHost::IPlugin::INotification*>(notification));
auto range = _notifiers.equal_range(const_cast<NOTIFICATION*>(notification));
for (auto it = range.first; it != range.second; ++it) {
if (it->second.IsEqual(std::forward<Args>(args)...) == true) {
PluginHost::IPlugin::INotification* foundnotification = it->first;
NOTIFICATION* foundnotification = it->first;
_notifiers.erase(it);
foundnotification->Release();
foundnotification = nullptr;
Expand All @@ -2731,14 +2733,14 @@ namespace PluginHost {

return found;
}
void RemoveAll(const PluginHost::IPlugin::INotification* const notification)
void RemoveAll(const NOTIFICATION* const notification)
{
_notificationLock.Lock();

auto range = _notifiers.equal_range(const_cast<PluginHost::IPlugin::INotification*>(notification));
auto range = _notifiers.equal_range(const_cast<NOTIFICATION*>(notification));
auto it = range.first;
while (it != range.second) {
PluginHost::IPlugin::INotification* foundnotification = it->first;
NOTIFICATION* foundnotification = it->first;
it = _notifiers.erase(it);
foundnotification->Release();
foundnotification = nullptr;
Expand All @@ -2753,7 +2755,7 @@ namespace PluginHost {
auto it = _notifiers.begin();
while (it != _notifiers.end()) {
if (static_cast<const Core::IUnknown*>(it->first) == notification) {
PluginHost::IPlugin::INotification* foundnotification = it->first;
NOTIFICATION* foundnotification = it->first;
it = _notifiers.erase(it);
foundnotification->Release();
foundnotification = nullptr;
Expand All @@ -2764,7 +2766,7 @@ namespace PluginHost {

_notificationLock.Unlock();
}
void Notify(const string& callsign, PluginHost::IShell* entry, Core::hresult (PluginHost::IPlugin::INotification::*notificatonmethod)(const string& callsign, IShell* plugin))
void Notify(const string& callsign, PluginHost::IShell* entry, Core::hresult (NOTIFICATION::*notificatonmethod)(const string& callsign, IShell* plugin))
{
_notificationLock.Lock();

Expand All @@ -2773,7 +2775,7 @@ namespace PluginHost {
if (it->second.SendNotification(callsign, entry) == true) {
Core::hresult result = (it->first->*notificatonmethod)(callsign, entry);
if (result == Core::ERROR_CANCEL) {
PluginHost::IPlugin::INotification* foundnotification = it->first;
NOTIFICATION* foundnotification = it->first;
it = _notifiers.erase(it);
foundnotification->Release();
foundnotification = nullptr;
Expand All @@ -2794,7 +2796,7 @@ namespace PluginHost {

for (const auto& notifier : _notifiers) {
if (notifier.second.SendNotification(callsign, entry) == true) {
PluginHost::IPlugin::ILifeTime* lifeTime = notifier.first->QueryInterface<PluginHost::IPlugin::ILifeTime>();
PluginHost::IPlugin::ILifeTime* lifeTime = notifier.first->template QueryInterface<PluginHost::IPlugin::ILifeTime>();
if (lifeTime != nullptr) {
(lifeTime->*notificatonmethod)(callsign, entry);
lifeTime->Release();
Expand All @@ -2819,7 +2821,7 @@ namespace PluginHost {

private:
template <typename... Args>
bool RegistrationAllowed(PluginHost::IPlugin::INotification* notification, Args&&... args) const
bool RegistrationAllowed(NOTIFICATION* notification, Args&&... args) const
{
bool notallowed = false;
auto range = _notifiers.equal_range(notification);
Expand All @@ -2833,11 +2835,10 @@ namespace PluginHost {
}

private:
std::unordered_multimap<PluginHost::IPlugin::INotification*, Notifier> _notifiers;
std::unordered_multimap<NOTIFICATION*, Notifier> _notifiers;
mutable Core::CriticalSection _notificationLock;
};


using Plugins = std::unordered_map<string, Core::ProxyType<Service>>;
using RemoteInstantiators = std::unordered_map<string, IRemoteInstantiation*>;
using ShellNotifiers = std::vector<Exchange::Controller::IShells::INotification*>;
Expand Down Expand Up @@ -3689,6 +3690,7 @@ namespace PluginHost {
, _notificationLock()
, _services()
, _notifiers()
, _extendedNotifiers()
, _engine(Core::ProxyType<RPC::InvokeServer>::Create(&(server._dispatcher)))
, _processAdministrator(
*this,
Expand Down Expand Up @@ -3816,6 +3818,14 @@ namespace PluginHost {
{
_notifiers.Notify(callsign, entry, &PluginHost::IPlugin::INotification::CancelableUnavailable);
}
void Hibernated(const string& callsign, PluginHost::IShell* entry)
{
_extendedNotifiers.Notify(callsign, entry, &PluginHost::IPlugin::INotificationExtended::CancelableHibernated);
}
void Destroyed(const string& callsign, PluginHost::IShell* entry)
{
_extendedNotifiers.Notify(callsign, entry, &PluginHost::IPlugin::INotificationExtended::CancelableDestroyed);
}
void StateControlStateChange(const string& callsign, const IStateControl::state state)
{
_server.StateControlStateChange(callsign, state);
Expand Down Expand Up @@ -3856,6 +3866,15 @@ namespace PluginHost {
}
}
}
void Register(PluginHost::IPlugin::INotificationExtended* sink, const Core::OptionalType<string>& callsign = {})
{
if (callsign.IsSet() == true) {
_extendedNotifiers.Add(sink, callsign.Value());
}
else {
_extendedNotifiers.Add(sink);
}
}
void Unregister(const PluginHost::IPlugin::INotification* sink, const Core::OptionalType<string>& callsign = {})
{
if (callsign.IsSet() == true) {
Expand All @@ -3864,6 +3883,14 @@ namespace PluginHost {
_notifiers.Remove(sink);
}
}
void Unregister(const PluginHost::IPlugin::INotificationExtended* sink, const Core::OptionalType<string>& callsign = {})
{
if (callsign.IsSet() == true) {
_extendedNotifiers.Remove(sink, callsign.Value());
} else {
_extendedNotifiers.Remove(sink);
}
}
void Register(IPlugin::INotification* sink, const uint32_t interface_id)
{
if( _notifiers.Add(sink, interface_id) == true) {
Expand All @@ -3876,6 +3903,14 @@ namespace PluginHost {
{
_notifiers.Remove(sink, interface_id);
}
void Register(IPlugin::INotificationExtended* sink, const uint32_t interface_id)
{
_extendedNotifiers.Add(sink, interface_id);
}
void Unregister(IPlugin::INotificationExtended* sink, const uint32_t interface_id)
{
_extendedNotifiers.Remove(sink, interface_id);
}
inline void* QueryInterfaceByCallsign(const uint32_t id, const string& name)
{
void* result = nullptr;
Expand Down Expand Up @@ -4305,6 +4340,9 @@ namespace PluginHost {
if (interfaceId == PluginHost::IPlugin::INotification::ID) {
_notifiers.RemoveAll(remote);
}
else if (interfaceId == PluginHost::IPlugin::INotificationExtended::ID) {
_extendedNotifiers.RemoveAll(remote);
}
else if (interfaceId == IShell::IConnectionServer::INotification::ID) {

_notificationLock.Lock();
Expand Down Expand Up @@ -4451,7 +4489,8 @@ namespace PluginHost {
Core::CriticalSection _notificationLock;
Plugins _services;
mutable RemoteInstantiators _instantiators;
Notifiers _notifiers;
Notifiers<PluginHost::IPlugin::INotification> _notifiers;
Notifiers<PluginHost::IPlugin::INotificationExtended> _extendedNotifiers;
Core::ProxyType<RPC::InvokeServer> _engine;
CommunicatorServer _processAdministrator;
Core::SinkType<SubSystems> _subSystems;
Expand Down
1 change: 1 addition & 0 deletions Source/com/Ids.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ namespace RPC {
ID_COMPOSIT_PLUGIN = (ID_OFFSET_INTERNAL + 0x003B),
ID_COMPOSIT_PLUGIN_CALLBACK = (ID_OFFSET_INTERNAL + 0x003C),
ID_DISPATCHER_CALLBACK = (ID_OFFSET_INTERNAL + 0x003D),
ID_PLUGIN_NOTIFICATION_EXTENDED = (ID_OFFSET_INTERNAL + 0x003E),

ID_SHELL = (ID_OFFSET_INTERNAL + 0x0040),
ID_SHELL_COMLINK = (ID_OFFSET_INTERNAL + 0x0041),
Expand Down
34 changes: 34 additions & 0 deletions Source/plugins/IPlugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,40 @@ namespace PluginHost {

};

struct INotificationExtended : virtual public Core::IUnknown {

enum { ID = RPC::ID_PLUGIN_NOTIFICATION_EXTENDED };

~INotificationExtended() override = default;

//! @{
//! ================================== CALLED ON THREADPOOL THREAD =====================================
//! Whenever a plugin transitions to a hibernated or destroyed state, this is reported to an observer.
//! @}

// @stubgen:omit
virtual void Hibernated(const string&, IShell*)
{
ASSERT(false);
}
// @stubgen:omit
virtual void Destroyed(const string&, IShell*)
{
ASSERT(false);
}

virtual Core::hresult CancelableHibernated(const string& callsign, IShell* plugin)
{
Hibernated(callsign, plugin);
return Core::ERROR_NONE;
}
virtual Core::hresult CancelableDestroyed(const string& callsign, IShell* plugin)
{
Destroyed(callsign, plugin);
return Core::ERROR_NONE;
}
};

struct ILifeTime : virtual public Core::IUnknown {

enum { ID = RPC::ID_PLUGIN_LIFETIME };
Expand Down
Loading