genode/repos/os/src/lib/sandbox/child_registry.h

150 lines
3.0 KiB
C++

/*
* \brief Child registry
* \author Norman Feske
* \date 2010-04-27
*/
/*
* Copyright (C) 2010-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _LIB__SANDBOX__CHILD_REGISTRY_H_
#define _LIB__SANDBOX__CHILD_REGISTRY_H_
/* local includes */
#include <child.h>
#include <name_registry.h>
#include <alias.h>
#include <report.h>
namespace Sandbox { struct Child_registry; }
class Sandbox::Child_registry : public Name_registry, Child_list
{
private:
List<Alias> _aliases { };
bool _unique(const char *name) const
{
/* check for name clash with an existing child */
List_element<Sandbox::Child> const *curr = first();
for (; curr; curr = curr->next())
if (curr->object()->has_name(name))
return false;
/* check for name clash with an existing alias */
for (Alias const *a = _aliases.first(); a; a = a->next()) {
if (Alias::Name(name) == a->name)
return false;
}
return true;
}
public:
/**
* Exception type
*/
class Alias_name_is_not_unique { };
/**
* Register child
*/
void insert(Child *child)
{
Child_list::insert(&child->_list_element);
}
/**
* Unregister child
*/
void remove(Child *child)
{
Child_list::remove(&child->_list_element);
}
/**
* Register alias
*/
void insert_alias(Alias *alias)
{
if (!_unique(alias->name.string())) {
error("alias name ", alias->name, " is not unique");
throw Alias_name_is_not_unique();
}
_aliases.insert(alias);
}
/**
* Unregister alias
*/
void remove_alias(Alias *alias)
{
_aliases.remove(alias);
}
/**
* Return any of the registered children, or 0 if no child exists
*/
Child *any()
{
return first() ? first()->object() : 0;
}
/**
* Return any of the registered aliases, or 0 if no alias exists
*/
Alias *any_alias()
{
return _aliases.first() ? _aliases.first() : 0;
}
template <typename FN>
void for_each_child(FN const &fn) const
{
Genode::List_element<Child> const *curr = first();
for (; curr; curr = curr->next())
fn(*curr->object());
}
template <typename FN>
void for_each_child(FN const &fn)
{
Genode::List_element<Child> *curr = first(), *next = nullptr;
for (; curr; curr = next) {
next = curr->next();
fn(*curr->object());
}
}
void report_state(Xml_generator &xml, Report_detail const &detail) const
{
for_each_child([&] (Child &child) { child.report_state(xml, detail); });
/* check for name clash with an existing alias */
for (Alias const *a = _aliases.first(); a; a = a->next()) {
xml.node("alias", [&] () {
xml.attribute("name", a->name);
xml.attribute("child", a->child);
});
}
}
Child::Name deref_alias(Child::Name const &name) override
{
for (Alias const *a = _aliases.first(); a; a = a->next())
if (name == a->name)
return a->child;
return name;
}
};
#endif /* _LIB__SANDBOX__CHILD_REGISTRY_H_ */