Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
6 changes: 4 additions & 2 deletions Source/Thunder/Controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,8 @@ namespace Plugin {
}
}

_service->Register(&_systemInfoReport);
_service->Register(static_cast<PluginHost::IPlugin::INotification*>(&_systemInfoReport));
_service->Register(static_cast<PluginHost::IPlugin::INotificationExtended*>(&_systemInfoReport));

if (config.Ui.Value() == true) {
_service->EnableWebServer(_T("UI"), EMPTY_STRING);
Expand Down Expand Up @@ -180,7 +181,8 @@ namespace Plugin {
_probe = nullptr;
}

_service->Unregister(&_systemInfoReport);
_service->Unregister(static_cast<PluginHost::IPlugin::INotification*>(&_systemInfoReport));
_service->Unregister(static_cast<PluginHost::IPlugin::INotificationExtended*>(&_systemInfoReport));

/* stop the file serving over http.... */
service->DisableWebServer();
Expand Down
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
11 changes: 11 additions & 0 deletions Source/Thunder/PluginServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,16 @@ namespace PluginHost {
_administrator.Unregister(sink, callsign);
}

void Server::Service::Register(IPlugin::INotificationExtended * sink, const Core::OptionalType<string>& callsign) /* override */
{
_administrator.Register(sink, callsign);
}

void Server::Service::Unregister(IPlugin::INotificationExtended * sink, const Core::OptionalType<string>& callsign) /* override */
{
_administrator.Unregister(sink, callsign);
}

void Server::Service::Register(IPlugin::INotification * sink, const uint32_t interface_id)
{
_administrator.Register(sink, interface_id);
Expand Down Expand Up @@ -797,6 +807,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
155 changes: 155 additions & 0 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 @@ -1291,6 +1292,8 @@ namespace PluginHost {
void Unregister(IPlugin::INotification* sink, const Core::OptionalType<string>& callsign) override;
void Register(IPlugin::INotification* sink, const uint32_t interface_id) override;
void Unregister(IPlugin::INotification* sink, const uint32_t interface_id) override;
void Register(IPlugin::INotificationExtended* sink, const Core::OptionalType<string>& callsign) override;
void Unregister(IPlugin::INotificationExtended* sink, const Core::OptionalType<string>& callsign) override;

string Model() const override {
return (_administrator.Configuration().Model());
Expand Down Expand Up @@ -2837,6 +2840,128 @@ namespace PluginHost {
mutable Core::CriticalSection _notificationLock;
};

class ExtendedNotifiers
{
public:
ExtendedNotifiers()
: _notifiers()
, _notificationLock()
{
}
~ExtendedNotifiers() = default;

ExtendedNotifiers(ExtendedNotifiers&&) = delete;
ExtendedNotifiers(const ExtendedNotifiers&) = delete;
ExtendedNotifiers& operator=(ExtendedNotifiers&&) = delete;
ExtendedNotifiers& operator=(const ExtendedNotifiers&) = delete;

template <typename... Args>
bool Add(PluginHost::IPlugin::INotificationExtended* notification, Args&&... args)
{
_notificationLock.Lock();

bool allowed = RegistrationAllowed(notification, std::forward<Args>(args)...);

ASSERT(allowed == true);

if (allowed == true) {
notification->AddRef();
_notifiers.emplace(std::piecewise_construct,
std::forward_as_tuple(notification),
std::forward_as_tuple(std::forward<Args>(args)...));
}

_notificationLock.Unlock();

return allowed;
}

template <typename... Args>
bool Remove(const PluginHost::IPlugin::INotificationExtended* const notification, Args&&... args)
{
bool found = false;

_notificationLock.Lock();

auto range = _notifiers.equal_range(const_cast<PluginHost::IPlugin::INotificationExtended*>(notification));
for (auto it = range.first; it != range.second; ++it) {
if (it->second.IsEqual(std::forward<Args>(args)...) == true) {
PluginHost::IPlugin::INotificationExtended* foundnotification = it->first;
_notifiers.erase(it);
foundnotification->Release();
foundnotification = nullptr;
found = true;
break;
}
}

_notificationLock.Unlock();

return found;
}

void RemoveAll(const Core::IUnknown* const notification)
{
_notificationLock.Lock();

auto it = _notifiers.begin();
while (it != _notifiers.end()) {
if (static_cast<const Core::IUnknown*>(it->first) == notification) {
PluginHost::IPlugin::INotificationExtended* foundnotification = it->first;
it = _notifiers.erase(it);
foundnotification->Release();
foundnotification = nullptr;
} else {
++it;
}
}

_notificationLock.Unlock();
}

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

auto it = _notifiers.begin();
while (it != _notifiers.end()) {
if (it->second.SendNotification(callsign, entry) == true) {
Core::hresult result = (it->first->*notificatonmethod)(callsign, entry);
if (result == Core::ERROR_CANCEL) {
PluginHost::IPlugin::INotificationExtended* foundnotification = it->first;
it = _notifiers.erase(it);
foundnotification->Release();
foundnotification = nullptr;
} else {
++it;
}
} else {
++it;
}
}

_notificationLock.Unlock();
}

private:
template <typename... Args>
bool RegistrationAllowed(PluginHost::IPlugin::INotificationExtended* notification, Args&&... args) const
{
bool notallowed = false;
auto range = _notifiers.equal_range(notification);
for (auto it = range.first; it != range.second; ++it) {
notallowed = it->second.ConsideredDuplicate(std::forward<Args>(args)...);
if (notallowed == true) {
break;
}
}
return (notallowed == false);
}

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

using Plugins = std::unordered_map<string, Core::ProxyType<Service>>;
using RemoteInstantiators = std::unordered_map<string, IRemoteInstantiation*>;
Expand Down Expand Up @@ -3689,6 +3814,7 @@ namespace PluginHost {
, _notificationLock()
, _services()
, _notifiers()
, _extendedNotifiers()
, _engine(Core::ProxyType<RPC::InvokeServer>::Create(&(server._dispatcher)))
, _processAdministrator(
*this,
Expand Down Expand Up @@ -3816,6 +3942,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 +3990,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 +4007,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 Down Expand Up @@ -4305,6 +4456,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 @@ -4452,6 +4606,7 @@ namespace PluginHost {
Plugins _services;
mutable RemoteInstantiators _instantiators;
Notifiers _notifiers;
ExtendedNotifiers _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
2 changes: 2 additions & 0 deletions Source/plugins/IShell.h
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,8 @@ namespace PluginHost {
virtual void Unregister(IPlugin::INotification* sink, const Core::OptionalType<string>& callsign = {}) = 0;
virtual void Register(IPlugin::INotification* sink, const uint32_t interface_id) = 0;
virtual void Unregister(IPlugin::INotification* sink, const uint32_t interface_id) = 0;
virtual void Register(IPlugin::INotificationExtended* sink, const Core::OptionalType<string>& callsign = {}) = 0;
virtual void Unregister(IPlugin::INotificationExtended* sink, const Core::OptionalType<string>& callsign = {}) = 0;
virtual state State() const = 0;
virtual void* /* @interface:id */ QueryInterfaceByCallsign(const uint32_t id, const string& name) = 0;
Comment thread
nxtum marked this conversation as resolved.

Expand Down
Loading