mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			Create singleton class and update code to use it
Create the wrapper class SingletonPtr. This provides a safe way to declare and use singletons. This class allows both the lazy initialization of a singleton, and allows the singleton to be garbage collected by the linker if it is never referenced. This patch also updates the HAL to use SingletonPtr when declaring singleton mutexes.pull/2158/head
							parent
							
								
									d4627176da
								
							
						
					
					
						commit
						348b32c3c6
					
				| 
						 | 
				
			
			@ -21,6 +21,7 @@
 | 
			
		|||
#if DEVICE_ANALOGIN
 | 
			
		||||
 | 
			
		||||
#include "analogin_api.h"
 | 
			
		||||
#include "SingletonPtr.h"
 | 
			
		||||
 | 
			
		||||
namespace mbed {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -110,15 +111,15 @@ public:
 | 
			
		|||
protected:
 | 
			
		||||
 | 
			
		||||
    virtual void lock() {
 | 
			
		||||
        _mutex.lock();
 | 
			
		||||
        _mutex->lock();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual void unlock() {
 | 
			
		||||
        _mutex.unlock();
 | 
			
		||||
        _mutex->unlock();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    analogin_t _adc;
 | 
			
		||||
    static PlatformMutex _mutex;
 | 
			
		||||
    static SingletonPtr<PlatformMutex> _mutex;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace mbed
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -41,6 +41,7 @@ typedef long off_t;
 | 
			
		|||
#endif
 | 
			
		||||
 | 
			
		||||
#include "platform.h"
 | 
			
		||||
#include "SingletonPtr.h"
 | 
			
		||||
 | 
			
		||||
namespace mbed {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -65,7 +66,7 @@ public:
 | 
			
		|||
    /* disallow copy constructor and assignment operators */
 | 
			
		||||
private:
 | 
			
		||||
    static FileBase *_head;
 | 
			
		||||
    static PlatformMutex _mutex;
 | 
			
		||||
    static SingletonPtr<PlatformMutex> _mutex;
 | 
			
		||||
 | 
			
		||||
    FileBase   *_next;
 | 
			
		||||
    const char * const _name;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,6 +21,7 @@
 | 
			
		|||
#if DEVICE_I2C
 | 
			
		||||
 | 
			
		||||
#include "i2c_api.h"
 | 
			
		||||
#include "SingletonPtr.h"
 | 
			
		||||
 | 
			
		||||
#if DEVICE_I2C_ASYNCH
 | 
			
		||||
#include "CThunk.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -181,7 +182,7 @@ protected:
 | 
			
		|||
    i2c_t _i2c;
 | 
			
		||||
    static I2C  *_owner;
 | 
			
		||||
    int         _hz;
 | 
			
		||||
    static PlatformMutex _mutex;
 | 
			
		||||
    static SingletonPtr<PlatformMutex> _mutex;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace mbed
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,103 @@
 | 
			
		|||
/* mbed Microcontroller Library
 | 
			
		||||
 * Copyright (c) 2006-2013 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef SINGLETONPTR_H
 | 
			
		||||
#define SINGLETONPTR_H
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <new>
 | 
			
		||||
#include "mbed_assert.h"
 | 
			
		||||
#ifdef MBED_CONF_RTOS_PRESENT
 | 
			
		||||
#include "cmsis_os.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef MBED_CONF_RTOS_PRESENT
 | 
			
		||||
extern osMutexId singleton_mutex_id;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/** Lock the singleton mutex
 | 
			
		||||
 *
 | 
			
		||||
 * This function is typically used to provide
 | 
			
		||||
 * exclusive access when initializing a
 | 
			
		||||
 * global object.
 | 
			
		||||
 */
 | 
			
		||||
inline static void singleton_lock(void)
 | 
			
		||||
{
 | 
			
		||||
#ifdef MBED_CONF_RTOS_PRESENT
 | 
			
		||||
    osMutexWait(singleton_mutex_id, osWaitForever);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Unlock the singleton mutex
 | 
			
		||||
 *
 | 
			
		||||
 * This function is typically used to provide
 | 
			
		||||
 * exclusive access when initializing a
 | 
			
		||||
 * global object.
 | 
			
		||||
 */
 | 
			
		||||
inline static void singleton_unlock(void)
 | 
			
		||||
{
 | 
			
		||||
#ifdef MBED_CONF_RTOS_PRESENT
 | 
			
		||||
    osMutexRelease (singleton_mutex_id);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Utility class for creating an using a singleton
 | 
			
		||||
 *
 | 
			
		||||
 * @Note Synchronization level: Thread safe
 | 
			
		||||
 *
 | 
			
		||||
 * @Note: This class must only be used in a static context -
 | 
			
		||||
 * this class must never be allocated or created on the
 | 
			
		||||
 * stack.
 | 
			
		||||
 *
 | 
			
		||||
 * @Note: This class is lazily initialized on first use.
 | 
			
		||||
 * This class is a POD type so if it is not used it will
 | 
			
		||||
 * be garbage collected.
 | 
			
		||||
 */
 | 
			
		||||
template <class T>
 | 
			
		||||
struct SingletonPtr {
 | 
			
		||||
 | 
			
		||||
    /** Get a pointer to the underlying singleton
 | 
			
		||||
     *
 | 
			
		||||
     * @returns
 | 
			
		||||
     *   A pointer to the singleton
 | 
			
		||||
     */
 | 
			
		||||
    T* get() {
 | 
			
		||||
        if (NULL == _ptr) {
 | 
			
		||||
            singleton_lock();
 | 
			
		||||
            _ptr = new (_data) T;
 | 
			
		||||
            singleton_unlock();
 | 
			
		||||
        }
 | 
			
		||||
        // _ptr was not zero initialized or was
 | 
			
		||||
        // corrupted if this assert is hit
 | 
			
		||||
        MBED_ASSERT(_ptr == (T *)&_data);
 | 
			
		||||
        return _ptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Get a pointer to the underlying singleton
 | 
			
		||||
     *
 | 
			
		||||
     * @returns
 | 
			
		||||
     *   A pointer to the singleton
 | 
			
		||||
     */
 | 
			
		||||
    T* operator->() {
 | 
			
		||||
        return get();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // This is zero initialized when in global scope
 | 
			
		||||
    T *_ptr;
 | 
			
		||||
    // Force data to be 4 byte aligned
 | 
			
		||||
    uint32_t _data[(sizeof(T) + sizeof(uint32_t) - 1) / sizeof(uint32_t)];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -22,7 +22,7 @@
 | 
			
		|||
 | 
			
		||||
namespace mbed {
 | 
			
		||||
 | 
			
		||||
PlatformMutex AnalogIn::_mutex;
 | 
			
		||||
SingletonPtr<PlatformMutex> AnalogIn::_mutex;
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,12 +18,12 @@
 | 
			
		|||
namespace mbed {
 | 
			
		||||
 | 
			
		||||
FileBase *FileBase::_head = NULL;
 | 
			
		||||
PlatformMutex FileBase::_mutex;
 | 
			
		||||
SingletonPtr<PlatformMutex> FileBase::_mutex;
 | 
			
		||||
 | 
			
		||||
FileBase::FileBase(const char *name, PathType t) : _next(NULL),
 | 
			
		||||
                                                   _name(name),
 | 
			
		||||
                                                   _path_type(t) {
 | 
			
		||||
    _mutex.lock();
 | 
			
		||||
    _mutex->lock();
 | 
			
		||||
    if (name != NULL) {
 | 
			
		||||
        // put this object at head of the list
 | 
			
		||||
        _next = _head;
 | 
			
		||||
| 
						 | 
				
			
			@ -31,11 +31,11 @@ FileBase::FileBase(const char *name, PathType t) : _next(NULL),
 | 
			
		|||
    } else {
 | 
			
		||||
        _next = NULL;
 | 
			
		||||
    }
 | 
			
		||||
    _mutex.unlock();
 | 
			
		||||
    _mutex->unlock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FileBase::~FileBase() {
 | 
			
		||||
    _mutex.lock();
 | 
			
		||||
    _mutex->lock();
 | 
			
		||||
    if (_name != NULL) {
 | 
			
		||||
        // remove this object from the list
 | 
			
		||||
        if (_head == this) { // first in the list, so just drop me
 | 
			
		||||
| 
						 | 
				
			
			@ -48,38 +48,38 @@ FileBase::~FileBase() {
 | 
			
		|||
            p->_next = _next;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    _mutex.unlock();
 | 
			
		||||
    _mutex->unlock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FileBase *FileBase::lookup(const char *name, unsigned int len) {
 | 
			
		||||
    _mutex.lock();
 | 
			
		||||
    _mutex->lock();
 | 
			
		||||
    FileBase *p = _head;
 | 
			
		||||
    while (p != NULL) {
 | 
			
		||||
        /* Check that p->_name matches name and is the correct length */
 | 
			
		||||
        if (p->_name != NULL && std::strncmp(p->_name, name, len) == 0 && std::strlen(p->_name) == len) {
 | 
			
		||||
            _mutex.unlock();
 | 
			
		||||
            _mutex->unlock();
 | 
			
		||||
            return p;
 | 
			
		||||
        }
 | 
			
		||||
        p = p->_next;
 | 
			
		||||
    }
 | 
			
		||||
    _mutex.unlock();
 | 
			
		||||
    _mutex->unlock();
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FileBase *FileBase::get(int n) {
 | 
			
		||||
    _mutex.lock();
 | 
			
		||||
    _mutex->lock();
 | 
			
		||||
    FileBase *p = _head;
 | 
			
		||||
    int m = 0;
 | 
			
		||||
    while (p != NULL) {
 | 
			
		||||
        if (m == n) {
 | 
			
		||||
            _mutex.unlock();
 | 
			
		||||
            _mutex->unlock();
 | 
			
		||||
            return p;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        m++;
 | 
			
		||||
        p = p->_next;
 | 
			
		||||
    }
 | 
			
		||||
    _mutex.unlock();
 | 
			
		||||
    _mutex->unlock();
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,7 +20,7 @@
 | 
			
		|||
namespace mbed {
 | 
			
		||||
 | 
			
		||||
I2C *I2C::_owner = NULL;
 | 
			
		||||
PlatformMutex I2C::_mutex;
 | 
			
		||||
SingletonPtr<PlatformMutex> I2C::_mutex;
 | 
			
		||||
 | 
			
		||||
I2C::I2C(PinName sda, PinName scl) :
 | 
			
		||||
#if DEVICE_I2C_ASYNCH
 | 
			
		||||
| 
						 | 
				
			
			@ -113,11 +113,11 @@ void I2C::stop(void) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void I2C::lock() {
 | 
			
		||||
    _mutex.lock();
 | 
			
		||||
    _mutex->lock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void I2C::unlock() {
 | 
			
		||||
    _mutex.unlock();
 | 
			
		||||
    _mutex->unlock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if DEVICE_I2C_ASYNCH
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,6 +21,7 @@
 | 
			
		|||
#include "toolchain.h"
 | 
			
		||||
#include "semihost_api.h"
 | 
			
		||||
#include "mbed_interface.h"
 | 
			
		||||
#include "SingletonPtr.h"
 | 
			
		||||
#if DEVICE_STDIO_MESSAGES
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -72,17 +73,17 @@ extern const char __stderr_name[] = "/stderr";
 | 
			
		|||
 * (or rather index+3, as filehandles 0-2 are stdin/out/err).
 | 
			
		||||
 */
 | 
			
		||||
static FileHandle *filehandles[OPEN_MAX];
 | 
			
		||||
static PlatformMutex filehandle_mutex;
 | 
			
		||||
static SingletonPtr<PlatformMutex> filehandle_mutex;
 | 
			
		||||
 | 
			
		||||
FileHandle::~FileHandle() {
 | 
			
		||||
    filehandle_mutex.lock();
 | 
			
		||||
    filehandle_mutex->lock();
 | 
			
		||||
    /* Remove all open filehandles for this */
 | 
			
		||||
    for (unsigned int fh_i = 0; fh_i < sizeof(filehandles)/sizeof(*filehandles); fh_i++) {
 | 
			
		||||
        if (filehandles[fh_i] == this) {
 | 
			
		||||
            filehandles[fh_i] = NULL;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    filehandle_mutex.unlock();
 | 
			
		||||
    filehandle_mutex->unlock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if DEVICE_SERIAL
 | 
			
		||||
| 
						 | 
				
			
			@ -162,17 +163,17 @@ extern "C" FILEHANDLE PREFIX(_open)(const char* name, int openmode) {
 | 
			
		|||
    #endif
 | 
			
		||||
 | 
			
		||||
    // find the first empty slot in filehandles
 | 
			
		||||
    filehandle_mutex.lock();
 | 
			
		||||
    filehandle_mutex->lock();
 | 
			
		||||
    unsigned int fh_i;
 | 
			
		||||
    for (fh_i = 0; fh_i < sizeof(filehandles)/sizeof(*filehandles); fh_i++) {
 | 
			
		||||
        if (filehandles[fh_i] == NULL) break;
 | 
			
		||||
    }
 | 
			
		||||
    if (fh_i >= sizeof(filehandles)/sizeof(*filehandles)) {
 | 
			
		||||
        filehandle_mutex.unlock();
 | 
			
		||||
        filehandle_mutex->unlock();
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
    filehandles[fh_i] = (FileHandle*)FILE_HANDLE_RESERVED;
 | 
			
		||||
    filehandle_mutex.unlock();
 | 
			
		||||
    filehandle_mutex->unlock();
 | 
			
		||||
 | 
			
		||||
    FileHandle *res;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -225,6 +225,10 @@ uint32_t       os_tmr = 0;
 | 
			
		|||
uint32_t const *m_tmr = NULL;
 | 
			
		||||
uint16_t const mp_tmr_size = 0;
 | 
			
		||||
 | 
			
		||||
/* singleton mutex */
 | 
			
		||||
osMutexId singleton_mutex_id;
 | 
			
		||||
osMutexDef(singleton_mutex);
 | 
			
		||||
 | 
			
		||||
#if defined (__CC_ARM) && !defined (__MICROLIB)
 | 
			
		||||
 /* A memory space for arm standard library. */
 | 
			
		||||
 static uint32_t std_libspace[OS_TASK_CNT][96/4];
 | 
			
		||||
| 
						 | 
				
			
			@ -434,6 +438,7 @@ void $Sub$$__cpp_initialize__aeabi_(void)
 | 
			
		|||
 | 
			
		||||
void pre_main()  
 | 
			
		||||
{  
 | 
			
		||||
  singleton_mutex_id = osMutexCreate(osMutex(singleton_mutex));
 | 
			
		||||
  $Super$$__cpp_initialize__aeabi_();  
 | 
			
		||||
  main();  
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -447,6 +452,7 @@ int main(void);
 | 
			
		|||
 | 
			
		||||
void pre_main (void)
 | 
			
		||||
{
 | 
			
		||||
    singleton_mutex_id = osMutexCreate(osMutex(singleton_mutex));
 | 
			
		||||
    __rt_lib_init((unsigned)armcc_heap_base, (unsigned)armcc_heap_top);
 | 
			
		||||
    main();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -484,6 +490,7 @@ extern void __libc_init_array (void);
 | 
			
		|||
extern int main(int argc, char **argv);
 | 
			
		||||
 | 
			
		||||
void pre_main(void) {
 | 
			
		||||
    singleton_mutex_id = osMutexCreate(osMutex(singleton_mutex));
 | 
			
		||||
    atexit(__libc_fini_array);
 | 
			
		||||
    __libc_init_array();
 | 
			
		||||
    main(0, NULL);
 | 
			
		||||
| 
						 | 
				
			
			@ -516,6 +523,7 @@ extern int main(void);
 | 
			
		|||
static uint8_t low_level_init_needed;
 | 
			
		||||
 | 
			
		||||
void pre_main(void) {
 | 
			
		||||
    singleton_mutex_id = osMutexCreate(osMutex(singleton_mutex));
 | 
			
		||||
    if (low_level_init_needed) {
 | 
			
		||||
        __iar_dynamic_initialization();
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -187,6 +187,10 @@ uint32_t       os_tmr = 0U;
 | 
			
		|||
uint32_t const *m_tmr = NULL;
 | 
			
		||||
uint16_t const mp_tmr_size = 0U;
 | 
			
		||||
 | 
			
		||||
/* singleton mutex */
 | 
			
		||||
osMutexId singleton_mutex_id;
 | 
			
		||||
osMutexDef(singleton_mutex);
 | 
			
		||||
 | 
			
		||||
#if defined (__CC_ARM) && !defined (__MICROLIB)
 | 
			
		||||
 /* A memory space for arm standard library. */
 | 
			
		||||
 static uint32_t std_libspace[OS_TASK_CNT][96/4];
 | 
			
		||||
| 
						 | 
				
			
			@ -585,6 +589,7 @@ void $Sub$$__cpp_initialize__aeabi_(void)
 | 
			
		|||
 | 
			
		||||
void pre_main()
 | 
			
		||||
{
 | 
			
		||||
  singleton_mutex_id = osMutexCreate(osMutex(singleton_mutex));
 | 
			
		||||
  $Super$$__cpp_initialize__aeabi_();
 | 
			
		||||
  main();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -598,6 +603,7 @@ int main(void);
 | 
			
		|||
 | 
			
		||||
void pre_main (void)
 | 
			
		||||
{
 | 
			
		||||
    singleton_mutex_id = osMutexCreate(osMutex(singleton_mutex));
 | 
			
		||||
    __rt_lib_init((unsigned)armcc_heap_base, (unsigned)armcc_heap_top);
 | 
			
		||||
    main();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -664,6 +670,7 @@ extern void __libc_init_array (void);
 | 
			
		|||
extern int main(int argc, char **argv);
 | 
			
		||||
 | 
			
		||||
void pre_main(void) {
 | 
			
		||||
    singleton_mutex_id = osMutexCreate(osMutex(singleton_mutex));
 | 
			
		||||
    malloc_mutex_id = osMutexCreate(osMutex(malloc_mutex));
 | 
			
		||||
    env_mutex_id = osMutexCreate(osMutex(env_mutex));
 | 
			
		||||
    atexit(__libc_fini_array);
 | 
			
		||||
| 
						 | 
				
			
			@ -725,6 +732,7 @@ extern void exit(int arg);
 | 
			
		|||
static uint8_t low_level_init_needed;
 | 
			
		||||
 | 
			
		||||
void pre_main(void) {
 | 
			
		||||
    singleton_mutex_id = osMutexCreate(osMutex(singleton_mutex));
 | 
			
		||||
    if (low_level_init_needed) {
 | 
			
		||||
        __iar_dynamic_initialization();
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue