genode/repos/base/include/base/attached_rom_dataspace.h

140 lines
3.8 KiB
C
Raw Normal View History

/*
* \brief Utility to open a ROM session and locally attach its content
* \author Norman Feske
* \date 2012-01-09
*/
/*
* Copyright (C) 2012-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 _INCLUDE__BASE__ATTACHED_ROM_DATASPACE_H_
#define _INCLUDE__BASE__ATTACHED_ROM_DATASPACE_H_
#include <util/reconstructible.h>
#include <util/xml_node.h>
#include <base/attached_dataspace.h>
#include <rom_session/connection.h>
namespace Genode { class Attached_rom_dataspace; }
class Genode::Attached_rom_dataspace
{
private:
Region_map &_rm;
Rom_connection _rom;
/*
* A ROM module may change or disappear over the lifetime of a ROM
* session. In contrast to the plain 'Attached_dataspace', which is
* always be valid once constructed, a 'Attached_rom_dataspace' has
* to handle the validity of the dataspace.
*/
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
Constructible<Attached_dataspace> _ds { };
/**
* Try to attach the ROM module, ignore invalid dataspaces
*/
void _try_attach()
{
/*
* Normally, '_ds.construct()' would implicitly destruct an
* existing dataspace upon re-construction. However, we have to
* explicitly destruct the original dataspace prior calling
* '_rom.dataspace()'.
*
* The ROM server may destroy the original dataspace when the
* 'dataspace()' method is called. In this case, all existing
* mappings of the dataspace will be flushed by core. A destruction
* of 'Attached_dataspace' after this point will attempt to detach
* the already flushed mappings, thereby producing error messages
* at core.
*/
_ds.destruct();
try { _ds.construct(_rm, _rom.dataspace()); }
catch (Attached_dataspace::Invalid_dataspace) { }
}
public:
/**
* Constructor
*
* \throw Rom_connection::Rom_connection_failed
* \throw Region_map::Region_conflict
* \throw Region_map::Invalid_dataspace
* \throw Out_of_ram
* \throw Out_of_caps
*/
Attached_rom_dataspace(Env &env, char const *name)
: _rm(env.rm()), _rom(env, name) { _try_attach(); }
/**
* Return capability of the used dataspace
*/
Dataspace_capability cap() const { return _ds->cap(); }
template <typename T> T *local_addr() {
return _ds->local_addr<T>(); }
template <typename T> T const *local_addr() const {
return _ds->local_addr<T const>(); }
size_t size() const { return _ds.constructed() ? _ds->size() : 0; }
/**
* Register signal handler for ROM module changes
*/
void sigh(Signal_context_capability sigh) { _rom.sigh(sigh); }
/**
* Update ROM module content, re-attach if needed
*/
void update()
{
/*
* If the dataspace is already attached and the update fits into
* the existing dataspace, we can keep everything in place. The
* dataspace content gets updated by the call of '_rom.update'.
*/
if (_ds.constructed() && _rom.update() == true)
return;
/*
* If there was no valid dataspace attached beforehand or the
* new data size exceeds the capacity of the existing dataspace,
* replace the current dataspace by a new one.
*/
_try_attach();
}
/**
* Return true of content is present
*/
bool valid() const { return _ds.constructed(); }
/**
* Return dataspace content as XML node
*
* This method always returns a valid XML node. It never throws an
* exception. If the dataspace is invalid or does not contain properly
* formatted XML, the returned XML node has the form "<empty/>".
*/
Xml_node xml() const
{
try {
if (valid() && local_addr<void const>())
return Xml_node(local_addr<char>(), size());
} catch (Xml_node::Invalid_syntax) { }
return Xml_node("<empty/>");
}
};
#endif /* _INCLUDE__BASE__ATTACHED_ROM_DATASPACE_H_ */