Mistake on this page?
Report an issue in GitHub or email us
SingletonPtr.h
1 
2 /** \addtogroup platform */
3 /** @{*/
4 /**
5  * \defgroup platform_SingletonPtr SingletonPtr class
6  * @{
7  */
8 /* mbed Microcontroller Library
9  * Copyright (c) 2006-2013 ARM Limited
10  * SPDX-License-Identifier: Apache-2.0
11  *
12  * Licensed under the Apache License, Version 2.0 (the "License");
13  * you may not use this file except in compliance with the License.
14  * You may obtain a copy of the License at
15  *
16  * http://www.apache.org/licenses/LICENSE-2.0
17  *
18  * Unless required by applicable law or agreed to in writing, software
19  * distributed under the License is distributed on an "AS IS" BASIS,
20  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21  * See the License for the specific language governing permissions and
22  * limitations under the License.
23  */
24 #ifndef SINGLETONPTR_H
25 #define SINGLETONPTR_H
26 
27 #include <stdlib.h>
28 #include <stdint.h>
29 #include <new>
30 #include "platform/mbed_assert.h"
31 #include "platform/mbed_atomic.h"
32 #ifdef MBED_CONF_RTOS_PRESENT
33 #include "cmsis_os2.h"
34 #endif
35 
36 #ifdef MBED_CONF_RTOS_PRESENT
37 extern osMutexId_t singleton_mutex_id;
38 #endif
39 
40 /** Lock the singleton mutex
41  *
42  * This function is typically used to provide
43  * exclusive access when initializing a
44  * global object.
45  */
46 inline static void singleton_lock(void)
47 {
48 #ifdef MBED_CONF_RTOS_PRESENT
49  if (!singleton_mutex_id) {
50  // RTOS has not booted yet so no mutex is needed
51  return;
52  }
53  osMutexAcquire(singleton_mutex_id, osWaitForever);
54 #endif
55 }
56 
57 /** Unlock the singleton mutex
58  *
59  * This function is typically used to provide
60  * exclusive access when initializing a
61  * global object.
62  */
63 inline static void singleton_unlock(void)
64 {
65 #ifdef MBED_CONF_RTOS_PRESENT
66  if (!singleton_mutex_id) {
67  // RTOS has not booted yet so no mutex is needed
68  return;
69  }
70  osMutexRelease(singleton_mutex_id);
71 #endif
72 }
73 
74 /** Utility class for creating an using a singleton
75  *
76  * @note Synchronization level: Thread safe
77  *
78  * @note: This class must only be used in a static context -
79  * this class must never be allocated or created on the
80  * stack.
81  *
82  * @note: This class is lazily initialized on first use.
83  * This class is a POD type so if it is not used it will
84  * be garbage collected.
85  */
86 template <class T>
87 struct SingletonPtr {
88 
89  /** Get a pointer to the underlying singleton
90  *
91  * @returns
92  * A pointer to the singleton
93  */
94  T *get() const
95  {
96  T *p = static_cast<T *>(core_util_atomic_load_ptr(&_ptr));
97  if (p == NULL) {
99  p = static_cast<T *>(_ptr);
100  if (p == NULL) {
101  p = new (_data) T();
102  core_util_atomic_store_ptr(&_ptr, p);
103  }
105  }
106  // _ptr was not zero initialized or was
107  // corrupted if this assert is hit
108  MBED_ASSERT(p == reinterpret_cast<T *>(&_data));
109  return p;
110  }
111 
112  /** Get a pointer to the underlying singleton
113  *
114  * @returns
115  * A pointer to the singleton
116  */
117  T *operator->() const
118  {
119  return get();
120  }
121 
122  /** Get a reference to the underlying singleton
123  *
124  * @returns
125  * A reference to the singleton
126  */
127  T &operator*() const
128  {
129  return *get();
130  }
131 
132  // This is zero initialized when in global scope
133  mutable void *_ptr;
134 #if __cplusplus >= 201103L && !defined __CC_ARM
135  // Align data appropriately (ARM Compiler 5 does not support alignas in C++11 mode)
136  alignas(T) mutable char _data[sizeof(T)];
137 #else
138  // Force data to be 8 byte aligned
139  mutable uint64_t _data[(sizeof(T) + sizeof(uint64_t) - 1) / sizeof(uint64_t)];
140 #endif
141 };
142 
143 #endif
144 /**@}*/
145 
146 /**@}*/
static void singleton_lock(void)
Lock the singleton mutex.
Definition: SingletonPtr.h:46
T * operator->() const
Get a pointer to the underlying singleton.
Definition: SingletonPtr.h:117
Utility class for creating an using a singleton.
Definition: SingletonPtr.h:87
static void singleton_unlock(void)
Unlock the singleton mutex.
Definition: SingletonPtr.h:63
MBED_FORCEINLINE void * core_util_atomic_load_ptr(void *const volatile *valuePtr)
Atomic load.
#define MBED_ASSERT(expr)
MBED_ASSERT Declare runtime assertions: results in runtime error if condition is false.
Definition: mbed_assert.h:65
T & operator*() const
Get a reference to the underlying singleton.
Definition: SingletonPtr.h:127
MBED_FORCEINLINE void core_util_atomic_store_ptr(void *volatile *valuePtr, void *value)
Atomic store.
Important Information for this Arm website

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.