/** \file
 *
 *  Contains the LcmInstance class definition.
 *	Implements single shared LCM instance (singleton).

 * This implementation may not be thread safe, as some C++ compilers (g++, e.g.)
 * create internal data structures that can't be protected by locks.
 * https:*sourcemaking.com/design_patterns/to_kill_a_singleton

 * If thread safety becomes an issue, the template solution in the article above
 * may help.
 * There are other drawbacks, e.g. it isn't configurable, and
 * it can't be changed at run time.
 * To implement that, it would be necessary implement mechanism
 * for preventing dangling references held by users, and create other issues
 * related to destroying instances
 * This implementation has the advantage that object creation/destruction is handled
 * implicitly, and doesn't create an instance unless it is used.

 *
 *  Copyright (c) 2007,2008,2009 MBARI
 *  MBARI Proprietary Information.  All Rights Reserved
 *
 */

#ifndef LCMINSTANCE_H_
#define LCMINSTANCE_H_

#include <lcm/lcm-cpp.hpp>
#include "utils/Mutex.h"

class LcmInstance
{

    friend class LcmInstance_Test;
    friend class Supervisor;

public:
    static lcm::LCM *GetInstance();
    static const char *GetURL();
    static bool IsValid();

protected:
    virtual ~LcmInstance();

private:
    // Singleton, so no instantiation, no copies
    LcmInstance();
    LcmInstance( const LcmInstance& );
    LcmInstance& operator= ( const LcmInstance& );

    lcm::LCM *lcm_;

    static Mutex LCMInstanceMutex_;

    static const char *LcmUrl_;

    // Static LcmInstance_ was not being cleaned up on the stack,
    // so we've put it on the heap and Supervisor kills it with a call to Uninitialize()
    static LcmInstance* LcmInstance_;
    static void CreateInstance();
    static void Uninitialize();
};

#endif
