ACE_Singleton,ACE_Object_Manager

ACE_Singleton singleton模式的一个很好实力,增加了在线程中的安全行,使用ACE_Object_Manage管理势力,不用对其进行资源释放

 

#pragma once
#include <ace/Singleton.h>
class CTest
{
 friend class ACE_Singleton<CTest, ACE_Null_Mutex>;

public:
 CTest(void);
public:
 ~CTest(void);

 //ACE_ALLOC_HOOK_DECLARE;
};

typedef ACE_Singleton<CTest, ACE_Null_Mutex> CSingletonTest;

 

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////

instance源代码,使用了double check 模式

 

template <class TYPE, class ACE_LOCK> TYPE *
ACE_Singleton<TYPE, ACE_LOCK>::instance (void)
{
  ACE_TRACE ("ACE_Singleton<TYPE, ACE_LOCK>::instance");

  ACE_Singleton<TYPE, ACE_LOCK> *&singleton =
    ACE_Singleton<TYPE, ACE_LOCK>::instance_i ();

  // Perform the Double-Check pattern...
  if (singleton == 0)
    {
      if (ACE_Object_Manager::starting_up () ||
          ACE_Object_Manager::shutting_down ())
        {
          // The program is still starting up, and therefore assumed
          // to be single threaded.  There's no need to double-check.
          // Or, the ACE_Object_Manager instance has been destroyed,
          // so the preallocated lock is not available.  Either way,
          // don't register for destruction with the
          // ACE_Object_Manager:  we'll have to leak this instance.

          ACE_NEW_RETURN (singleton, (ACE_Singleton<TYPE, ACE_LOCK>), 0);
        }
      else
        {
#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
          // Obtain a lock from the ACE_Object_Manager.  The pointer
          // is static, so we only obtain one per ACE_Singleton
          // instantiation.
          static ACE_LOCK *lock = 0;
          if (ACE_Object_Manager::get_singleton_lock (lock) != 0)
            // Failed to acquire the lock!
            return 0;

          ACE_GUARD_RETURN (ACE_LOCK, ace_mon, *lock, 0);

          if (singleton == 0)
            {
#endif /* ACE_MT_SAFE */
              ACE_NEW_RETURN (singleton, (ACE_Singleton<TYPE, ACE_LOCK>), 0);

              // Register for destruction with ACE_Object_Manager.

              //使用ACE_Object_Manage管理singleton
              ACE_Object_Manager::at_exit (singleton);
#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
            }
#endif /* ACE_MT_SAFE */
        }
    }

  return &singleton->instance_;
}

 

 

 

ace还分装了其他的singleton模式,ACE_Singleton,ACE_Unmanaged_Singleton,ACE_TSS_Singleton,ACE_Unmanaged_TSS_Singleton,ACE_DLL_Singleton_T,ACE_DLL_Singleton_Adapter_T

 

 

 

ACE_Object_Manager对象管理类

 

ACE所有对象管理使用ACE_Object_Manager管理类,可以自动释放资源

 

ACE_Object_Manager的使用:

 

//初始化

 ACE_Object_Manager::init();

 

/**
   * Register an ACE_Cleanup object for cleanup at process
   * termination.  The object is deleted via the
   * <ace_cleanup_destroyer>.  If you need more flexiblity, see the
   * <other at_exit> method below.  For OS's that do not have
   * processes, cleanup takes place at the end of <main>.  Returns 0
   * on success.  On failure, returns -1 and sets errno to: EAGAIN if
   * shutting down, ENOMEM if insufficient virtual memory, or EEXIST
   * if the object (or array) had already been registered.
   */

 ACE_Object_Manager::at_exit (singleton);

 

//fini()

 

