summaryrefslogtreecommitdiff
path: root/include/service.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/service.h')
-rw-r--r--include/service.h232
1 files changed, 117 insertions, 115 deletions
diff --git a/include/service.h b/include/service.h
index 715d7c992..ca9533c70 100644
--- a/include/service.h
+++ b/include/service.h
@@ -1,16 +1,24 @@
/*
+ * Anope IRC Services
*
- * (C) 2003-2017 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2016 Adam <Adam@anope.org>
+ * Copyright (C) 2012-2017 Anope Team <team@anope.org>
*
- * Please read COPYING and README for further details.
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
*
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
*/
-#ifndef SERVICE_H
-#define SERVICE_H
+#pragma once
#include "services.h"
#include "anope.h"
@@ -23,151 +31,145 @@
*/
class CoreExport Service : public virtual Base
{
- static std::map<Anope::string, std::map<Anope::string, Service *> > Services;
- static std::map<Anope::string, std::map<Anope::string, Anope::string> > Aliases;
-
- static Service *FindService(const std::map<Anope::string, Service *> &services, const std::map<Anope::string, Anope::string> *aliases, const Anope::string &n)
- {
- std::map<Anope::string, Service *>::const_iterator it = services.find(n);
- if (it != services.end())
- return it->second;
-
- if (aliases != NULL)
- {
- std::map<Anope::string, Anope::string>::const_iterator it2 = aliases->find(n);
- if (it2 != aliases->end())
- return FindService(services, aliases, it2->second);
- }
-
- return NULL;
- }
+ Module *owner;
+ /* Service type, which should be the class name (eg "Command") */
+ Anope::string type;
+ /* Service name, commands are usually named service/command */
+ Anope::string name;
public:
- static Service *FindService(const Anope::string &t, const Anope::string &n)
- {
- std::map<Anope::string, std::map<Anope::string, Service *> >::const_iterator it = Services.find(t);
- if (it == Services.end())
- return NULL;
+ Service(Module *o, const Anope::string &t, const Anope::string &n);
+
+ Service(Module *o, const Anope::string &t) : Service(o, t, "") { }
- std::map<Anope::string, std::map<Anope::string, Anope::string> >::const_iterator it2 = Aliases.find(t);
- if (it2 != Aliases.end())
- return FindService(it->second, &it2->second, n);
+ virtual ~Service();
- return FindService(it->second, NULL, n);
- }
+ Module *GetOwner() const { return owner; }
- static std::vector<Anope::string> GetServiceKeys(const Anope::string &t)
- {
- std::vector<Anope::string> keys;
- std::map<Anope::string, std::map<Anope::string, Service *> >::iterator it = Services.find(t);
- if (it != Services.end())
- for (std::map<Anope::string, Service *>::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2)
- keys.push_back(it2->first);
- return keys;
- }
+ const Anope::string &GetType() const { return type; }
- static void AddAlias(const Anope::string &t, const Anope::string &n, const Anope::string &v)
- {
- std::map<Anope::string, Anope::string> &smap = Aliases[t];
- smap[n] = v;
- }
+ const Anope::string &GetName() const { return name; }
+};
- static void DelAlias(const Anope::string &t, const Anope::string &n)
- {
- std::map<Anope::string, Anope::string> &smap = Aliases[t];
- smap.erase(n);
- if (smap.empty())
- Aliases.erase(t);
- }
+class ServiceReferenceBase
+{
+ Anope::string type, name;
- Module *owner;
- /* Service type, which should be the class name (eg "Command") */
- Anope::string type;
- /* Service name, commands are usually named service/command */
- Anope::string name;
+ protected:
+ std::vector<Service *> services;
- Service(Module *o, const Anope::string &t, const Anope::string &n) : owner(o), type(t), name(n)
- {
- this->Register();
- }
+ public:
- virtual ~Service()
- {
- this->Unregister();
- }
+ ServiceReferenceBase() = default;
- void Register()
+ ServiceReferenceBase(const Anope::string &_type, const Anope::string &_name);
+ ServiceReferenceBase(const Anope::string &_type);
+
+ virtual ~ServiceReferenceBase();
+
+ explicit operator bool() const
{
- std::map<Anope::string, Service *> &smap = Services[this->type];
- if (smap.find(this->name) != smap.end())
- throw ModuleException("Service " + this->type + " with name " + this->name + " already exists");
- smap[this->name] = this;
+ return !this->services.empty();
}
- void Unregister()
- {
- std::map<Anope::string, Service *> &smap = Services[this->type];
- smap.erase(this->name);
- if (smap.empty())
- Services.erase(this->type);
- }
+ const Anope::string &GetType() const { return type; }
+ const Anope::string &GetName() const { return name; }
+
+ Service *GetService() const { return services.empty() ? nullptr : services[0]; }
+ const std::vector<Service *> &GetServices() const { return services; }
+ void SetService(Service *service);
+ void SetServices(const std::vector<Service *> &s);
};
-/** Like Reference, but used to refer to Services.
- */
template<typename T>
-class ServiceReference : public Reference<T>
+class ServiceReference : public ServiceReferenceBase
{
- Anope::string type;
- Anope::string name;
+ static_assert(std::is_base_of<Service, T>::value, "");
public:
- ServiceReference() { }
+ ServiceReference() : ServiceReferenceBase(T::NAME) { }
+ ServiceReference(const Anope::string &n) : ServiceReferenceBase(T::NAME, n) { }
- ServiceReference(const Anope::string &t, const Anope::string &n) : type(t), name(n)
+ operator T*() const
{
+ return static_cast<T*>(GetService());
}
- inline void operator=(const Anope::string &n)
+ T* operator->() const
{
- this->name = n;
- this->invalid = true;
+ return static_cast<T*>(GetService());
}
- operator bool() anope_override
+ T* operator*() const
{
- if (this->invalid)
- {
- this->invalid = false;
- this->ref = NULL;
- }
- if (!this->ref)
- {
- /* This really could be dynamic_cast in every case, except for when a module
- * creates its own service type (that other modules must include the header file
- * for), as the core is not compiled with it so there is no RTTI for it.
- */
- this->ref = static_cast<T *>(::Service::FindService(this->type, this->name));
- if (this->ref)
- this->ref->AddReference(this);
- }
- return this->ref;
+ return static_cast<T*>(GetService());
}
};
-class ServiceAlias
+template<typename T>
+class ServiceReferenceList : public ServiceReferenceBase
{
- Anope::string t, f;
+ static_assert(std::is_base_of<Service, T>::value, "");
+
public:
- ServiceAlias(const Anope::string &type, const Anope::string &from, const Anope::string &to) : t(type), f(from)
+ using ServiceReferenceBase::ServiceReferenceBase;
+
+ std::vector<T *> GetServices() const
{
- Service::AddAlias(type, from, to);
+ std::vector<T *> out;
+ std::transform(services.begin(), services.end(), std::back_inserter(out), [](Service *e) { return static_cast<T *>(e); });
+ return out;
}
+};
+
+class ServiceManager
+{
+ std::vector<ServiceReferenceBase *> references; // managed references
+ std::vector<Service *> services; // all registered services
+
+ /* Lookup services for a reference */
+ void Lookup(ServiceReferenceBase *reference);
- ~ServiceAlias()
+ /* Lookup services for all managed references */
+ void LookupAll();
+
+ std::vector<Service *> FindServices(const Anope::string &type);
+
+ static ServiceManager *manager;
+
+ public:
+ Service *FindService(const Anope::string &name);
+ Service *FindService(const Anope::string &type, const Anope::string &name);
+
+ template<typename T>
+ std::vector<T> FindServices()
{
- Service::DelAlias(t, f);
+ static_assert(std::is_base_of<Service, typename std::remove_pointer<T>::type>::value, "");
+ const char *type = std::remove_pointer<T>::type::NAME;
+ std::vector<Service *> s = FindServices(type);
+ std::vector<T> out;
+ std::transform(s.begin(), s.end(), std::back_inserter(out), [](Service *e) { return static_cast<T>(e); });
+ return out;
}
+
+ template<typename T>
+ T FindService(const Anope::string &name)
+ {
+ static_assert(std::is_base_of<Service, typename std::remove_pointer<T>::type>::value, "");
+ const char *type = std::remove_pointer<T>::type::NAME;
+ return static_cast<T>(FindService(type, name));
+ }
+
+ void Register(Service *service);
+
+ void Unregister(Service *service);
+
+ void RegisterReference(ServiceReferenceBase *reference);
+
+ void UnregisterReference(ServiceReferenceBase *reference);
+
+ static void Init();
+ static ServiceManager *Get();
+ static void Destroy();
};
-#endif // SERVICE_H