genode/base-hw/src/base/singleton.h

54 lines
1.8 KiB
C++

/*
* \brief Helper for creating singleton objects
* \author Norman Feske
* \date 2013-05-14
*
* 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'. 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 _SINGLETON_H_
#define _SINGLETON_H_
inline void *operator new(Genode::size_t, void *at) { return at; }
template <typename T, int ALIGN = 2, typename... Args>
static inline T *unsynchronized_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.
*/
static bool initialized;
static int inst[sizeof(T)/sizeof(int) + 1] __attribute__((aligned(ALIGN)));
/* execute constructor on first call */
if (!initialized) {
initialized = true;
new (&inst) T(args...);
}
return reinterpret_cast<T *>(inst);
}
#endif /* _SINGLETON_H_ */