<think>我们被要求实现一个名为 DECLARE_SINGLETON 的宏,用于简化单例类的声明。 根据之前的讨论,我们知道单例模式的关键点: 1. 私有化构造函数和析构函数。 2. 删除拷贝构造函数和赋值运算符。 3. 提供一个静态的实例访问方法(例如Instance)。 4. 使用静态局部变量确保线程安全(C++11及以上)。 目标:定义一个宏 DECLARE_SINGLETON(ClassName),它可以在类声明内部使用,自动生成单例所需的声明部分。 注意:宏的定义需要考虑到类名,因此使用参数 ClassName。 通常,我们会在类的声明中使用这个宏,然后在类外定义静态成员函数(Instance函数)以及静态局部变量。 但是,由于静态局部变量只能在函数内部定义,所以宏只能处理声明部分,定义部分需要另外处理。 然而,有时为了简化,我们也可以将定义部分也通过宏来实现(例如在头文件中定义),但这可能会导致多个定义的问题(如果头文件被多个cpp包含),所以需要配合inline或者只在cpp中定义一次。 但是,根据要求,我们需要在工程中方便地加入单例,我们可以提供两个宏: DECLARE_SINGLETON(ClassName) // 用于类声明内部 DEFINE_SINGLETON(ClassName) // 用于类外部(一般在cpp文件中)定义Instance函数 但是问题只要求 DECLARE_SINGLETON,所以我们先按照只声明不定义的方式设计。 然而,观察之前的代码,我们发现Instance函数是静态成员函数,需要在类外定义。如果我们只在类内声明,那么用户还需要在类外定义这个函数。 为了简化,我们可以将Instance函数定义为内联函数,这样在类内定义就可以避免链接错误。但是,静态局部变量在函数内部,每个翻译单元都有自己的一份?不会,因为它是静态的,但是C++要求全局变量只能有一个定义,而内联函数可以在多个翻译单元中定义,所以C++17之后引入内联变量,而在此之前,我们可以使用模板技巧或者直接使用内联函数(C++17支持内联变量,静态局部变量在函数内,它本身是内部链接?不,静态局部变量在函数内部,它的初始化是线程安全的,并且只有一个实例,因为它是静态存储期的变量,但它的定义在函数内部,所以不会出现多个定义的问题,因为它是函数的局部静态变量。但是,如果函数是内联的,那么每个包含该头文件的翻译单元都会有一个相同的函数定义,但是静态局部变量仍然是唯一的,因为它是定义在函数内部的,并且是静态的,所以整个程序在执行时只有一个实例(由运行时保证)。因此,我们可以将Instance函数定义为内联的,放在类内部。 所以,我们可以这样设计: 在宏 DECLARE_SINGLETON(ClassName) 中,我们声明构造函数和析构函数为私有,删除拷贝构造和赋值运算符,并定义一个公有的静态成员函数Instance,它返回类对象的引用,并在函数内部定义一个静态局部变量实例。 但是,由于宏是在类内部使用的,我们可以将整个单例的声明和定义(Instance函数)都放在宏中,这样用户只需要在类内部使用这个宏,就完成了所有工作。 但是注意:在类内部定义函数体,则该函数是内联的。这样我们就可以在头文件中使用这个宏而不会导致链接错误。 因此,我们设计如下: ```cpp #define DECLARE_SINGLETON(ClassName) \ public: \ static ClassName& Instance() { \ static ClassName instance; \ return instance; \ } \ ClassName(const ClassName&) = delete; \ ClassName& operator=(const ClassName&) = delete; \ private: \ ClassName() = default; \ ~ClassName() = default; ``` 注意: 1. 我们将构造函数和析构函数设为私有,并且使用default实现(因为不一定有复杂的初始化,用户可以在类外定义构造函数,但这里我们提供默认,如果用户需要自定义构造函数,则需要在类外定义构造函数,但这样会导致宏无法满足,所以我们需要考虑灵活性)。 2. 但是,如果用户需要自定义构造函数,那么他们应该在类中自己声明构造函数,这样就会和宏中的构造函数声明冲突。所以我们需要改进。 另一种做法:宏只提供必要的声明,但允许用户自己定义构造函数和析构函数(但必须是私有的)。这样我们可以不提供构造函数和析构函数的声明,由用户自己提供。但是这样用户必须记得将构造函数和析构函数设为私有,并且删除拷贝构造和赋值运算符,这样就失去了宏的意义。 因此,我们可以在宏中不定义构造函数和析构函数,而是要求用户将构造函数和析构函数声明为私有(或者受保护的),并在宏中删除拷贝构造和赋值运算符,同时提供Instance函数。 但是这样宏就不完整了。 为了平衡,我们可以这样:在宏中声明构造函数和析构函数为私有,但不对其进行定义(即使用默认的声明),这样用户可以在类外定义它们。但是,如果用户没有在类外定义,那么就会链接错误(因为构造函数和析构函数没有定义)。所以我们需要在宏的注释中说明用户需要自行定义构造函数和析构函数(如果需要的话),或者使用默认的(如果不需要的话)。 但是,由于我们使用`= default`,如果用户不在类外定义,那么编译器会在需要的时候生成默认的构造函数和析构函数,并且由于是私有的,所以只有Instance函数能调用(因为Instance是成员函数,可以访问私有成员)。但是,在类内使用`=default`且是私有的,那么编译器会隐式生成,不需要在类外定义。所以没有问题。 但是,如果用户需要自定义构造函数,他们可以在类中自己声明,然后定义在类外。但是这样就会覆盖宏中的默认构造函数声明?因为宏中已经声明了一个私有的默认构造函数。所以用户不能在类中再次声明构造函数,否则会重复声明。 因此,我们需要一个更灵活的方式。 常见的做法是:将宏设计为在类声明中使用,并且要求用户将宏放在类的私有区域。然后宏会定义Instance函数(公有)以及删除拷贝构造和赋值运算符(公有或私有?通常删除应该公有,这样错误在编译时就能捕获)。同时,我们不在宏中声明构造函数和析构函数,而是要求用户自己声明(私有)。 例如(参考一些框架的做法): ```cpp // 假设这样使用: class MySingleton { DECLARE_SINGLETON(MySingleton) public: // 公有成员函数 private: // 如果需要,用户自己在这里声明构造函数和析构函数 }; ``` 那么宏可以这样写: ```cpp #define DECLARE_SINGLETON(ClassName) \ public: \ static ClassName& Instance() { \ static ClassName instance; \ return instance; \ } \ ClassName(const ClassName&) = delete; \ ClassName& operator=(const ClassName&) = delete; // 注意:这里没有提供构造函数和析构函数,需要用户在类中私有区域声明 ``` 但是用户必须记得将构造函数和析构函数设为私有,否则外部可以创建实例。 为了强制私有,我们可以将宏放在私有区域,但是这样Instance函数就会被放在私有区域,这是不允许的。 所以,我们只能采用第一种方案:在宏中声明构造函数和析构函数为私有,并默认使用default。这样用户如果不需要自定义,就可以直接用。如果需要自定义,可以在类外定义,但是注意不能在类中再次声明(因为会重复),所以用户需要避免在类中声明构造函数和析构函数。 因此,我们回到第一种方案,并认为这是最简单的方式,适用于大多数不需要自定义构造函数的场景。如果需要自定义,用户可以选择不使用宏,或者修改宏。 权衡后,我们给出第一种方案,并在注释中说明:如果用户需要自定义构造函数,则需要在类外定义,并且不要再次在类中声明(因为宏已经声明了私有的默认构造函数,如果用户需要自定义,可以在类外定义构造函数,这样会覆盖默认的,但是注意,用户必须提供定义,否则链接错误)。 但是,由于我们在宏中已经声明了构造函数,用户不能在类中再次声明(只能定义一次)。所以用户可以在类外定义自定义的构造函数: ```cpp class MySingleton { DECLARE_SINGLETON(MySingleton) // 其他成员函数... }; // 在cpp文件中定义构造函数(如果需要) MySingleton::MySingleton() { // 自定义构造 } ``` 由于宏中默认使用`=default`,如果用户不在类外定义,则使用编译器生成的默认构造函数。如果用户定义了,那么就会覆盖默认的。 但是,宏中声明构造函数是私有且默认的,而用户可以在类外定义自己的构造函数(必须是私有的,因为声明是私有的)。这样是可以的。 因此,我们采用如下宏定义: ```cpp #define DECLARE_SINGLETON(ClassName) \ public: \ static ClassName& Instance() { \ static ClassName instance; \ return instance; \ } \ ClassName(const ClassName&) = delete; \ ClassName& operator=(const ClassName&) = delete; \ private: \ ClassName() = default; \ ~ClassName() = default; ``` 注意:析构函数同理。 但是,这样写可能会因为宏的换行导致问题(特别是类中还有其他成员时),所以我们需要在宏的最后一行加上一个注释说明,或者确保用户在使用宏后不需要分号(因为宏后面通常需要分号,但这里我们不需要,因为宏的最后是private声明,而类中声明不需要分号,但整个类定义最后需要分号)。所以用户在使用时,在宏后面不需要加分号,否则会多一个分号,但语法上允许。 另外,如果用户希望构造函数有参数,那么这种方法就不适用了,因为Instance函数调用的是默认构造函数。所以这种宏只适用于默认构造函数的情况。 因此,我们明确:这个宏只适用于无参构造的单例。如果需要有参构造,那么单例的初始化需要其他机制(例如Init函数),这超出了本宏的范围。 最后,我们给出完整的宏定义,并提供一个使用示例。 注意:由于Instance函数在类内定义,它是内联的,所以可以放在头文件中。静态局部变量在整个程序中只有一个实例。 示例代码: ```cpp // 宏定义 #define DECLARE_SINGLETON(ClassName) \ public: \ static ClassName& Instance() { \ static ClassName instance; \ return instance; \ } \ ClassName(const ClassName&) = delete; \ ClassName& operator=(const ClassName&) = delete; \ private: \ ClassName() = default; \ ~ClassName() = default; // 使用宏的类 class MySingleton { DECLARE_SINGLETON(MySingleton) public: void DoSomething() { // 业务逻辑 } // 注意:如果需要自定义构造函数,可以在类外定义(但必须是无参的,因为Instance中调用的是默认构造) }; // 如果需要自定义构造函数,在cpp文件中定义: // MySingleton::MySingleton() { // // 自定义初始化 // } // 使用: // MySingleton::Instance().DoSomething(); ``` 但是,如果用户需要传递参数构造,那么这种方法不适用。因此,我们在宏的注释中说明仅适用于默认构造。 所以,回答如下: </think>在C++中,可以通过宏`DECLARE_SINGLETON`简化单例类的声明,自动生成必要的成员声明和删除操作。以下是完整的实现方案: ```cpp #define DECLARE_SINGLETON(ClassName) \ public: \ static ClassName& Instance() { \ static ClassName instance; \ return instance; \ } \ ClassName(const ClassName&) = delete; \ ClassName& operator=(const ClassName&) = delete; \ private: \ ClassName() = default; \ ~ClassName() = default; ``` **使用示例**: ```cpp class Logger { DECLARE_SINGLETON(Logger) // 关键宏调用 public: void Log(const std::string& message) { std::cout << "[LOG] " << message << std::endl; } // 其他成员函数... }; // 全局调用示例: Logger::Instance().Log("Service started"); ``` **核心机制**: 1. **自动生成关键成员**: - 生成线程安全的`Instance()`静态方法(C++11标准保证) - 自动删除拷贝构造和赋值运算符(`= delete`) - 私有化默认构造和析构函数(`= default`) 2. **线程安全**: ```cpp static ClassName instance; // C++11静态局部变量保证线程安全 ``` 3. **使用规范**: - 在类声明**公有区域**调用宏 - 禁止手动声明构造函数/拷贝操作 - 支持C++11及以上标准 **注意事项**: 1. 适用于无参构造的单例(如需参数需手动扩展) 2. 头文件需包含`<mutex>`(仅C++11前需要) 3. 宏调用后无需分号(宏定义已包含完整语句)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值