mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-31 08:25:38 +00:00
base: provide template for unmanaged singletons
An unmanaged singleton is a singleton object that isn't constructed or destructed implicitly through the C++ runtime enviroment. The new header provides a helper to create such objects and is located in src/base/include. ref #989
This commit is contained in:
parent
ea9c0e20ba
commit
212fc47768
74
base/src/base/include/unmanaged_singleton.h
Normal file
74
base/src/base/include/unmanaged_singleton.h
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* \brief Singleton objects that aren't implicitly constructed or destructed
|
||||
* \author Norman Feske
|
||||
* \author Martin Stein
|
||||
* \date 2013-12-04
|
||||
*
|
||||
* Before enabling the MMU on ARM, the 'cmpxchg' implementation is not always
|
||||
* guaranteed to work. For example, on the Raspberry Pi, the 'ldrex' as used by
|
||||
* 'cmpxchg' causes the machine to reboot. After enabling the MMU, everything
|
||||
* is fine. Hence, we need to avoid executing 'cmpxchg' prior this point.
|
||||
* Unfortunately, 'cmpxchg' is implicitly called each time when creating a
|
||||
* singleton object via a local-static object pattern. In this case, the
|
||||
* compiler generates code that calls the '__cxa_guard_acquire' function of the
|
||||
* C++ runtime, which, in turn, relies 'cmpxchg' for synchronization.
|
||||
*
|
||||
* The utility provided herein is an alternative way to create single object
|
||||
* instances without implicitly calling 'cmpxchg'. Furthermore, the created
|
||||
* objects are not destructed automatically at program exit which is useful
|
||||
* because it prevents the main thread of a program from destructing the
|
||||
* enviroment it needs to finish program close-down. Because object creation
|
||||
* is not synchronized via a spin lock, it must not be used in scenarios where
|
||||
* multiple threads may contend.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _UNMANAGED_SINGLETON_H_
|
||||
#define _UNMANAGED_SINGLETON_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/stdint.h>
|
||||
|
||||
/**
|
||||
* Placement new operator
|
||||
*
|
||||
* \param p destination address
|
||||
*/
|
||||
inline void * operator new(Genode::size_t, void * p) { return p; }
|
||||
|
||||
/**
|
||||
* Create a singleton object that isn't implicitly constructed or destructed
|
||||
*
|
||||
* \param T object type
|
||||
* \param ALIGNMENT object alignment
|
||||
* \param ARGS arguments to the object constructor
|
||||
*
|
||||
* \return object pointer
|
||||
*/
|
||||
template <typename T, int ALIGNMENT = 2, typename... ARGS>
|
||||
static inline T * unmanaged_singleton(ARGS... args)
|
||||
{
|
||||
/*
|
||||
* Each instantiation of the function template with a different type 'T'
|
||||
* yields a dedicated instance of the local static variables, thereby
|
||||
* creating the living space for the singleton objects.
|
||||
*/
|
||||
enum { OBJECT_SIZE = sizeof(T) / sizeof(char) + 1 };
|
||||
static bool object_constructed = false;
|
||||
static char object_space[OBJECT_SIZE] __attribute__((aligned(ALIGNMENT)));
|
||||
|
||||
/* execute constructor on first call */
|
||||
if (!object_constructed) {
|
||||
object_constructed = true;
|
||||
new (&object_space) T(args...);
|
||||
}
|
||||
return reinterpret_cast<T *>(object_space);
|
||||
}
|
||||
|
||||
#endif /* _UNMANAGED_SINGLETON_H_ */
|
Loading…
x
Reference in New Issue
Block a user