takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SingletonPtr.h Source File

SingletonPtr.h

00001 
00002 /** \addtogroup platform */
00003 /** @{*/
00004 /**
00005  * \defgroup platform_SingletonPtr SingletonPtr class
00006  * @{
00007  */
00008 /* mbed Microcontroller Library
00009  * Copyright (c) 2006-2013 ARM Limited
00010  *
00011  * Licensed under the Apache License, Version 2.0 (the "License");
00012  * you may not use this file except in compliance with the License.
00013  * You may obtain a copy of the License at
00014  *
00015  *     http://www.apache.org/licenses/LICENSE-2.0
00016  *
00017  * Unless required by applicable law or agreed to in writing, software
00018  * distributed under the License is distributed on an "AS IS" BASIS,
00019  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00020  * See the License for the specific language governing permissions and
00021  * limitations under the License.
00022  */
00023 #ifndef SINGLETONPTR_H
00024 #define SINGLETONPTR_H
00025 
00026 #include <stdint.h>
00027 #include <new>
00028 #include "platform/mbed_assert.h"
00029 #ifdef MBED_CONF_RTOS_PRESENT
00030 #include "cmsis_os2.h"
00031 #endif
00032 
00033 #ifdef MBED_CONF_RTOS_PRESENT
00034 extern osMutexId_t singleton_mutex_id;
00035 #endif
00036 
00037 /** Lock the singleton mutex
00038  *
00039  * This function is typically used to provide
00040  * exclusive access when initializing a
00041  * global object.
00042  */
00043 inline static void singleton_lock(void)
00044 {
00045 #ifdef MBED_CONF_RTOS_PRESENT
00046     if (!singleton_mutex_id) {
00047         // RTOS has not booted yet so no mutex is needed
00048         return;
00049     }
00050     osMutexAcquire(singleton_mutex_id, osWaitForever);
00051 #endif
00052 }
00053 
00054 /** Unlock the singleton mutex
00055  *
00056  * This function is typically used to provide
00057  * exclusive access when initializing a
00058  * global object.
00059  */
00060 inline static void singleton_unlock(void)
00061 {
00062 #ifdef MBED_CONF_RTOS_PRESENT
00063     if (!singleton_mutex_id) {
00064         // RTOS has not booted yet so no mutex is needed
00065         return;
00066     }
00067     osMutexRelease(singleton_mutex_id);
00068 #endif
00069 }
00070 
00071 /** Utility class for creating an using a singleton
00072  *
00073  * @note Synchronization level: Thread safe
00074  *
00075  * @note: This class must only be used in a static context -
00076  * this class must never be allocated or created on the
00077  * stack.
00078  *
00079  * @note: This class is lazily initialized on first use.
00080  * This class is a POD type so if it is not used it will
00081  * be garbage collected.
00082  */
00083 template <class T>
00084 struct SingletonPtr {
00085 
00086     /** Get a pointer to the underlying singleton
00087      *
00088      * @returns
00089      *   A pointer to the singleton
00090      */
00091     T *get()
00092     {
00093         if (NULL == _ptr) {
00094             singleton_lock();
00095             if (NULL == _ptr) {
00096                 _ptr = new (_data) T();
00097             }
00098             singleton_unlock();
00099         }
00100         // _ptr was not zero initialized or was
00101         // corrupted if this assert is hit
00102         MBED_ASSERT(_ptr == (T *)&_data);
00103         return _ptr;
00104     }
00105 
00106     /** Get a pointer to the underlying singleton
00107      *
00108      * @returns
00109      *   A pointer to the singleton
00110      */
00111     T *operator->()
00112     {
00113         return get();
00114     }
00115 
00116     /** Get a reference to the underlying singleton
00117      *
00118      * @returns
00119      *   A reference to the singleton
00120      */
00121     T &operator*()
00122     {
00123         return *get();
00124     }
00125 
00126     // This is zero initialized when in global scope
00127     T *_ptr;
00128     // Force data to be 4 byte aligned
00129     uint32_t _data[(sizeof(T) + sizeof(uint32_t) - 1) / sizeof(uint32_t)];
00130 };
00131 
00132 #endif
00133 /**@}*/
00134 
00135 /**@}*/