Rtos API example

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     osMutexAcquire(singleton_mutex_id, osWaitForever);
00047 #endif
00048 }
00049 
00050 /** Unlock the singleton mutex
00051  *
00052  * This function is typically used to provide
00053  * exclusive access when initializing a
00054  * global object.
00055  */
00056 inline static void singleton_unlock(void)
00057 {
00058 #ifdef MBED_CONF_RTOS_PRESENT
00059     osMutexRelease (singleton_mutex_id);
00060 #endif
00061 }
00062 
00063 /** Utility class for creating an using a singleton
00064  *
00065  * @note Synchronization level: Thread safe
00066  *
00067  * @note: This class must only be used in a static context -
00068  * this class must never be allocated or created on the
00069  * stack.
00070  *
00071  * @note: This class is lazily initialized on first use.
00072  * This class is a POD type so if it is not used it will
00073  * be garbage collected.
00074  */
00075 template <class T>
00076 struct SingletonPtr {
00077 
00078     /** Get a pointer to the underlying singleton
00079      *
00080      * @returns
00081      *   A pointer to the singleton
00082      */
00083     T* get() {
00084         if (NULL == _ptr) {
00085             singleton_lock();
00086             if (NULL == _ptr) {
00087                 _ptr = new (_data) T();
00088             }
00089             singleton_unlock();
00090         }
00091         // _ptr was not zero initialized or was
00092         // corrupted if this assert is hit
00093         MBED_ASSERT(_ptr == (T *)&_data);
00094         return _ptr;
00095     }
00096 
00097     /** Get a pointer to the underlying singleton
00098      *
00099      * @returns
00100      *   A pointer to the singleton
00101      */
00102     T* operator->() {
00103         return get();
00104     }
00105 
00106     // This is zero initialized when in global scope
00107     T *_ptr;
00108     // Force data to be 4 byte aligned
00109     uint32_t _data[(sizeof(T) + sizeof(uint32_t) - 1) / sizeof(uint32_t)];
00110 };
00111 
00112 #endif
00113 /**@}*/
00114 
00115 /**@}*/