This fork captures the mbed lib v125 for ease of integration into older projects.

Fork of mbed-dev by mbed official

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SingletonPtr.h Source File

SingletonPtr.h

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