forked

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SingletonPtr.h Source File

SingletonPtr.h

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