SingletonPtr.h 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. /** \addtogroup platform */
  2. /** @{*/
  3. /**
  4. * \defgroup platform_SingletonPtr SingletonPtr class
  5. * @{
  6. */
  7. /* mbed Microcontroller Library
  8. * Copyright (c) 2006-2013 ARM Limited
  9. *
  10. * Licensed under the Apache License, Version 2.0 (the "License");
  11. * you may not use this file except in compliance with the License.
  12. * You may obtain a copy of the License at
  13. *
  14. * http://www.apache.org/licenses/LICENSE-2.0
  15. *
  16. * Unless required by applicable law or agreed to in writing, software
  17. * distributed under the License is distributed on an "AS IS" BASIS,
  18. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  19. * See the License for the specific language governing permissions and
  20. * limitations under the License.
  21. */
  22. #ifndef SINGLETONPTR_H
  23. #define SINGLETONPTR_H
  24. #include <stdint.h>
  25. #include <new>
  26. #include "platform/mbed_assert.h"
  27. #ifdef MBED_CONF_RTOS_PRESENT
  28. #include "cmsis_os2.h"
  29. #endif
  30. #ifdef MBED_CONF_RTOS_PRESENT
  31. extern osMutexId_t singleton_mutex_id;
  32. #endif
  33. /** Lock the singleton mutex
  34. *
  35. * This function is typically used to provide
  36. * exclusive access when initializing a
  37. * global object.
  38. */
  39. inline static void singleton_lock(void)
  40. {
  41. #ifdef MBED_CONF_RTOS_PRESENT
  42. osMutexAcquire(singleton_mutex_id, osWaitForever);
  43. #endif
  44. }
  45. /** Unlock the singleton mutex
  46. *
  47. * This function is typically used to provide
  48. * exclusive access when initializing a
  49. * global object.
  50. */
  51. inline static void singleton_unlock(void)
  52. {
  53. #ifdef MBED_CONF_RTOS_PRESENT
  54. osMutexRelease(singleton_mutex_id);
  55. #endif
  56. }
  57. /** Utility class for creating an using a singleton
  58. *
  59. * @note Synchronization level: Thread safe
  60. *
  61. * @note: This class must only be used in a static context -
  62. * this class must never be allocated or created on the
  63. * stack.
  64. *
  65. * @note: This class is lazily initialized on first use.
  66. * This class is a POD type so if it is not used it will
  67. * be garbage collected.
  68. */
  69. template <class T>
  70. struct SingletonPtr {
  71. /** Get a pointer to the underlying singleton
  72. *
  73. * @returns
  74. * A pointer to the singleton
  75. */
  76. T *get()
  77. {
  78. if (NULL == _ptr) {
  79. singleton_lock();
  80. if (NULL == _ptr) {
  81. _ptr = new (_data) T();
  82. }
  83. singleton_unlock();
  84. }
  85. // _ptr was not zero initialized or was
  86. // corrupted if this assert is hit
  87. MBED_ASSERT(_ptr == (T *)&_data);
  88. return _ptr;
  89. }
  90. /** Get a pointer to the underlying singleton
  91. *
  92. * @returns
  93. * A pointer to the singleton
  94. */
  95. T *operator->()
  96. {
  97. return get();
  98. }
  99. // This is zero initialized when in global scope
  100. T *_ptr;
  101. // Force data to be 4 byte aligned
  102. uint32_t _data[(sizeof(T) + sizeof(uint32_t) - 1) / sizeof(uint32_t)];
  103. };
  104. #endif
  105. /**@}*/
  106. /**@}*/