/*---------------------------------------------------------------------------* Project: NintendoWare File: ut_Signal.ih Copyright (C)2010 Nintendo Co., Ltd./HAL Laboratory, Inc. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. - Auto generated code - *---------------------------------------------------------------------------*/ //--------------------------------------------------------------------------- //! @brief シグナルを受け取るためのインターフェースです。(引数は 0 個です) //! //! @tparam TResult 返り値の型です。 //! @tparam TAllocator アロケータの型です。 //--------------------------------------------------------------------------- template< typename TResult, typename TAllocator = os::IAllocator > class Slot0 { public: typedef TResult ResultType; typedef TAllocator AllocatorType; //! @brief コンストラクタです。 explicit Slot0(AllocatorType* allocator) : m_Allocator(allocator) {} //! @brief 自らを破棄します。 void Destroy() { AllocatorType* allocator = this->GetAllocator(); if (allocator) { this->~Slot0(); allocator->Free(this); } } //! @brief 自らを破棄します。 void Destroy(AllocatorType* allocator) { NW_NULL_ASSERT(allocator); this->~Slot0(); allocator->Free(this); } //! @brief スロットにシグナルを送信します。 virtual ResultType Invoke() = 0; AllocatorType* GetAllocator() { return m_Allocator; } protected: //! デストラクタです。 virtual ~Slot0() {} private: AllocatorType* m_Allocator; }; //--------------------------------------------------------------------------- //! @brief シグナルを受け取るためのクラスです。(引数は 0 個です) //! //! @tparam TResult 返り値の型です。 //! @tparam TFunction 関数か関数オブジェクトの型です。 //! @tparam TAllocator アロケータの型です。 //--------------------------------------------------------------------------- template< typename TResult, typename TFunction, typename TAllocator = os::IAllocator > class FunctionSlot0 : public Slot0 { public: typedef TResult ResultType; typedef TFunction FunctionType; typedef TAllocator AllocatorType; //! コンストラクタです。 FunctionSlot0(AllocatorType* allocator, FunctionType function) : Slot0(allocator), m_Function(function) {} //! @brief スロットにシグナルを送信します。 virtual ResultType Invoke() { return m_Function(); } private: TFunction m_Function; }; //--------------------------------------------------------------------------- //! @brief スロットに合図を送るためのクラスです。(引数は 0 個です) //! //! @tparam TResult 返り値の型です。 //! @tparam TResultCombiner スロットの返り値をまとめて返してくれるコンバイナの型です。 //! @tparam TAllocator アロケータの型です。 //! @tparam TSlot スロットの型です。 //--------------------------------------------------------------------------- template< typename TResult, typename TResultCombiner = LastValueResult, typename TAllocator = os::IAllocator, typename TSlot = Slot0 > class Signal0 { NW_DISALLOW_COPY_AND_ASSIGN(Signal0); public: typedef Signal0 SelfType; typedef TSlot SlotType; typedef TResult ResultType; typedef ut::MoveArray SlotList; typedef TResultCombiner ResultCombinerType; typedef TAllocator AllocatorType; #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED //! @brief スロット実行用関数オブジェクトです。 struct Invoker { Invoker() {} ResultType operator()(SlotType* slot) const { return slot->Invoke(); } ; }; #endif //---------------------------------------- //! @name 作成/破棄 //@{ //! @brief 無効なシグナルを生成します。 //! //! @param[in] allocator アロケータです。 //! static SelfType* CreateInvalidateSignal(AllocatorType* allocator) { void* memory = allocator->Alloc(sizeof(SelfType)); if (memory) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED return new(memory) SelfType(NULL, 0, allocator); #else return new(memory) SelfType(allocator); #endif } else { return NULL; } } //! @brief 必要なメモリを事前に確保してシグナルを生成します。 //! //! @param[in] maxSlots スロットを追加できる最大数です。 //! @param[in] allocator アロケータです。 //! static SelfType* CreateFixedSizedSignal(size_t maxSlots, AllocatorType* allocator) { void* memory = allocator->Alloc(sizeof(SelfType)); if (memory) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED void* elements = allocator->Alloc(sizeof(SlotType*) * maxSlots); if (elements != NULL) { return new(memory) SelfType(elements, maxSlots, allocator); } else { allocator->Free(memory); return NULL; } #else NW_UNUSED_VARIABLE(maxSlots); return new(memory) SelfType(allocator); #endif } else { return NULL; } } //! @brief 必要になるごとにメモリを確保するシグナルを生成します。 static SelfType* CreateVariableSizeSignal(AllocatorType* allocator) { void* memory = allocator->Alloc(sizeof(SelfType)); if (memory) { return new(memory) SelfType(allocator); } else { return NULL; } } //! オブジェクトを破棄します。 void Destroy() { this->~Signal0(); this->m_Allocator->Free(this); } //@} //---------------------------------------- //! @name スロット //@{ //! @brief スロットと接続し、シグナルが送られるようにする。 //! //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! シグナルに接続できるスロット数は1つになります。 //! //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! Connect する前に必ず Disconnect するようにしてください。 //! Disconnect していない場合は、アサートで停止します。 //! //! @param[in] slot スロットです。 //! void Connect(SlotType* slot) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED bool pushed = this->m_Slots.push_back(slot); NW_ASSERT(pushed); #else NW_ASSERT(this->m_Slot == NULL); this->m_Slot = slot; #endif } //! @brief スロットを作成し、接続します。 //! //! 内部でメモリを確保します。 //! //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! シグナルに接続できるスロット数は1つになります。 //! //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! Connect する前に必ず Disconnect するようにしてください。 //! Disconnect していない場合は、アサートで停止します。 //! //! @tparam TFunction 関数ポインタまたは、関数オブジェクトの型です。 //! //! @param[in] function 関数ポインタまたは、関数オブジェクトです。 //! @param[in] allocator アロケータです。 //! //! @return 生成されたスロットです。 //! template SlotType* CreateAndConnect(TFunction function, AllocatorType* allocator) { typedef FunctionSlot0 FunctionSlotType; FunctionSlotType* slot = CreateSlot(allocator, function); this->Connect(slot); return slot; } //! @brief スロットを作成し、接続します。 //! //! 内部でメモリを確保します。 //! //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! シグナルに接続できるスロット数は1つになります。 //! //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! Connect する前に必ず Disconnect するようにしてください。 //! Disconnect していない場合は、アサートで停止します。 //! //! @tparam TFunction 関数ポインタまたは、関数オブジェクトの型です。 //! //! @param[in] function 関数ポインタまたは、関数オブジェクトです。 //! //! @return 生成されたスロットです。 //! template SlotType* CreateAndConnect(TFunction function) { return CreateAndConnect(function, this->m_Allocator); } //! @brief スロットを切断します。 //! //! @param[in] slot 切断するスロットです。 //! void Disconnect(SlotType* slot) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED this->m_Slots.erase_find(slot); #else if (this->m_Slot == slot) { this->m_Slot = NULL; } #endif } //! @brief スロットを切断して、破棄します。 //! //! 関数オブジェクトにアロケータが設定されていると、オブジェクトを破棄します。 //! アロケータが設定されていないと、登録を解除して破棄は行いません。 //! //! @param[in] slot 切断するスロットです。 //! void DisconnectAndDestroy(SlotType* slot) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED this->m_Slots.erase_find(slot); slot->Destroy(); #else if (this->m_Slot == slot) { this->m_Slot = NULL; } if (slot) { slot->Destroy(); } #endif } //@} //! @brief シグナルを送信します。 ResultType operator()() { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED ResultCombinerType combiner; return combiner(m_Slots.begin(), m_Slots.end(), Invoker()); #else if (this->m_Slot) { return this->m_Slot->Invoke(); } else { return ResultType(); } #endif } //! @brief CreateInvalidateSignal() の実行に必要なメモリサイズを取得します。 static size_t GetMemorySizeForInvalidateSignal(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) { os::MemorySizeCalculator size(alignment); GetMemorySizeForInvalidateSignalInternal(&size); return size.GetSizeWithPadding(alignment); } //! @details :private static void GetMemorySizeForInvalidateSignalInternal(os::MemorySizeCalculator* pSize) { os::MemorySizeCalculator& size = *pSize; size += sizeof(SelfType); } //! @brief CreateFixedSizedSignal() の実行に必要なメモリサイズを取得します。 //! //! @param[in] maxSlots スロットを追加できる最大数です。 static size_t GetMemorySizeForFixedSizedSignal(size_t maxSlots, size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) { os::MemorySizeCalculator size(alignment); GetMemorySizeForFixedSizedSignalInternal(&size, maxSlots); return size.GetSizeWithPadding(alignment); } //! @details :private static void GetMemorySizeForFixedSizedSignalInternal(os::MemorySizeCalculator* pSize, size_t maxSlots) { os::MemorySizeCalculator& size = *pSize; size += sizeof(SelfType); #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED size += sizeof(SlotType*) * maxSlots; #else NW_UNUSED_VARIABLE(maxSlots); #endif } private: #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED //! @brief コンストラクタです。 Signal0(void* elements, size_t maxSlots, AllocatorType* allocator) : m_Allocator(allocator), m_Slots(elements, maxSlots, allocator) {} //! @brief コンストラクタです。 explicit Signal0(AllocatorType* allocator) : m_Allocator(allocator), m_Slots(allocator) {} //! @brief デストラクタです。 ~Signal0() { DestroyAllSlots(m_Slots); } #else //! @brief コンストラクタです。 explicit Signal0(AllocatorType* allocator) : m_Allocator(allocator), m_Slot(NULL) {} //! @brief デストラクタです。 ~Signal0() { SafeDestroy(this->m_Slot); } #endif AllocatorType* m_Allocator; #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED SlotList m_Slots; #else SlotType* m_Slot; #endif }; //--------------------------------------------------------------------------- //! @brief シグナルを受け取るためのインターフェースです。(引数は 1 個です) //! //! @tparam TResult 返り値の型です。 //! @tparam TAllocator アロケータの型です。 //--------------------------------------------------------------------------- template< typename TResult, typename TArg0, typename TAllocator = os::IAllocator > class Slot1 { public: typedef TResult ResultType; typedef TAllocator AllocatorType; //! @brief コンストラクタです。 explicit Slot1(AllocatorType* allocator) : m_Allocator(allocator) {} //! @brief 自らを破棄します。 void Destroy() { AllocatorType* allocator = this->GetAllocator(); if (allocator) { this->~Slot1(); allocator->Free(this); } } //! @brief 自らを破棄します。 void Destroy(AllocatorType* allocator) { NW_NULL_ASSERT(allocator); this->~Slot1(); allocator->Free(this); } //! @brief スロットにシグナルを送信します。 virtual ResultType Invoke(TArg0 arg0) = 0; AllocatorType* GetAllocator() { return m_Allocator; } protected: //! デストラクタです。 virtual ~Slot1() {} private: AllocatorType* m_Allocator; }; //--------------------------------------------------------------------------- //! @brief シグナルを受け取るためのクラスです。(引数は 1 個です) //! //! @tparam TResult 返り値の型です。 //! @tparam TFunction 関数か関数オブジェクトの型です。 //! @tparam TAllocator アロケータの型です。 //--------------------------------------------------------------------------- template< typename TResult, typename TArg0, typename TFunction, typename TAllocator = os::IAllocator > class FunctionSlot1 : public Slot1 { public: typedef TResult ResultType; typedef TFunction FunctionType; typedef TAllocator AllocatorType; //! コンストラクタです。 FunctionSlot1(AllocatorType* allocator, FunctionType function) : Slot1(allocator), m_Function(function) {} //! @brief スロットにシグナルを送信します。 virtual ResultType Invoke(TArg0 arg0) { return m_Function(arg0); } private: TFunction m_Function; }; //--------------------------------------------------------------------------- //! @brief スロットに合図を送るためのクラスです。(引数は 1 個です) //! //! @tparam TResult 返り値の型です。 //! @tparam TResultCombiner スロットの返り値をまとめて返してくれるコンバイナの型です。 //! @tparam TAllocator アロケータの型です。 //! @tparam TSlot スロットの型です。 //--------------------------------------------------------------------------- template< typename TResult, typename TArg0, typename TResultCombiner = LastValueResult, typename TAllocator = os::IAllocator, typename TSlot = Slot1 > class Signal1 { NW_DISALLOW_COPY_AND_ASSIGN(Signal1); public: typedef Signal1 SelfType; typedef TSlot SlotType; typedef TResult ResultType; typedef ut::MoveArray SlotList; typedef TResultCombiner ResultCombinerType; typedef TAllocator AllocatorType; #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED //! @brief スロット実行用関数オブジェクトです。 struct Invoker { Invoker(TArg0 arg0) : m_arg0(arg0) {} ResultType operator()(SlotType* slot) const { return slot->Invoke(m_arg0); } TArg0 m_arg0; }; #endif //---------------------------------------- //! @name 作成/破棄 //@{ //! @brief 無効なシグナルを生成します。 //! //! @param[in] allocator アロケータです。 //! static SelfType* CreateInvalidateSignal(AllocatorType* allocator) { void* memory = allocator->Alloc(sizeof(SelfType)); if (memory) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED return new(memory) SelfType(NULL, 0, allocator); #else return new(memory) SelfType(allocator); #endif } else { return NULL; } } //! @brief 必要なメモリを事前に確保してシグナルを生成します。 //! //! @param[in] maxSlots スロットを追加できる最大数です。 //! @param[in] allocator アロケータです。 //! static SelfType* CreateFixedSizedSignal(size_t maxSlots, AllocatorType* allocator) { void* memory = allocator->Alloc(sizeof(SelfType)); if (memory) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED void* elements = allocator->Alloc(sizeof(SlotType*) * maxSlots); if (elements != NULL) { return new(memory) SelfType(elements, maxSlots, allocator); } else { allocator->Free(memory); return NULL; } #else NW_UNUSED_VARIABLE(maxSlots); return new(memory) SelfType(allocator); #endif } else { return NULL; } } //! @brief 必要になるごとにメモリを確保するシグナルを生成します。 static SelfType* CreateVariableSizeSignal(AllocatorType* allocator) { void* memory = allocator->Alloc(sizeof(SelfType)); if (memory) { return new(memory) SelfType(allocator); } else { return NULL; } } //! オブジェクトを破棄します。 void Destroy() { this->~Signal1(); this->m_Allocator->Free(this); } //@} //---------------------------------------- //! @name スロット //@{ //! @brief スロットと接続し、シグナルが送られるようにする。 //! //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! シグナルに接続できるスロット数は1つになります。 //! //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! Connect する前に必ず Disconnect するようにしてください。 //! Disconnect していない場合は、アサートで停止します。 //! //! @param[in] slot スロットです。 //! void Connect(SlotType* slot) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED bool pushed = this->m_Slots.push_back(slot); NW_ASSERT(pushed); #else NW_ASSERT(this->m_Slot == NULL); this->m_Slot = slot; #endif } //! @brief スロットを作成し、接続します。 //! //! 内部でメモリを確保します。 //! //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! シグナルに接続できるスロット数は1つになります。 //! //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! Connect する前に必ず Disconnect するようにしてください。 //! Disconnect していない場合は、アサートで停止します。 //! //! @tparam TFunction 関数ポインタまたは、関数オブジェクトの型です。 //! //! @param[in] function 関数ポインタまたは、関数オブジェクトです。 //! @param[in] allocator アロケータです。 //! //! @return 生成されたスロットです。 //! template SlotType* CreateAndConnect(TFunction function, AllocatorType* allocator) { typedef FunctionSlot1 FunctionSlotType; FunctionSlotType* slot = CreateSlot(allocator, function); this->Connect(slot); return slot; } //! @brief スロットを作成し、接続します。 //! //! 内部でメモリを確保します。 //! //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! シグナルに接続できるスロット数は1つになります。 //! //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! Connect する前に必ず Disconnect するようにしてください。 //! Disconnect していない場合は、アサートで停止します。 //! //! @tparam TFunction 関数ポインタまたは、関数オブジェクトの型です。 //! //! @param[in] function 関数ポインタまたは、関数オブジェクトです。 //! //! @return 生成されたスロットです。 //! template SlotType* CreateAndConnect(TFunction function) { return CreateAndConnect(function, this->m_Allocator); } //! @brief スロットを切断します。 //! //! @param[in] slot 切断するスロットです。 //! void Disconnect(SlotType* slot) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED this->m_Slots.erase_find(slot); #else if (this->m_Slot == slot) { this->m_Slot = NULL; } #endif } //! @brief スロットを切断して、破棄します。 //! //! 関数オブジェクトにアロケータが設定されていると、オブジェクトを破棄します。 //! アロケータが設定されていないと、登録を解除して破棄は行いません。 //! //! @param[in] slot 切断するスロットです。 //! void DisconnectAndDestroy(SlotType* slot) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED this->m_Slots.erase_find(slot); slot->Destroy(); #else if (this->m_Slot == slot) { this->m_Slot = NULL; } if (slot) { slot->Destroy(); } #endif } //@} //! @brief シグナルを送信します。 ResultType operator()(TArg0 arg0) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED ResultCombinerType combiner; return combiner(m_Slots.begin(), m_Slots.end(), Invoker(arg0)); #else if (this->m_Slot) { return this->m_Slot->Invoke(arg0); } else { return ResultType(); } #endif } //! @brief CreateInvalidateSignal() の実行に必要なメモリサイズを取得します。 static size_t GetMemorySizeForInvalidateSignal(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) { os::MemorySizeCalculator size(alignment); GetMemorySizeForInvalidateSignalInternal(&size); return size.GetSizeWithPadding(alignment); } //! @details :private static void GetMemorySizeForInvalidateSignalInternal(os::MemorySizeCalculator* pSize) { os::MemorySizeCalculator& size = *pSize; size += sizeof(SelfType); } //! @brief CreateFixedSizedSignal() の実行に必要なメモリサイズを取得します。 //! //! @param[in] maxSlots スロットを追加できる最大数です。 static size_t GetMemorySizeForFixedSizedSignal(size_t maxSlots, size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) { os::MemorySizeCalculator size(alignment); GetMemorySizeForFixedSizedSignalInternal(&size, maxSlots); return size.GetSizeWithPadding(alignment); } //! @details :private static void GetMemorySizeForFixedSizedSignalInternal(os::MemorySizeCalculator* pSize, size_t maxSlots) { os::MemorySizeCalculator& size = *pSize; size += sizeof(SelfType); #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED size += sizeof(SlotType*) * maxSlots; #else NW_UNUSED_VARIABLE(maxSlots); #endif } private: #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED //! @brief コンストラクタです。 Signal1(void* elements, size_t maxSlots, AllocatorType* allocator) : m_Allocator(allocator), m_Slots(elements, maxSlots, allocator) {} //! @brief コンストラクタです。 explicit Signal1(AllocatorType* allocator) : m_Allocator(allocator), m_Slots(allocator) {} //! @brief デストラクタです。 ~Signal1() { DestroyAllSlots(m_Slots); } #else //! @brief コンストラクタです。 explicit Signal1(AllocatorType* allocator) : m_Allocator(allocator), m_Slot(NULL) {} //! @brief デストラクタです。 ~Signal1() { SafeDestroy(this->m_Slot); } #endif AllocatorType* m_Allocator; #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED SlotList m_Slots; #else SlotType* m_Slot; #endif }; //--------------------------------------------------------------------------- //! @brief シグナルを受け取るためのインターフェースです。(引数は 2 個です) //! //! @tparam TResult 返り値の型です。 //! @tparam TAllocator アロケータの型です。 //--------------------------------------------------------------------------- template< typename TResult, typename TArg0, typename TArg1, typename TAllocator = os::IAllocator > class Slot2 { public: typedef TResult ResultType; typedef TAllocator AllocatorType; //! @brief コンストラクタです。 explicit Slot2(AllocatorType* allocator) : m_Allocator(allocator) {} //! @brief 自らを破棄します。 void Destroy() { AllocatorType* allocator = this->GetAllocator(); if (allocator) { this->~Slot2(); allocator->Free(this); } } //! @brief 自らを破棄します。 void Destroy(AllocatorType* allocator) { NW_NULL_ASSERT(allocator); this->~Slot2(); allocator->Free(this); } //! @brief スロットにシグナルを送信します。 virtual ResultType Invoke(TArg0 arg0, TArg1 arg1) = 0; AllocatorType* GetAllocator() { return m_Allocator; } protected: //! デストラクタです。 virtual ~Slot2() {} private: AllocatorType* m_Allocator; }; //--------------------------------------------------------------------------- //! @brief シグナルを受け取るためのクラスです。(引数は 2 個です) //! //! @tparam TResult 返り値の型です。 //! @tparam TFunction 関数か関数オブジェクトの型です。 //! @tparam TAllocator アロケータの型です。 //--------------------------------------------------------------------------- template< typename TResult, typename TArg0, typename TArg1, typename TFunction, typename TAllocator = os::IAllocator > class FunctionSlot2 : public Slot2 { public: typedef TResult ResultType; typedef TFunction FunctionType; typedef TAllocator AllocatorType; //! コンストラクタです。 FunctionSlot2(AllocatorType* allocator, FunctionType function) : Slot2(allocator), m_Function(function) {} //! @brief スロットにシグナルを送信します。 virtual ResultType Invoke(TArg0 arg0, TArg1 arg1) { return m_Function(arg0, arg1); } private: TFunction m_Function; }; //--------------------------------------------------------------------------- //! @brief スロットに合図を送るためのクラスです。(引数は 2 個です) //! //! @tparam TResult 返り値の型です。 //! @tparam TResultCombiner スロットの返り値をまとめて返してくれるコンバイナの型です。 //! @tparam TAllocator アロケータの型です。 //! @tparam TSlot スロットの型です。 //--------------------------------------------------------------------------- template< typename TResult, typename TArg0, typename TArg1, typename TResultCombiner = LastValueResult, typename TAllocator = os::IAllocator, typename TSlot = Slot2 > class Signal2 { NW_DISALLOW_COPY_AND_ASSIGN(Signal2); public: typedef Signal2 SelfType; typedef TSlot SlotType; typedef TResult ResultType; typedef ut::MoveArray SlotList; typedef TResultCombiner ResultCombinerType; typedef TAllocator AllocatorType; #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED //! @brief スロット実行用関数オブジェクトです。 struct Invoker { Invoker(TArg0 arg0, TArg1 arg1) : m_arg0(arg0), m_arg1(arg1) {} ResultType operator()(SlotType* slot) const { return slot->Invoke(m_arg0, m_arg1); } TArg0 m_arg0; TArg1 m_arg1; }; #endif //---------------------------------------- //! @name 作成/破棄 //@{ //! @brief 無効なシグナルを生成します。 //! //! @param[in] allocator アロケータです。 //! static SelfType* CreateInvalidateSignal(AllocatorType* allocator) { void* memory = allocator->Alloc(sizeof(SelfType)); if (memory) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED return new(memory) SelfType(NULL, 0, allocator); #else return new(memory) SelfType(allocator); #endif } else { return NULL; } } //! @brief 必要なメモリを事前に確保してシグナルを生成します。 //! //! @param[in] maxSlots スロットを追加できる最大数です。 //! @param[in] allocator アロケータです。 //! static SelfType* CreateFixedSizedSignal(size_t maxSlots, AllocatorType* allocator) { void* memory = allocator->Alloc(sizeof(SelfType)); if (memory) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED void* elements = allocator->Alloc(sizeof(SlotType*) * maxSlots); if (elements != NULL) { return new(memory) SelfType(elements, maxSlots, allocator); } else { allocator->Free(memory); return NULL; } #else NW_UNUSED_VARIABLE(maxSlots); return new(memory) SelfType(allocator); #endif } else { return NULL; } } //! @brief 必要になるごとにメモリを確保するシグナルを生成します。 static SelfType* CreateVariableSizeSignal(AllocatorType* allocator) { void* memory = allocator->Alloc(sizeof(SelfType)); if (memory) { return new(memory) SelfType(allocator); } else { return NULL; } } //! オブジェクトを破棄します。 void Destroy() { this->~Signal2(); this->m_Allocator->Free(this); } //@} //---------------------------------------- //! @name スロット //@{ //! @brief スロットと接続し、シグナルが送られるようにする。 //! //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! シグナルに接続できるスロット数は1つになります。 //! //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! Connect する前に必ず Disconnect するようにしてください。 //! Disconnect していない場合は、アサートで停止します。 //! //! @param[in] slot スロットです。 //! void Connect(SlotType* slot) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED bool pushed = this->m_Slots.push_back(slot); NW_ASSERT(pushed); #else NW_ASSERT(this->m_Slot == NULL); this->m_Slot = slot; #endif } //! @brief スロットを作成し、接続します。 //! //! 内部でメモリを確保します。 //! //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! シグナルに接続できるスロット数は1つになります。 //! //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! Connect する前に必ず Disconnect するようにしてください。 //! Disconnect していない場合は、アサートで停止します。 //! //! @tparam TFunction 関数ポインタまたは、関数オブジェクトの型です。 //! //! @param[in] function 関数ポインタまたは、関数オブジェクトです。 //! @param[in] allocator アロケータです。 //! //! @return 生成されたスロットです。 //! template SlotType* CreateAndConnect(TFunction function, AllocatorType* allocator) { typedef FunctionSlot2 FunctionSlotType; FunctionSlotType* slot = CreateSlot(allocator, function); this->Connect(slot); return slot; } //! @brief スロットを作成し、接続します。 //! //! 内部でメモリを確保します。 //! //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! シグナルに接続できるスロット数は1つになります。 //! //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! Connect する前に必ず Disconnect するようにしてください。 //! Disconnect していない場合は、アサートで停止します。 //! //! @tparam TFunction 関数ポインタまたは、関数オブジェクトの型です。 //! //! @param[in] function 関数ポインタまたは、関数オブジェクトです。 //! //! @return 生成されたスロットです。 //! template SlotType* CreateAndConnect(TFunction function) { return CreateAndConnect(function, this->m_Allocator); } //! @brief スロットを切断します。 //! //! @param[in] slot 切断するスロットです。 //! void Disconnect(SlotType* slot) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED this->m_Slots.erase_find(slot); #else if (this->m_Slot == slot) { this->m_Slot = NULL; } #endif } //! @brief スロットを切断して、破棄します。 //! //! 関数オブジェクトにアロケータが設定されていると、オブジェクトを破棄します。 //! アロケータが設定されていないと、登録を解除して破棄は行いません。 //! //! @param[in] slot 切断するスロットです。 //! void DisconnectAndDestroy(SlotType* slot) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED this->m_Slots.erase_find(slot); slot->Destroy(); #else if (this->m_Slot == slot) { this->m_Slot = NULL; } if (slot) { slot->Destroy(); } #endif } //@} //! @brief シグナルを送信します。 ResultType operator()(TArg0 arg0, TArg1 arg1) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED ResultCombinerType combiner; return combiner(m_Slots.begin(), m_Slots.end(), Invoker(arg0, arg1)); #else if (this->m_Slot) { return this->m_Slot->Invoke(arg0, arg1); } else { return ResultType(); } #endif } //! @brief CreateInvalidateSignal() の実行に必要なメモリサイズを取得します。 static size_t GetMemorySizeForInvalidateSignal(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) { os::MemorySizeCalculator size(alignment); GetMemorySizeForInvalidateSignalInternal(&size); return size.GetSizeWithPadding(alignment); } //! @details :private static void GetMemorySizeForInvalidateSignalInternal(os::MemorySizeCalculator* pSize) { os::MemorySizeCalculator& size = *pSize; size += sizeof(SelfType); } //! @brief CreateFixedSizedSignal() の実行に必要なメモリサイズを取得します。 //! //! @param[in] maxSlots スロットを追加できる最大数です。 static size_t GetMemorySizeForFixedSizedSignal(size_t maxSlots, size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) { os::MemorySizeCalculator size(alignment); GetMemorySizeForFixedSizedSignalInternal(&size, maxSlots); return size.GetSizeWithPadding(alignment); } //! @details :private static void GetMemorySizeForFixedSizedSignalInternal(os::MemorySizeCalculator* pSize, size_t maxSlots) { os::MemorySizeCalculator& size = *pSize; size += sizeof(SelfType); #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED size += sizeof(SlotType*) * maxSlots; #else NW_UNUSED_VARIABLE(maxSlots); #endif } private: #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED //! @brief コンストラクタです。 Signal2(void* elements, size_t maxSlots, AllocatorType* allocator) : m_Allocator(allocator), m_Slots(elements, maxSlots, allocator) {} //! @brief コンストラクタです。 explicit Signal2(AllocatorType* allocator) : m_Allocator(allocator), m_Slots(allocator) {} //! @brief デストラクタです。 ~Signal2() { DestroyAllSlots(m_Slots); } #else //! @brief コンストラクタです。 explicit Signal2(AllocatorType* allocator) : m_Allocator(allocator), m_Slot(NULL) {} //! @brief デストラクタです。 ~Signal2() { SafeDestroy(this->m_Slot); } #endif AllocatorType* m_Allocator; #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED SlotList m_Slots; #else SlotType* m_Slot; #endif }; //--------------------------------------------------------------------------- //! @brief シグナルを受け取るためのインターフェースです。(引数は 3 個です) //! //! @tparam TResult 返り値の型です。 //! @tparam TAllocator アロケータの型です。 //--------------------------------------------------------------------------- template< typename TResult, typename TArg0, typename TArg1, typename TArg2, typename TAllocator = os::IAllocator > class Slot3 { public: typedef TResult ResultType; typedef TAllocator AllocatorType; //! @brief コンストラクタです。 explicit Slot3(AllocatorType* allocator) : m_Allocator(allocator) {} //! @brief 自らを破棄します。 void Destroy() { AllocatorType* allocator = this->GetAllocator(); if (allocator) { this->~Slot3(); allocator->Free(this); } } //! @brief 自らを破棄します。 void Destroy(AllocatorType* allocator) { NW_NULL_ASSERT(allocator); this->~Slot3(); allocator->Free(this); } //! @brief スロットにシグナルを送信します。 virtual ResultType Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2) = 0; AllocatorType* GetAllocator() { return m_Allocator; } protected: //! デストラクタです。 virtual ~Slot3() {} private: AllocatorType* m_Allocator; }; //--------------------------------------------------------------------------- //! @brief シグナルを受け取るためのクラスです。(引数は 3 個です) //! //! @tparam TResult 返り値の型です。 //! @tparam TFunction 関数か関数オブジェクトの型です。 //! @tparam TAllocator アロケータの型です。 //--------------------------------------------------------------------------- template< typename TResult, typename TArg0, typename TArg1, typename TArg2, typename TFunction, typename TAllocator = os::IAllocator > class FunctionSlot3 : public Slot3 { public: typedef TResult ResultType; typedef TFunction FunctionType; typedef TAllocator AllocatorType; //! コンストラクタです。 FunctionSlot3(AllocatorType* allocator, FunctionType function) : Slot3(allocator), m_Function(function) {} //! @brief スロットにシグナルを送信します。 virtual ResultType Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2) { return m_Function(arg0, arg1, arg2); } private: TFunction m_Function; }; //--------------------------------------------------------------------------- //! @brief スロットに合図を送るためのクラスです。(引数は 3 個です) //! //! @tparam TResult 返り値の型です。 //! @tparam TResultCombiner スロットの返り値をまとめて返してくれるコンバイナの型です。 //! @tparam TAllocator アロケータの型です。 //! @tparam TSlot スロットの型です。 //--------------------------------------------------------------------------- template< typename TResult, typename TArg0, typename TArg1, typename TArg2, typename TResultCombiner = LastValueResult, typename TAllocator = os::IAllocator, typename TSlot = Slot3 > class Signal3 { NW_DISALLOW_COPY_AND_ASSIGN(Signal3); public: typedef Signal3 SelfType; typedef TSlot SlotType; typedef TResult ResultType; typedef ut::MoveArray SlotList; typedef TResultCombiner ResultCombinerType; typedef TAllocator AllocatorType; #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED //! @brief スロット実行用関数オブジェクトです。 struct Invoker { Invoker(TArg0 arg0, TArg1 arg1, TArg2 arg2) : m_arg0(arg0), m_arg1(arg1), m_arg2(arg2) {} ResultType operator()(SlotType* slot) const { return slot->Invoke(m_arg0, m_arg1, m_arg2); } TArg0 m_arg0; TArg1 m_arg1; TArg2 m_arg2; }; #endif //---------------------------------------- //! @name 作成/破棄 //@{ //! @brief 無効なシグナルを生成します。 //! //! @param[in] allocator アロケータです。 //! static SelfType* CreateInvalidateSignal(AllocatorType* allocator) { void* memory = allocator->Alloc(sizeof(SelfType)); if (memory) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED return new(memory) SelfType(NULL, 0, allocator); #else return new(memory) SelfType(allocator); #endif } else { return NULL; } } //! @brief 必要なメモリを事前に確保してシグナルを生成します。 //! //! @param[in] maxSlots スロットを追加できる最大数です。 //! @param[in] allocator アロケータです。 //! static SelfType* CreateFixedSizedSignal(size_t maxSlots, AllocatorType* allocator) { void* memory = allocator->Alloc(sizeof(SelfType)); if (memory) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED void* elements = allocator->Alloc(sizeof(SlotType*) * maxSlots); if (elements != NULL) { return new(memory) SelfType(elements, maxSlots, allocator); } else { allocator->Free(memory); return NULL; } #else NW_UNUSED_VARIABLE(maxSlots); return new(memory) SelfType(allocator); #endif } else { return NULL; } } //! @brief 必要になるごとにメモリを確保するシグナルを生成します。 static SelfType* CreateVariableSizeSignal(AllocatorType* allocator) { void* memory = allocator->Alloc(sizeof(SelfType)); if (memory) { return new(memory) SelfType(allocator); } else { return NULL; } } //! オブジェクトを破棄します。 void Destroy() { this->~Signal3(); this->m_Allocator->Free(this); } //@} //---------------------------------------- //! @name スロット //@{ //! @brief スロットと接続し、シグナルが送られるようにする。 //! //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! シグナルに接続できるスロット数は1つになります。 //! //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! Connect する前に必ず Disconnect するようにしてください。 //! Disconnect していない場合は、アサートで停止します。 //! //! @param[in] slot スロットです。 //! void Connect(SlotType* slot) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED bool pushed = this->m_Slots.push_back(slot); NW_ASSERT(pushed); #else NW_ASSERT(this->m_Slot == NULL); this->m_Slot = slot; #endif } //! @brief スロットを作成し、接続します。 //! //! 内部でメモリを確保します。 //! //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! シグナルに接続できるスロット数は1つになります。 //! //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! Connect する前に必ず Disconnect するようにしてください。 //! Disconnect していない場合は、アサートで停止します。 //! //! @tparam TFunction 関数ポインタまたは、関数オブジェクトの型です。 //! //! @param[in] function 関数ポインタまたは、関数オブジェクトです。 //! @param[in] allocator アロケータです。 //! //! @return 生成されたスロットです。 //! template SlotType* CreateAndConnect(TFunction function, AllocatorType* allocator) { typedef FunctionSlot3 FunctionSlotType; FunctionSlotType* slot = CreateSlot(allocator, function); this->Connect(slot); return slot; } //! @brief スロットを作成し、接続します。 //! //! 内部でメモリを確保します。 //! //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! シグナルに接続できるスロット数は1つになります。 //! //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! Connect する前に必ず Disconnect するようにしてください。 //! Disconnect していない場合は、アサートで停止します。 //! //! @tparam TFunction 関数ポインタまたは、関数オブジェクトの型です。 //! //! @param[in] function 関数ポインタまたは、関数オブジェクトです。 //! //! @return 生成されたスロットです。 //! template SlotType* CreateAndConnect(TFunction function) { return CreateAndConnect(function, this->m_Allocator); } //! @brief スロットを切断します。 //! //! @param[in] slot 切断するスロットです。 //! void Disconnect(SlotType* slot) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED this->m_Slots.erase_find(slot); #else if (this->m_Slot == slot) { this->m_Slot = NULL; } #endif } //! @brief スロットを切断して、破棄します。 //! //! 関数オブジェクトにアロケータが設定されていると、オブジェクトを破棄します。 //! アロケータが設定されていないと、登録を解除して破棄は行いません。 //! //! @param[in] slot 切断するスロットです。 //! void DisconnectAndDestroy(SlotType* slot) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED this->m_Slots.erase_find(slot); slot->Destroy(); #else if (this->m_Slot == slot) { this->m_Slot = NULL; } if (slot) { slot->Destroy(); } #endif } //@} //! @brief シグナルを送信します。 ResultType operator()(TArg0 arg0, TArg1 arg1, TArg2 arg2) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED ResultCombinerType combiner; return combiner(m_Slots.begin(), m_Slots.end(), Invoker(arg0, arg1, arg2)); #else if (this->m_Slot) { return this->m_Slot->Invoke(arg0, arg1, arg2); } else { return ResultType(); } #endif } //! @brief CreateInvalidateSignal() の実行に必要なメモリサイズを取得します。 static size_t GetMemorySizeForInvalidateSignal(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) { os::MemorySizeCalculator size(alignment); GetMemorySizeForInvalidateSignalInternal(&size); return size.GetSizeWithPadding(alignment); } //! @details :private static void GetMemorySizeForInvalidateSignalInternal(os::MemorySizeCalculator* pSize) { os::MemorySizeCalculator& size = *pSize; size += sizeof(SelfType); } //! @brief CreateFixedSizedSignal() の実行に必要なメモリサイズを取得します。 //! //! @param[in] maxSlots スロットを追加できる最大数です。 static size_t GetMemorySizeForFixedSizedSignal(size_t maxSlots, size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) { os::MemorySizeCalculator size(alignment); GetMemorySizeForFixedSizedSignalInternal(&size, maxSlots); return size.GetSizeWithPadding(alignment); } //! @details :private static void GetMemorySizeForFixedSizedSignalInternal(os::MemorySizeCalculator* pSize, size_t maxSlots) { os::MemorySizeCalculator& size = *pSize; size += sizeof(SelfType); #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED size += sizeof(SlotType*) * maxSlots; #else NW_UNUSED_VARIABLE(maxSlots); #endif } private: #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED //! @brief コンストラクタです。 Signal3(void* elements, size_t maxSlots, AllocatorType* allocator) : m_Allocator(allocator), m_Slots(elements, maxSlots, allocator) {} //! @brief コンストラクタです。 explicit Signal3(AllocatorType* allocator) : m_Allocator(allocator), m_Slots(allocator) {} //! @brief デストラクタです。 ~Signal3() { DestroyAllSlots(m_Slots); } #else //! @brief コンストラクタです。 explicit Signal3(AllocatorType* allocator) : m_Allocator(allocator), m_Slot(NULL) {} //! @brief デストラクタです。 ~Signal3() { SafeDestroy(this->m_Slot); } #endif AllocatorType* m_Allocator; #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED SlotList m_Slots; #else SlotType* m_Slot; #endif }; //--------------------------------------------------------------------------- //! @brief シグナルを受け取るためのインターフェースです。(引数は 4 個です) //! //! @tparam TResult 返り値の型です。 //! @tparam TAllocator アロケータの型です。 //--------------------------------------------------------------------------- template< typename TResult, typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TAllocator = os::IAllocator > class Slot4 { public: typedef TResult ResultType; typedef TAllocator AllocatorType; //! @brief コンストラクタです。 explicit Slot4(AllocatorType* allocator) : m_Allocator(allocator) {} //! @brief 自らを破棄します。 void Destroy() { AllocatorType* allocator = this->GetAllocator(); if (allocator) { this->~Slot4(); allocator->Free(this); } } //! @brief 自らを破棄します。 void Destroy(AllocatorType* allocator) { NW_NULL_ASSERT(allocator); this->~Slot4(); allocator->Free(this); } //! @brief スロットにシグナルを送信します。 virtual ResultType Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3) = 0; AllocatorType* GetAllocator() { return m_Allocator; } protected: //! デストラクタです。 virtual ~Slot4() {} private: AllocatorType* m_Allocator; }; //--------------------------------------------------------------------------- //! @brief シグナルを受け取るためのクラスです。(引数は 4 個です) //! //! @tparam TResult 返り値の型です。 //! @tparam TFunction 関数か関数オブジェクトの型です。 //! @tparam TAllocator アロケータの型です。 //--------------------------------------------------------------------------- template< typename TResult, typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TFunction, typename TAllocator = os::IAllocator > class FunctionSlot4 : public Slot4 { public: typedef TResult ResultType; typedef TFunction FunctionType; typedef TAllocator AllocatorType; //! コンストラクタです。 FunctionSlot4(AllocatorType* allocator, FunctionType function) : Slot4(allocator), m_Function(function) {} //! @brief スロットにシグナルを送信します。 virtual ResultType Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3) { return m_Function(arg0, arg1, arg2, arg3); } private: TFunction m_Function; }; //--------------------------------------------------------------------------- //! @brief スロットに合図を送るためのクラスです。(引数は 4 個です) //! //! @tparam TResult 返り値の型です。 //! @tparam TResultCombiner スロットの返り値をまとめて返してくれるコンバイナの型です。 //! @tparam TAllocator アロケータの型です。 //! @tparam TSlot スロットの型です。 //--------------------------------------------------------------------------- template< typename TResult, typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TResultCombiner = LastValueResult, typename TAllocator = os::IAllocator, typename TSlot = Slot4 > class Signal4 { NW_DISALLOW_COPY_AND_ASSIGN(Signal4); public: typedef Signal4 SelfType; typedef TSlot SlotType; typedef TResult ResultType; typedef ut::MoveArray SlotList; typedef TResultCombiner ResultCombinerType; typedef TAllocator AllocatorType; #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED //! @brief スロット実行用関数オブジェクトです。 struct Invoker { Invoker(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3) : m_arg0(arg0), m_arg1(arg1), m_arg2(arg2), m_arg3(arg3) {} ResultType operator()(SlotType* slot) const { return slot->Invoke(m_arg0, m_arg1, m_arg2, m_arg3); } TArg0 m_arg0; TArg1 m_arg1; TArg2 m_arg2; TArg3 m_arg3; }; #endif //---------------------------------------- //! @name 作成/破棄 //@{ //! @brief 無効なシグナルを生成します。 //! //! @param[in] allocator アロケータです。 //! static SelfType* CreateInvalidateSignal(AllocatorType* allocator) { void* memory = allocator->Alloc(sizeof(SelfType)); if (memory) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED return new(memory) SelfType(NULL, 0, allocator); #else return new(memory) SelfType(allocator); #endif } else { return NULL; } } //! @brief 必要なメモリを事前に確保してシグナルを生成します。 //! //! @param[in] maxSlots スロットを追加できる最大数です。 //! @param[in] allocator アロケータです。 //! static SelfType* CreateFixedSizedSignal(size_t maxSlots, AllocatorType* allocator) { void* memory = allocator->Alloc(sizeof(SelfType)); if (memory) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED void* elements = allocator->Alloc(sizeof(SlotType*) * maxSlots); if (elements != NULL) { return new(memory) SelfType(elements, maxSlots, allocator); } else { allocator->Free(memory); return NULL; } #else NW_UNUSED_VARIABLE(maxSlots); return new(memory) SelfType(allocator); #endif } else { return NULL; } } //! @brief 必要になるごとにメモリを確保するシグナルを生成します。 static SelfType* CreateVariableSizeSignal(AllocatorType* allocator) { void* memory = allocator->Alloc(sizeof(SelfType)); if (memory) { return new(memory) SelfType(allocator); } else { return NULL; } } //! オブジェクトを破棄します。 void Destroy() { this->~Signal4(); this->m_Allocator->Free(this); } //@} //---------------------------------------- //! @name スロット //@{ //! @brief スロットと接続し、シグナルが送られるようにする。 //! //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! シグナルに接続できるスロット数は1つになります。 //! //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! Connect する前に必ず Disconnect するようにしてください。 //! Disconnect していない場合は、アサートで停止します。 //! //! @param[in] slot スロットです。 //! void Connect(SlotType* slot) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED bool pushed = this->m_Slots.push_back(slot); NW_ASSERT(pushed); #else NW_ASSERT(this->m_Slot == NULL); this->m_Slot = slot; #endif } //! @brief スロットを作成し、接続します。 //! //! 内部でメモリを確保します。 //! //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! シグナルに接続できるスロット数は1つになります。 //! //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! Connect する前に必ず Disconnect するようにしてください。 //! Disconnect していない場合は、アサートで停止します。 //! //! @tparam TFunction 関数ポインタまたは、関数オブジェクトの型です。 //! //! @param[in] function 関数ポインタまたは、関数オブジェクトです。 //! @param[in] allocator アロケータです。 //! //! @return 生成されたスロットです。 //! template SlotType* CreateAndConnect(TFunction function, AllocatorType* allocator) { typedef FunctionSlot4 FunctionSlotType; FunctionSlotType* slot = CreateSlot(allocator, function); this->Connect(slot); return slot; } //! @brief スロットを作成し、接続します。 //! //! 内部でメモリを確保します。 //! //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! シグナルに接続できるスロット数は1つになります。 //! //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! Connect する前に必ず Disconnect するようにしてください。 //! Disconnect していない場合は、アサートで停止します。 //! //! @tparam TFunction 関数ポインタまたは、関数オブジェクトの型です。 //! //! @param[in] function 関数ポインタまたは、関数オブジェクトです。 //! //! @return 生成されたスロットです。 //! template SlotType* CreateAndConnect(TFunction function) { return CreateAndConnect(function, this->m_Allocator); } //! @brief スロットを切断します。 //! //! @param[in] slot 切断するスロットです。 //! void Disconnect(SlotType* slot) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED this->m_Slots.erase_find(slot); #else if (this->m_Slot == slot) { this->m_Slot = NULL; } #endif } //! @brief スロットを切断して、破棄します。 //! //! 関数オブジェクトにアロケータが設定されていると、オブジェクトを破棄します。 //! アロケータが設定されていないと、登録を解除して破棄は行いません。 //! //! @param[in] slot 切断するスロットです。 //! void DisconnectAndDestroy(SlotType* slot) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED this->m_Slots.erase_find(slot); slot->Destroy(); #else if (this->m_Slot == slot) { this->m_Slot = NULL; } if (slot) { slot->Destroy(); } #endif } //@} //! @brief シグナルを送信します。 ResultType operator()(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED ResultCombinerType combiner; return combiner(m_Slots.begin(), m_Slots.end(), Invoker(arg0, arg1, arg2, arg3)); #else if (this->m_Slot) { return this->m_Slot->Invoke(arg0, arg1, arg2, arg3); } else { return ResultType(); } #endif } //! @brief CreateInvalidateSignal() の実行に必要なメモリサイズを取得します。 static size_t GetMemorySizeForInvalidateSignal(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) { os::MemorySizeCalculator size(alignment); GetMemorySizeForInvalidateSignalInternal(&size); return size.GetSizeWithPadding(alignment); } //! @details :private static void GetMemorySizeForInvalidateSignalInternal(os::MemorySizeCalculator* pSize) { os::MemorySizeCalculator& size = *pSize; size += sizeof(SelfType); } //! @brief CreateFixedSizedSignal() の実行に必要なメモリサイズを取得します。 //! //! @param[in] maxSlots スロットを追加できる最大数です。 static size_t GetMemorySizeForFixedSizedSignal(size_t maxSlots, size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) { os::MemorySizeCalculator size(alignment); GetMemorySizeForFixedSizedSignalInternal(&size, maxSlots); return size.GetSizeWithPadding(alignment); } //! @details :private static void GetMemorySizeForFixedSizedSignalInternal(os::MemorySizeCalculator* pSize, size_t maxSlots) { os::MemorySizeCalculator& size = *pSize; size += sizeof(SelfType); #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED size += sizeof(SlotType*) * maxSlots; #else NW_UNUSED_VARIABLE(maxSlots); #endif } private: #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED //! @brief コンストラクタです。 Signal4(void* elements, size_t maxSlots, AllocatorType* allocator) : m_Allocator(allocator), m_Slots(elements, maxSlots, allocator) {} //! @brief コンストラクタです。 explicit Signal4(AllocatorType* allocator) : m_Allocator(allocator), m_Slots(allocator) {} //! @brief デストラクタです。 ~Signal4() { DestroyAllSlots(m_Slots); } #else //! @brief コンストラクタです。 explicit Signal4(AllocatorType* allocator) : m_Allocator(allocator), m_Slot(NULL) {} //! @brief デストラクタです。 ~Signal4() { SafeDestroy(this->m_Slot); } #endif AllocatorType* m_Allocator; #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED SlotList m_Slots; #else SlotType* m_Slot; #endif }; //--------------------------------------------------------------------------- //! @brief シグナルを受け取るためのインターフェースです。(引数は 5 個です) //! //! @tparam TResult 返り値の型です。 //! @tparam TAllocator アロケータの型です。 //--------------------------------------------------------------------------- template< typename TResult, typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TAllocator = os::IAllocator > class Slot5 { public: typedef TResult ResultType; typedef TAllocator AllocatorType; //! @brief コンストラクタです。 explicit Slot5(AllocatorType* allocator) : m_Allocator(allocator) {} //! @brief 自らを破棄します。 void Destroy() { AllocatorType* allocator = this->GetAllocator(); if (allocator) { this->~Slot5(); allocator->Free(this); } } //! @brief 自らを破棄します。 void Destroy(AllocatorType* allocator) { NW_NULL_ASSERT(allocator); this->~Slot5(); allocator->Free(this); } //! @brief スロットにシグナルを送信します。 virtual ResultType Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4) = 0; AllocatorType* GetAllocator() { return m_Allocator; } protected: //! デストラクタです。 virtual ~Slot5() {} private: AllocatorType* m_Allocator; }; //--------------------------------------------------------------------------- //! @brief シグナルを受け取るためのクラスです。(引数は 5 個です) //! //! @tparam TResult 返り値の型です。 //! @tparam TFunction 関数か関数オブジェクトの型です。 //! @tparam TAllocator アロケータの型です。 //--------------------------------------------------------------------------- template< typename TResult, typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TFunction, typename TAllocator = os::IAllocator > class FunctionSlot5 : public Slot5 { public: typedef TResult ResultType; typedef TFunction FunctionType; typedef TAllocator AllocatorType; //! コンストラクタです。 FunctionSlot5(AllocatorType* allocator, FunctionType function) : Slot5(allocator), m_Function(function) {} //! @brief スロットにシグナルを送信します。 virtual ResultType Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4) { return m_Function(arg0, arg1, arg2, arg3, arg4); } private: TFunction m_Function; }; //--------------------------------------------------------------------------- //! @brief スロットに合図を送るためのクラスです。(引数は 5 個です) //! //! @tparam TResult 返り値の型です。 //! @tparam TResultCombiner スロットの返り値をまとめて返してくれるコンバイナの型です。 //! @tparam TAllocator アロケータの型です。 //! @tparam TSlot スロットの型です。 //--------------------------------------------------------------------------- template< typename TResult, typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TResultCombiner = LastValueResult, typename TAllocator = os::IAllocator, typename TSlot = Slot5 > class Signal5 { NW_DISALLOW_COPY_AND_ASSIGN(Signal5); public: typedef Signal5 SelfType; typedef TSlot SlotType; typedef TResult ResultType; typedef ut::MoveArray SlotList; typedef TResultCombiner ResultCombinerType; typedef TAllocator AllocatorType; #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED //! @brief スロット実行用関数オブジェクトです。 struct Invoker { Invoker(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4) : m_arg0(arg0), m_arg1(arg1), m_arg2(arg2), m_arg3(arg3), m_arg4(arg4) {} ResultType operator()(SlotType* slot) const { return slot->Invoke(m_arg0, m_arg1, m_arg2, m_arg3, m_arg4); } TArg0 m_arg0; TArg1 m_arg1; TArg2 m_arg2; TArg3 m_arg3; TArg4 m_arg4; }; #endif //---------------------------------------- //! @name 作成/破棄 //@{ //! @brief 無効なシグナルを生成します。 //! //! @param[in] allocator アロケータです。 //! static SelfType* CreateInvalidateSignal(AllocatorType* allocator) { void* memory = allocator->Alloc(sizeof(SelfType)); if (memory) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED return new(memory) SelfType(NULL, 0, allocator); #else return new(memory) SelfType(allocator); #endif } else { return NULL; } } //! @brief 必要なメモリを事前に確保してシグナルを生成します。 //! //! @param[in] maxSlots スロットを追加できる最大数です。 //! @param[in] allocator アロケータです。 //! static SelfType* CreateFixedSizedSignal(size_t maxSlots, AllocatorType* allocator) { void* memory = allocator->Alloc(sizeof(SelfType)); if (memory) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED void* elements = allocator->Alloc(sizeof(SlotType*) * maxSlots); if (elements != NULL) { return new(memory) SelfType(elements, maxSlots, allocator); } else { allocator->Free(memory); return NULL; } #else NW_UNUSED_VARIABLE(maxSlots); return new(memory) SelfType(allocator); #endif } else { return NULL; } } //! @brief 必要になるごとにメモリを確保するシグナルを生成します。 static SelfType* CreateVariableSizeSignal(AllocatorType* allocator) { void* memory = allocator->Alloc(sizeof(SelfType)); if (memory) { return new(memory) SelfType(allocator); } else { return NULL; } } //! オブジェクトを破棄します。 void Destroy() { this->~Signal5(); this->m_Allocator->Free(this); } //@} //---------------------------------------- //! @name スロット //@{ //! @brief スロットと接続し、シグナルが送られるようにする。 //! //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! シグナルに接続できるスロット数は1つになります。 //! //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! Connect する前に必ず Disconnect するようにしてください。 //! Disconnect していない場合は、アサートで停止します。 //! //! @param[in] slot スロットです。 //! void Connect(SlotType* slot) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED bool pushed = this->m_Slots.push_back(slot); NW_ASSERT(pushed); #else NW_ASSERT(this->m_Slot == NULL); this->m_Slot = slot; #endif } //! @brief スロットを作成し、接続します。 //! //! 内部でメモリを確保します。 //! //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! シグナルに接続できるスロット数は1つになります。 //! //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! Connect する前に必ず Disconnect するようにしてください。 //! Disconnect していない場合は、アサートで停止します。 //! //! @tparam TFunction 関数ポインタまたは、関数オブジェクトの型です。 //! //! @param[in] function 関数ポインタまたは、関数オブジェクトです。 //! @param[in] allocator アロケータです。 //! //! @return 生成されたスロットです。 //! template SlotType* CreateAndConnect(TFunction function, AllocatorType* allocator) { typedef FunctionSlot5 FunctionSlotType; FunctionSlotType* slot = CreateSlot(allocator, function); this->Connect(slot); return slot; } //! @brief スロットを作成し、接続します。 //! //! 内部でメモリを確保します。 //! //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! シグナルに接続できるスロット数は1つになります。 //! //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! Connect する前に必ず Disconnect するようにしてください。 //! Disconnect していない場合は、アサートで停止します。 //! //! @tparam TFunction 関数ポインタまたは、関数オブジェクトの型です。 //! //! @param[in] function 関数ポインタまたは、関数オブジェクトです。 //! //! @return 生成されたスロットです。 //! template SlotType* CreateAndConnect(TFunction function) { return CreateAndConnect(function, this->m_Allocator); } //! @brief スロットを切断します。 //! //! @param[in] slot 切断するスロットです。 //! void Disconnect(SlotType* slot) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED this->m_Slots.erase_find(slot); #else if (this->m_Slot == slot) { this->m_Slot = NULL; } #endif } //! @brief スロットを切断して、破棄します。 //! //! 関数オブジェクトにアロケータが設定されていると、オブジェクトを破棄します。 //! アロケータが設定されていないと、登録を解除して破棄は行いません。 //! //! @param[in] slot 切断するスロットです。 //! void DisconnectAndDestroy(SlotType* slot) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED this->m_Slots.erase_find(slot); slot->Destroy(); #else if (this->m_Slot == slot) { this->m_Slot = NULL; } if (slot) { slot->Destroy(); } #endif } //@} //! @brief シグナルを送信します。 ResultType operator()(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED ResultCombinerType combiner; return combiner(m_Slots.begin(), m_Slots.end(), Invoker(arg0, arg1, arg2, arg3, arg4)); #else if (this->m_Slot) { return this->m_Slot->Invoke(arg0, arg1, arg2, arg3, arg4); } else { return ResultType(); } #endif } //! @brief CreateInvalidateSignal() の実行に必要なメモリサイズを取得します。 static size_t GetMemorySizeForInvalidateSignal(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) { os::MemorySizeCalculator size(alignment); GetMemorySizeForInvalidateSignalInternal(&size); return size.GetSizeWithPadding(alignment); } //! @details :private static void GetMemorySizeForInvalidateSignalInternal(os::MemorySizeCalculator* pSize) { os::MemorySizeCalculator& size = *pSize; size += sizeof(SelfType); } //! @brief CreateFixedSizedSignal() の実行に必要なメモリサイズを取得します。 //! //! @param[in] maxSlots スロットを追加できる最大数です。 static size_t GetMemorySizeForFixedSizedSignal(size_t maxSlots, size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) { os::MemorySizeCalculator size(alignment); GetMemorySizeForFixedSizedSignalInternal(&size, maxSlots); return size.GetSizeWithPadding(alignment); } //! @details :private static void GetMemorySizeForFixedSizedSignalInternal(os::MemorySizeCalculator* pSize, size_t maxSlots) { os::MemorySizeCalculator& size = *pSize; size += sizeof(SelfType); #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED size += sizeof(SlotType*) * maxSlots; #else NW_UNUSED_VARIABLE(maxSlots); #endif } private: #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED //! @brief コンストラクタです。 Signal5(void* elements, size_t maxSlots, AllocatorType* allocator) : m_Allocator(allocator), m_Slots(elements, maxSlots, allocator) {} //! @brief コンストラクタです。 explicit Signal5(AllocatorType* allocator) : m_Allocator(allocator), m_Slots(allocator) {} //! @brief デストラクタです。 ~Signal5() { DestroyAllSlots(m_Slots); } #else //! @brief コンストラクタです。 explicit Signal5(AllocatorType* allocator) : m_Allocator(allocator), m_Slot(NULL) {} //! @brief デストラクタです。 ~Signal5() { SafeDestroy(this->m_Slot); } #endif AllocatorType* m_Allocator; #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED SlotList m_Slots; #else SlotType* m_Slot; #endif }; //--------------------------------------------------------------------------- //! @brief シグナルを受け取るためのインターフェースです。(引数は 6 個です) //! //! @tparam TResult 返り値の型です。 //! @tparam TAllocator アロケータの型です。 //--------------------------------------------------------------------------- template< typename TResult, typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename TAllocator = os::IAllocator > class Slot6 { public: typedef TResult ResultType; typedef TAllocator AllocatorType; //! @brief コンストラクタです。 explicit Slot6(AllocatorType* allocator) : m_Allocator(allocator) {} //! @brief 自らを破棄します。 void Destroy() { AllocatorType* allocator = this->GetAllocator(); if (allocator) { this->~Slot6(); allocator->Free(this); } } //! @brief 自らを破棄します。 void Destroy(AllocatorType* allocator) { NW_NULL_ASSERT(allocator); this->~Slot6(); allocator->Free(this); } //! @brief スロットにシグナルを送信します。 virtual ResultType Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5) = 0; AllocatorType* GetAllocator() { return m_Allocator; } protected: //! デストラクタです。 virtual ~Slot6() {} private: AllocatorType* m_Allocator; }; //--------------------------------------------------------------------------- //! @brief シグナルを受け取るためのクラスです。(引数は 6 個です) //! //! @tparam TResult 返り値の型です。 //! @tparam TFunction 関数か関数オブジェクトの型です。 //! @tparam TAllocator アロケータの型です。 //--------------------------------------------------------------------------- template< typename TResult, typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename TFunction, typename TAllocator = os::IAllocator > class FunctionSlot6 : public Slot6 { public: typedef TResult ResultType; typedef TFunction FunctionType; typedef TAllocator AllocatorType; //! コンストラクタです。 FunctionSlot6(AllocatorType* allocator, FunctionType function) : Slot6(allocator), m_Function(function) {} //! @brief スロットにシグナルを送信します。 virtual ResultType Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5) { return m_Function(arg0, arg1, arg2, arg3, arg4, arg5); } private: TFunction m_Function; }; //--------------------------------------------------------------------------- //! @brief スロットに合図を送るためのクラスです。(引数は 6 個です) //! //! @tparam TResult 返り値の型です。 //! @tparam TResultCombiner スロットの返り値をまとめて返してくれるコンバイナの型です。 //! @tparam TAllocator アロケータの型です。 //! @tparam TSlot スロットの型です。 //--------------------------------------------------------------------------- template< typename TResult, typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename TResultCombiner = LastValueResult, typename TAllocator = os::IAllocator, typename TSlot = Slot6 > class Signal6 { NW_DISALLOW_COPY_AND_ASSIGN(Signal6); public: typedef Signal6 SelfType; typedef TSlot SlotType; typedef TResult ResultType; typedef ut::MoveArray SlotList; typedef TResultCombiner ResultCombinerType; typedef TAllocator AllocatorType; #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED //! @brief スロット実行用関数オブジェクトです。 struct Invoker { Invoker(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5) : m_arg0(arg0), m_arg1(arg1), m_arg2(arg2), m_arg3(arg3), m_arg4(arg4), m_arg5(arg5) {} ResultType operator()(SlotType* slot) const { return slot->Invoke(m_arg0, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5); } TArg0 m_arg0; TArg1 m_arg1; TArg2 m_arg2; TArg3 m_arg3; TArg4 m_arg4; TArg5 m_arg5; }; #endif //---------------------------------------- //! @name 作成/破棄 //@{ //! @brief 無効なシグナルを生成します。 //! //! @param[in] allocator アロケータです。 //! static SelfType* CreateInvalidateSignal(AllocatorType* allocator) { void* memory = allocator->Alloc(sizeof(SelfType)); if (memory) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED return new(memory) SelfType(NULL, 0, allocator); #else return new(memory) SelfType(allocator); #endif } else { return NULL; } } //! @brief 必要なメモリを事前に確保してシグナルを生成します。 //! //! @param[in] maxSlots スロットを追加できる最大数です。 //! @param[in] allocator アロケータです。 //! static SelfType* CreateFixedSizedSignal(size_t maxSlots, AllocatorType* allocator) { void* memory = allocator->Alloc(sizeof(SelfType)); if (memory) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED void* elements = allocator->Alloc(sizeof(SlotType*) * maxSlots); if (elements != NULL) { return new(memory) SelfType(elements, maxSlots, allocator); } else { allocator->Free(memory); return NULL; } #else NW_UNUSED_VARIABLE(maxSlots); return new(memory) SelfType(allocator); #endif } else { return NULL; } } //! @brief 必要になるごとにメモリを確保するシグナルを生成します。 static SelfType* CreateVariableSizeSignal(AllocatorType* allocator) { void* memory = allocator->Alloc(sizeof(SelfType)); if (memory) { return new(memory) SelfType(allocator); } else { return NULL; } } //! オブジェクトを破棄します。 void Destroy() { this->~Signal6(); this->m_Allocator->Free(this); } //@} //---------------------------------------- //! @name スロット //@{ //! @brief スロットと接続し、シグナルが送られるようにする。 //! //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! シグナルに接続できるスロット数は1つになります。 //! //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! Connect する前に必ず Disconnect するようにしてください。 //! Disconnect していない場合は、アサートで停止します。 //! //! @param[in] slot スロットです。 //! void Connect(SlotType* slot) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED bool pushed = this->m_Slots.push_back(slot); NW_ASSERT(pushed); #else NW_ASSERT(this->m_Slot == NULL); this->m_Slot = slot; #endif } //! @brief スロットを作成し、接続します。 //! //! 内部でメモリを確保します。 //! //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! シグナルに接続できるスロット数は1つになります。 //! //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! Connect する前に必ず Disconnect するようにしてください。 //! Disconnect していない場合は、アサートで停止します。 //! //! @tparam TFunction 関数ポインタまたは、関数オブジェクトの型です。 //! //! @param[in] function 関数ポインタまたは、関数オブジェクトです。 //! @param[in] allocator アロケータです。 //! //! @return 生成されたスロットです。 //! template SlotType* CreateAndConnect(TFunction function, AllocatorType* allocator) { typedef FunctionSlot6 FunctionSlotType; FunctionSlotType* slot = CreateSlot(allocator, function); this->Connect(slot); return slot; } //! @brief スロットを作成し、接続します。 //! //! 内部でメモリを確保します。 //! //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! シグナルに接続できるスロット数は1つになります。 //! //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! Connect する前に必ず Disconnect するようにしてください。 //! Disconnect していない場合は、アサートで停止します。 //! //! @tparam TFunction 関数ポインタまたは、関数オブジェクトの型です。 //! //! @param[in] function 関数ポインタまたは、関数オブジェクトです。 //! //! @return 生成されたスロットです。 //! template SlotType* CreateAndConnect(TFunction function) { return CreateAndConnect(function, this->m_Allocator); } //! @brief スロットを切断します。 //! //! @param[in] slot 切断するスロットです。 //! void Disconnect(SlotType* slot) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED this->m_Slots.erase_find(slot); #else if (this->m_Slot == slot) { this->m_Slot = NULL; } #endif } //! @brief スロットを切断して、破棄します。 //! //! 関数オブジェクトにアロケータが設定されていると、オブジェクトを破棄します。 //! アロケータが設定されていないと、登録を解除して破棄は行いません。 //! //! @param[in] slot 切断するスロットです。 //! void DisconnectAndDestroy(SlotType* slot) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED this->m_Slots.erase_find(slot); slot->Destroy(); #else if (this->m_Slot == slot) { this->m_Slot = NULL; } if (slot) { slot->Destroy(); } #endif } //@} //! @brief シグナルを送信します。 ResultType operator()(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED ResultCombinerType combiner; return combiner(m_Slots.begin(), m_Slots.end(), Invoker(arg0, arg1, arg2, arg3, arg4, arg5)); #else if (this->m_Slot) { return this->m_Slot->Invoke(arg0, arg1, arg2, arg3, arg4, arg5); } else { return ResultType(); } #endif } //! @brief CreateInvalidateSignal() の実行に必要なメモリサイズを取得します。 static size_t GetMemorySizeForInvalidateSignal(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) { os::MemorySizeCalculator size(alignment); GetMemorySizeForInvalidateSignalInternal(&size); return size.GetSizeWithPadding(alignment); } //! @details :private static void GetMemorySizeForInvalidateSignalInternal(os::MemorySizeCalculator* pSize) { os::MemorySizeCalculator& size = *pSize; size += sizeof(SelfType); } //! @brief CreateFixedSizedSignal() の実行に必要なメモリサイズを取得します。 //! //! @param[in] maxSlots スロットを追加できる最大数です。 static size_t GetMemorySizeForFixedSizedSignal(size_t maxSlots, size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) { os::MemorySizeCalculator size(alignment); GetMemorySizeForFixedSizedSignalInternal(&size, maxSlots); return size.GetSizeWithPadding(alignment); } //! @details :private static void GetMemorySizeForFixedSizedSignalInternal(os::MemorySizeCalculator* pSize, size_t maxSlots) { os::MemorySizeCalculator& size = *pSize; size += sizeof(SelfType); #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED size += sizeof(SlotType*) * maxSlots; #else NW_UNUSED_VARIABLE(maxSlots); #endif } private: #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED //! @brief コンストラクタです。 Signal6(void* elements, size_t maxSlots, AllocatorType* allocator) : m_Allocator(allocator), m_Slots(elements, maxSlots, allocator) {} //! @brief コンストラクタです。 explicit Signal6(AllocatorType* allocator) : m_Allocator(allocator), m_Slots(allocator) {} //! @brief デストラクタです。 ~Signal6() { DestroyAllSlots(m_Slots); } #else //! @brief コンストラクタです。 explicit Signal6(AllocatorType* allocator) : m_Allocator(allocator), m_Slot(NULL) {} //! @brief デストラクタです。 ~Signal6() { SafeDestroy(this->m_Slot); } #endif AllocatorType* m_Allocator; #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED SlotList m_Slots; #else SlotType* m_Slot; #endif }; //--------------------------------------------------------------------------- //! @brief シグナルを受け取るためのインターフェースです。(引数は 7 個です) //! //! @tparam TResult 返り値の型です。 //! @tparam TAllocator アロケータの型です。 //--------------------------------------------------------------------------- template< typename TResult, typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename TArg6, typename TAllocator = os::IAllocator > class Slot7 { public: typedef TResult ResultType; typedef TAllocator AllocatorType; //! @brief コンストラクタです。 explicit Slot7(AllocatorType* allocator) : m_Allocator(allocator) {} //! @brief 自らを破棄します。 void Destroy() { AllocatorType* allocator = this->GetAllocator(); if (allocator) { this->~Slot7(); allocator->Free(this); } } //! @brief 自らを破棄します。 void Destroy(AllocatorType* allocator) { NW_NULL_ASSERT(allocator); this->~Slot7(); allocator->Free(this); } //! @brief スロットにシグナルを送信します。 virtual ResultType Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6) = 0; AllocatorType* GetAllocator() { return m_Allocator; } protected: //! デストラクタです。 virtual ~Slot7() {} private: AllocatorType* m_Allocator; }; //--------------------------------------------------------------------------- //! @brief シグナルを受け取るためのクラスです。(引数は 7 個です) //! //! @tparam TResult 返り値の型です。 //! @tparam TFunction 関数か関数オブジェクトの型です。 //! @tparam TAllocator アロケータの型です。 //--------------------------------------------------------------------------- template< typename TResult, typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename TArg6, typename TFunction, typename TAllocator = os::IAllocator > class FunctionSlot7 : public Slot7 { public: typedef TResult ResultType; typedef TFunction FunctionType; typedef TAllocator AllocatorType; //! コンストラクタです。 FunctionSlot7(AllocatorType* allocator, FunctionType function) : Slot7(allocator), m_Function(function) {} //! @brief スロットにシグナルを送信します。 virtual ResultType Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6) { return m_Function(arg0, arg1, arg2, arg3, arg4, arg5, arg6); } private: TFunction m_Function; }; //--------------------------------------------------------------------------- //! @brief スロットに合図を送るためのクラスです。(引数は 7 個です) //! //! @tparam TResult 返り値の型です。 //! @tparam TResultCombiner スロットの返り値をまとめて返してくれるコンバイナの型です。 //! @tparam TAllocator アロケータの型です。 //! @tparam TSlot スロットの型です。 //--------------------------------------------------------------------------- template< typename TResult, typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename TArg6, typename TResultCombiner = LastValueResult, typename TAllocator = os::IAllocator, typename TSlot = Slot7 > class Signal7 { NW_DISALLOW_COPY_AND_ASSIGN(Signal7); public: typedef Signal7 SelfType; typedef TSlot SlotType; typedef TResult ResultType; typedef ut::MoveArray SlotList; typedef TResultCombiner ResultCombinerType; typedef TAllocator AllocatorType; #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED //! @brief スロット実行用関数オブジェクトです。 struct Invoker { Invoker(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6) : m_arg0(arg0), m_arg1(arg1), m_arg2(arg2), m_arg3(arg3), m_arg4(arg4), m_arg5(arg5), m_arg6(arg6) {} ResultType operator()(SlotType* slot) const { return slot->Invoke(m_arg0, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6); } TArg0 m_arg0; TArg1 m_arg1; TArg2 m_arg2; TArg3 m_arg3; TArg4 m_arg4; TArg5 m_arg5; TArg6 m_arg6; }; #endif //---------------------------------------- //! @name 作成/破棄 //@{ //! @brief 無効なシグナルを生成します。 //! //! @param[in] allocator アロケータです。 //! static SelfType* CreateInvalidateSignal(AllocatorType* allocator) { void* memory = allocator->Alloc(sizeof(SelfType)); if (memory) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED return new(memory) SelfType(NULL, 0, allocator); #else return new(memory) SelfType(allocator); #endif } else { return NULL; } } //! @brief 必要なメモリを事前に確保してシグナルを生成します。 //! //! @param[in] maxSlots スロットを追加できる最大数です。 //! @param[in] allocator アロケータです。 //! static SelfType* CreateFixedSizedSignal(size_t maxSlots, AllocatorType* allocator) { void* memory = allocator->Alloc(sizeof(SelfType)); if (memory) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED void* elements = allocator->Alloc(sizeof(SlotType*) * maxSlots); if (elements != NULL) { return new(memory) SelfType(elements, maxSlots, allocator); } else { allocator->Free(memory); return NULL; } #else NW_UNUSED_VARIABLE(maxSlots); return new(memory) SelfType(allocator); #endif } else { return NULL; } } //! @brief 必要になるごとにメモリを確保するシグナルを生成します。 static SelfType* CreateVariableSizeSignal(AllocatorType* allocator) { void* memory = allocator->Alloc(sizeof(SelfType)); if (memory) { return new(memory) SelfType(allocator); } else { return NULL; } } //! オブジェクトを破棄します。 void Destroy() { this->~Signal7(); this->m_Allocator->Free(this); } //@} //---------------------------------------- //! @name スロット //@{ //! @brief スロットと接続し、シグナルが送られるようにする。 //! //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! シグナルに接続できるスロット数は1つになります。 //! //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! Connect する前に必ず Disconnect するようにしてください。 //! Disconnect していない場合は、アサートで停止します。 //! //! @param[in] slot スロットです。 //! void Connect(SlotType* slot) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED bool pushed = this->m_Slots.push_back(slot); NW_ASSERT(pushed); #else NW_ASSERT(this->m_Slot == NULL); this->m_Slot = slot; #endif } //! @brief スロットを作成し、接続します。 //! //! 内部でメモリを確保します。 //! //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! シグナルに接続できるスロット数は1つになります。 //! //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! Connect する前に必ず Disconnect するようにしてください。 //! Disconnect していない場合は、アサートで停止します。 //! //! @tparam TFunction 関数ポインタまたは、関数オブジェクトの型です。 //! //! @param[in] function 関数ポインタまたは、関数オブジェクトです。 //! @param[in] allocator アロケータです。 //! //! @return 生成されたスロットです。 //! template SlotType* CreateAndConnect(TFunction function, AllocatorType* allocator) { typedef FunctionSlot7 FunctionSlotType; FunctionSlotType* slot = CreateSlot(allocator, function); this->Connect(slot); return slot; } //! @brief スロットを作成し、接続します。 //! //! 内部でメモリを確保します。 //! //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! シグナルに接続できるスロット数は1つになります。 //! //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! Connect する前に必ず Disconnect するようにしてください。 //! Disconnect していない場合は、アサートで停止します。 //! //! @tparam TFunction 関数ポインタまたは、関数オブジェクトの型です。 //! //! @param[in] function 関数ポインタまたは、関数オブジェクトです。 //! //! @return 生成されたスロットです。 //! template SlotType* CreateAndConnect(TFunction function) { return CreateAndConnect(function, this->m_Allocator); } //! @brief スロットを切断します。 //! //! @param[in] slot 切断するスロットです。 //! void Disconnect(SlotType* slot) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED this->m_Slots.erase_find(slot); #else if (this->m_Slot == slot) { this->m_Slot = NULL; } #endif } //! @brief スロットを切断して、破棄します。 //! //! 関数オブジェクトにアロケータが設定されていると、オブジェクトを破棄します。 //! アロケータが設定されていないと、登録を解除して破棄は行いません。 //! //! @param[in] slot 切断するスロットです。 //! void DisconnectAndDestroy(SlotType* slot) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED this->m_Slots.erase_find(slot); slot->Destroy(); #else if (this->m_Slot == slot) { this->m_Slot = NULL; } if (slot) { slot->Destroy(); } #endif } //@} //! @brief シグナルを送信します。 ResultType operator()(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED ResultCombinerType combiner; return combiner(m_Slots.begin(), m_Slots.end(), Invoker(arg0, arg1, arg2, arg3, arg4, arg5, arg6)); #else if (this->m_Slot) { return this->m_Slot->Invoke(arg0, arg1, arg2, arg3, arg4, arg5, arg6); } else { return ResultType(); } #endif } //! @brief CreateInvalidateSignal() の実行に必要なメモリサイズを取得します。 static size_t GetMemorySizeForInvalidateSignal(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) { os::MemorySizeCalculator size(alignment); GetMemorySizeForInvalidateSignalInternal(&size); return size.GetSizeWithPadding(alignment); } //! @details :private static void GetMemorySizeForInvalidateSignalInternal(os::MemorySizeCalculator* pSize) { os::MemorySizeCalculator& size = *pSize; size += sizeof(SelfType); } //! @brief CreateFixedSizedSignal() の実行に必要なメモリサイズを取得します。 //! //! @param[in] maxSlots スロットを追加できる最大数です。 static size_t GetMemorySizeForFixedSizedSignal(size_t maxSlots, size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) { os::MemorySizeCalculator size(alignment); GetMemorySizeForFixedSizedSignalInternal(&size, maxSlots); return size.GetSizeWithPadding(alignment); } //! @details :private static void GetMemorySizeForFixedSizedSignalInternal(os::MemorySizeCalculator* pSize, size_t maxSlots) { os::MemorySizeCalculator& size = *pSize; size += sizeof(SelfType); #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED size += sizeof(SlotType*) * maxSlots; #else NW_UNUSED_VARIABLE(maxSlots); #endif } private: #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED //! @brief コンストラクタです。 Signal7(void* elements, size_t maxSlots, AllocatorType* allocator) : m_Allocator(allocator), m_Slots(elements, maxSlots, allocator) {} //! @brief コンストラクタです。 explicit Signal7(AllocatorType* allocator) : m_Allocator(allocator), m_Slots(allocator) {} //! @brief デストラクタです。 ~Signal7() { DestroyAllSlots(m_Slots); } #else //! @brief コンストラクタです。 explicit Signal7(AllocatorType* allocator) : m_Allocator(allocator), m_Slot(NULL) {} //! @brief デストラクタです。 ~Signal7() { SafeDestroy(this->m_Slot); } #endif AllocatorType* m_Allocator; #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED SlotList m_Slots; #else SlotType* m_Slot; #endif }; //--------------------------------------------------------------------------- //! @brief シグナルを受け取るためのインターフェースです。(引数は 8 個です) //! //! @tparam TResult 返り値の型です。 //! @tparam TAllocator アロケータの型です。 //--------------------------------------------------------------------------- template< typename TResult, typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename TArg6, typename TArg7, typename TAllocator = os::IAllocator > class Slot8 { public: typedef TResult ResultType; typedef TAllocator AllocatorType; //! @brief コンストラクタです。 explicit Slot8(AllocatorType* allocator) : m_Allocator(allocator) {} //! @brief 自らを破棄します。 void Destroy() { AllocatorType* allocator = this->GetAllocator(); if (allocator) { this->~Slot8(); allocator->Free(this); } } //! @brief 自らを破棄します。 void Destroy(AllocatorType* allocator) { NW_NULL_ASSERT(allocator); this->~Slot8(); allocator->Free(this); } //! @brief スロットにシグナルを送信します。 virtual ResultType Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6, TArg7 arg7) = 0; AllocatorType* GetAllocator() { return m_Allocator; } protected: //! デストラクタです。 virtual ~Slot8() {} private: AllocatorType* m_Allocator; }; //--------------------------------------------------------------------------- //! @brief シグナルを受け取るためのクラスです。(引数は 8 個です) //! //! @tparam TResult 返り値の型です。 //! @tparam TFunction 関数か関数オブジェクトの型です。 //! @tparam TAllocator アロケータの型です。 //--------------------------------------------------------------------------- template< typename TResult, typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename TArg6, typename TArg7, typename TFunction, typename TAllocator = os::IAllocator > class FunctionSlot8 : public Slot8 { public: typedef TResult ResultType; typedef TFunction FunctionType; typedef TAllocator AllocatorType; //! コンストラクタです。 FunctionSlot8(AllocatorType* allocator, FunctionType function) : Slot8(allocator), m_Function(function) {} //! @brief スロットにシグナルを送信します。 virtual ResultType Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6, TArg7 arg7) { return m_Function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); } private: TFunction m_Function; }; //--------------------------------------------------------------------------- //! @brief スロットに合図を送るためのクラスです。(引数は 8 個です) //! //! @tparam TResult 返り値の型です。 //! @tparam TResultCombiner スロットの返り値をまとめて返してくれるコンバイナの型です。 //! @tparam TAllocator アロケータの型です。 //! @tparam TSlot スロットの型です。 //--------------------------------------------------------------------------- template< typename TResult, typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename TArg6, typename TArg7, typename TResultCombiner = LastValueResult, typename TAllocator = os::IAllocator, typename TSlot = Slot8 > class Signal8 { NW_DISALLOW_COPY_AND_ASSIGN(Signal8); public: typedef Signal8 SelfType; typedef TSlot SlotType; typedef TResult ResultType; typedef ut::MoveArray SlotList; typedef TResultCombiner ResultCombinerType; typedef TAllocator AllocatorType; #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED //! @brief スロット実行用関数オブジェクトです。 struct Invoker { Invoker(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6, TArg7 arg7) : m_arg0(arg0), m_arg1(arg1), m_arg2(arg2), m_arg3(arg3), m_arg4(arg4), m_arg5(arg5), m_arg6(arg6), m_arg7(arg7) {} ResultType operator()(SlotType* slot) const { return slot->Invoke(m_arg0, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7); } TArg0 m_arg0; TArg1 m_arg1; TArg2 m_arg2; TArg3 m_arg3; TArg4 m_arg4; TArg5 m_arg5; TArg6 m_arg6; TArg7 m_arg7; }; #endif //---------------------------------------- //! @name 作成/破棄 //@{ //! @brief 無効なシグナルを生成します。 //! //! @param[in] allocator アロケータです。 //! static SelfType* CreateInvalidateSignal(AllocatorType* allocator) { void* memory = allocator->Alloc(sizeof(SelfType)); if (memory) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED return new(memory) SelfType(NULL, 0, allocator); #else return new(memory) SelfType(allocator); #endif } else { return NULL; } } //! @brief 必要なメモリを事前に確保してシグナルを生成します。 //! //! @param[in] maxSlots スロットを追加できる最大数です。 //! @param[in] allocator アロケータです。 //! static SelfType* CreateFixedSizedSignal(size_t maxSlots, AllocatorType* allocator) { void* memory = allocator->Alloc(sizeof(SelfType)); if (memory) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED void* elements = allocator->Alloc(sizeof(SlotType*) * maxSlots); if (elements != NULL) { return new(memory) SelfType(elements, maxSlots, allocator); } else { allocator->Free(memory); return NULL; } #else NW_UNUSED_VARIABLE(maxSlots); return new(memory) SelfType(allocator); #endif } else { return NULL; } } //! @brief 必要になるごとにメモリを確保するシグナルを生成します。 static SelfType* CreateVariableSizeSignal(AllocatorType* allocator) { void* memory = allocator->Alloc(sizeof(SelfType)); if (memory) { return new(memory) SelfType(allocator); } else { return NULL; } } //! オブジェクトを破棄します。 void Destroy() { this->~Signal8(); this->m_Allocator->Free(this); } //@} //---------------------------------------- //! @name スロット //@{ //! @brief スロットと接続し、シグナルが送られるようにする。 //! //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! シグナルに接続できるスロット数は1つになります。 //! //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! Connect する前に必ず Disconnect するようにしてください。 //! Disconnect していない場合は、アサートで停止します。 //! //! @param[in] slot スロットです。 //! void Connect(SlotType* slot) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED bool pushed = this->m_Slots.push_back(slot); NW_ASSERT(pushed); #else NW_ASSERT(this->m_Slot == NULL); this->m_Slot = slot; #endif } //! @brief スロットを作成し、接続します。 //! //! 内部でメモリを確保します。 //! //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! シグナルに接続できるスロット数は1つになります。 //! //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! Connect する前に必ず Disconnect するようにしてください。 //! Disconnect していない場合は、アサートで停止します。 //! //! @tparam TFunction 関数ポインタまたは、関数オブジェクトの型です。 //! //! @param[in] function 関数ポインタまたは、関数オブジェクトです。 //! @param[in] allocator アロケータです。 //! //! @return 生成されたスロットです。 //! template SlotType* CreateAndConnect(TFunction function, AllocatorType* allocator) { typedef FunctionSlot8 FunctionSlotType; FunctionSlotType* slot = CreateSlot(allocator, function); this->Connect(slot); return slot; } //! @brief スロットを作成し、接続します。 //! //! 内部でメモリを確保します。 //! //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! シグナルに接続できるスロット数は1つになります。 //! //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! Connect する前に必ず Disconnect するようにしてください。 //! Disconnect していない場合は、アサートで停止します。 //! //! @tparam TFunction 関数ポインタまたは、関数オブジェクトの型です。 //! //! @param[in] function 関数ポインタまたは、関数オブジェクトです。 //! //! @return 生成されたスロットです。 //! template SlotType* CreateAndConnect(TFunction function) { return CreateAndConnect(function, this->m_Allocator); } //! @brief スロットを切断します。 //! //! @param[in] slot 切断するスロットです。 //! void Disconnect(SlotType* slot) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED this->m_Slots.erase_find(slot); #else if (this->m_Slot == slot) { this->m_Slot = NULL; } #endif } //! @brief スロットを切断して、破棄します。 //! //! 関数オブジェクトにアロケータが設定されていると、オブジェクトを破棄します。 //! アロケータが設定されていないと、登録を解除して破棄は行いません。 //! //! @param[in] slot 切断するスロットです。 //! void DisconnectAndDestroy(SlotType* slot) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED this->m_Slots.erase_find(slot); slot->Destroy(); #else if (this->m_Slot == slot) { this->m_Slot = NULL; } if (slot) { slot->Destroy(); } #endif } //@} //! @brief シグナルを送信します。 ResultType operator()(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6, TArg7 arg7) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED ResultCombinerType combiner; return combiner(m_Slots.begin(), m_Slots.end(), Invoker(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7)); #else if (this->m_Slot) { return this->m_Slot->Invoke(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); } else { return ResultType(); } #endif } //! @brief CreateInvalidateSignal() の実行に必要なメモリサイズを取得します。 static size_t GetMemorySizeForInvalidateSignal(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) { os::MemorySizeCalculator size(alignment); GetMemorySizeForInvalidateSignalInternal(&size); return size.GetSizeWithPadding(alignment); } //! @details :private static void GetMemorySizeForInvalidateSignalInternal(os::MemorySizeCalculator* pSize) { os::MemorySizeCalculator& size = *pSize; size += sizeof(SelfType); } //! @brief CreateFixedSizedSignal() の実行に必要なメモリサイズを取得します。 //! //! @param[in] maxSlots スロットを追加できる最大数です。 static size_t GetMemorySizeForFixedSizedSignal(size_t maxSlots, size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) { os::MemorySizeCalculator size(alignment); GetMemorySizeForFixedSizedSignalInternal(&size, maxSlots); return size.GetSizeWithPadding(alignment); } //! @details :private static void GetMemorySizeForFixedSizedSignalInternal(os::MemorySizeCalculator* pSize, size_t maxSlots) { os::MemorySizeCalculator& size = *pSize; size += sizeof(SelfType); #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED size += sizeof(SlotType*) * maxSlots; #else NW_UNUSED_VARIABLE(maxSlots); #endif } private: #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED //! @brief コンストラクタです。 Signal8(void* elements, size_t maxSlots, AllocatorType* allocator) : m_Allocator(allocator), m_Slots(elements, maxSlots, allocator) {} //! @brief コンストラクタです。 explicit Signal8(AllocatorType* allocator) : m_Allocator(allocator), m_Slots(allocator) {} //! @brief デストラクタです。 ~Signal8() { DestroyAllSlots(m_Slots); } #else //! @brief コンストラクタです。 explicit Signal8(AllocatorType* allocator) : m_Allocator(allocator), m_Slot(NULL) {} //! @brief デストラクタです。 ~Signal8() { SafeDestroy(this->m_Slot); } #endif AllocatorType* m_Allocator; #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED SlotList m_Slots; #else SlotType* m_Slot; #endif }; //--------------------------------------------------------------------------- //! @brief シグナルを受け取るためのインターフェースです。(引数は 9 個です) //! //! @tparam TResult 返り値の型です。 //! @tparam TAllocator アロケータの型です。 //--------------------------------------------------------------------------- template< typename TResult, typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename TArg6, typename TArg7, typename TArg8, typename TAllocator = os::IAllocator > class Slot9 { public: typedef TResult ResultType; typedef TAllocator AllocatorType; //! @brief コンストラクタです。 explicit Slot9(AllocatorType* allocator) : m_Allocator(allocator) {} //! @brief 自らを破棄します。 void Destroy() { AllocatorType* allocator = this->GetAllocator(); if (allocator) { this->~Slot9(); allocator->Free(this); } } //! @brief 自らを破棄します。 void Destroy(AllocatorType* allocator) { NW_NULL_ASSERT(allocator); this->~Slot9(); allocator->Free(this); } //! @brief スロットにシグナルを送信します。 virtual ResultType Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6, TArg7 arg7, TArg8 arg8) = 0; AllocatorType* GetAllocator() { return m_Allocator; } protected: //! デストラクタです。 virtual ~Slot9() {} private: AllocatorType* m_Allocator; }; //--------------------------------------------------------------------------- //! @brief シグナルを受け取るためのクラスです。(引数は 9 個です) //! //! @tparam TResult 返り値の型です。 //! @tparam TFunction 関数か関数オブジェクトの型です。 //! @tparam TAllocator アロケータの型です。 //--------------------------------------------------------------------------- template< typename TResult, typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename TArg6, typename TArg7, typename TArg8, typename TFunction, typename TAllocator = os::IAllocator > class FunctionSlot9 : public Slot9 { public: typedef TResult ResultType; typedef TFunction FunctionType; typedef TAllocator AllocatorType; //! コンストラクタです。 FunctionSlot9(AllocatorType* allocator, FunctionType function) : Slot9(allocator), m_Function(function) {} //! @brief スロットにシグナルを送信します。 virtual ResultType Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6, TArg7 arg7, TArg8 arg8) { return m_Function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); } private: TFunction m_Function; }; //--------------------------------------------------------------------------- //! @brief スロットに合図を送るためのクラスです。(引数は 9 個です) //! //! @tparam TResult 返り値の型です。 //! @tparam TResultCombiner スロットの返り値をまとめて返してくれるコンバイナの型です。 //! @tparam TAllocator アロケータの型です。 //! @tparam TSlot スロットの型です。 //--------------------------------------------------------------------------- template< typename TResult, typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename TArg6, typename TArg7, typename TArg8, typename TResultCombiner = LastValueResult, typename TAllocator = os::IAllocator, typename TSlot = Slot9 > class Signal9 { NW_DISALLOW_COPY_AND_ASSIGN(Signal9); public: typedef Signal9 SelfType; typedef TSlot SlotType; typedef TResult ResultType; typedef ut::MoveArray SlotList; typedef TResultCombiner ResultCombinerType; typedef TAllocator AllocatorType; #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED //! @brief スロット実行用関数オブジェクトです。 struct Invoker { Invoker(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6, TArg7 arg7, TArg8 arg8) : m_arg0(arg0), m_arg1(arg1), m_arg2(arg2), m_arg3(arg3), m_arg4(arg4), m_arg5(arg5), m_arg6(arg6), m_arg7(arg7), m_arg8(arg8) {} ResultType operator()(SlotType* slot) const { return slot->Invoke(m_arg0, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8); } TArg0 m_arg0; TArg1 m_arg1; TArg2 m_arg2; TArg3 m_arg3; TArg4 m_arg4; TArg5 m_arg5; TArg6 m_arg6; TArg7 m_arg7; TArg8 m_arg8; }; #endif //---------------------------------------- //! @name 作成/破棄 //@{ //! @brief 無効なシグナルを生成します。 //! //! @param[in] allocator アロケータです。 //! static SelfType* CreateInvalidateSignal(AllocatorType* allocator) { void* memory = allocator->Alloc(sizeof(SelfType)); if (memory) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED return new(memory) SelfType(NULL, 0, allocator); #else return new(memory) SelfType(allocator); #endif } else { return NULL; } } //! @brief 必要なメモリを事前に確保してシグナルを生成します。 //! //! @param[in] maxSlots スロットを追加できる最大数です。 //! @param[in] allocator アロケータです。 //! static SelfType* CreateFixedSizedSignal(size_t maxSlots, AllocatorType* allocator) { void* memory = allocator->Alloc(sizeof(SelfType)); if (memory) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED void* elements = allocator->Alloc(sizeof(SlotType*) * maxSlots); if (elements != NULL) { return new(memory) SelfType(elements, maxSlots, allocator); } else { allocator->Free(memory); return NULL; } #else NW_UNUSED_VARIABLE(maxSlots); return new(memory) SelfType(allocator); #endif } else { return NULL; } } //! @brief 必要になるごとにメモリを確保するシグナルを生成します。 static SelfType* CreateVariableSizeSignal(AllocatorType* allocator) { void* memory = allocator->Alloc(sizeof(SelfType)); if (memory) { return new(memory) SelfType(allocator); } else { return NULL; } } //! オブジェクトを破棄します。 void Destroy() { this->~Signal9(); this->m_Allocator->Free(this); } //@} //---------------------------------------- //! @name スロット //@{ //! @brief スロットと接続し、シグナルが送られるようにする。 //! //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! シグナルに接続できるスロット数は1つになります。 //! //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! Connect する前に必ず Disconnect するようにしてください。 //! Disconnect していない場合は、アサートで停止します。 //! //! @param[in] slot スロットです。 //! void Connect(SlotType* slot) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED bool pushed = this->m_Slots.push_back(slot); NW_ASSERT(pushed); #else NW_ASSERT(this->m_Slot == NULL); this->m_Slot = slot; #endif } //! @brief スロットを作成し、接続します。 //! //! 内部でメモリを確保します。 //! //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! シグナルに接続できるスロット数は1つになります。 //! //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! Connect する前に必ず Disconnect するようにしてください。 //! Disconnect していない場合は、アサートで停止します。 //! //! @tparam TFunction 関数ポインタまたは、関数オブジェクトの型です。 //! //! @param[in] function 関数ポインタまたは、関数オブジェクトです。 //! @param[in] allocator アロケータです。 //! //! @return 生成されたスロットです。 //! template SlotType* CreateAndConnect(TFunction function, AllocatorType* allocator) { typedef FunctionSlot9 FunctionSlotType; FunctionSlotType* slot = CreateSlot(allocator, function); this->Connect(slot); return slot; } //! @brief スロットを作成し、接続します。 //! //! 内部でメモリを確保します。 //! //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! シグナルに接続できるスロット数は1つになります。 //! //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! Connect する前に必ず Disconnect するようにしてください。 //! Disconnect していない場合は、アサートで停止します。 //! //! @tparam TFunction 関数ポインタまたは、関数オブジェクトの型です。 //! //! @param[in] function 関数ポインタまたは、関数オブジェクトです。 //! //! @return 生成されたスロットです。 //! template SlotType* CreateAndConnect(TFunction function) { return CreateAndConnect(function, this->m_Allocator); } //! @brief スロットを切断します。 //! //! @param[in] slot 切断するスロットです。 //! void Disconnect(SlotType* slot) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED this->m_Slots.erase_find(slot); #else if (this->m_Slot == slot) { this->m_Slot = NULL; } #endif } //! @brief スロットを切断して、破棄します。 //! //! 関数オブジェクトにアロケータが設定されていると、オブジェクトを破棄します。 //! アロケータが設定されていないと、登録を解除して破棄は行いません。 //! //! @param[in] slot 切断するスロットです。 //! void DisconnectAndDestroy(SlotType* slot) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED this->m_Slots.erase_find(slot); slot->Destroy(); #else if (this->m_Slot == slot) { this->m_Slot = NULL; } if (slot) { slot->Destroy(); } #endif } //@} //! @brief シグナルを送信します。 ResultType operator()(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6, TArg7 arg7, TArg8 arg8) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED ResultCombinerType combiner; return combiner(m_Slots.begin(), m_Slots.end(), Invoker(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)); #else if (this->m_Slot) { return this->m_Slot->Invoke(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); } else { return ResultType(); } #endif } //! @brief CreateInvalidateSignal() の実行に必要なメモリサイズを取得します。 static size_t GetMemorySizeForInvalidateSignal(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) { os::MemorySizeCalculator size(alignment); GetMemorySizeForInvalidateSignalInternal(&size); return size.GetSizeWithPadding(alignment); } //! @details :private static void GetMemorySizeForInvalidateSignalInternal(os::MemorySizeCalculator* pSize) { os::MemorySizeCalculator& size = *pSize; size += sizeof(SelfType); } //! @brief CreateFixedSizedSignal() の実行に必要なメモリサイズを取得します。 //! //! @param[in] maxSlots スロットを追加できる最大数です。 static size_t GetMemorySizeForFixedSizedSignal(size_t maxSlots, size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) { os::MemorySizeCalculator size(alignment); GetMemorySizeForFixedSizedSignalInternal(&size, maxSlots); return size.GetSizeWithPadding(alignment); } //! @details :private static void GetMemorySizeForFixedSizedSignalInternal(os::MemorySizeCalculator* pSize, size_t maxSlots) { os::MemorySizeCalculator& size = *pSize; size += sizeof(SelfType); #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED size += sizeof(SlotType*) * maxSlots; #else NW_UNUSED_VARIABLE(maxSlots); #endif } private: #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED //! @brief コンストラクタです。 Signal9(void* elements, size_t maxSlots, AllocatorType* allocator) : m_Allocator(allocator), m_Slots(elements, maxSlots, allocator) {} //! @brief コンストラクタです。 explicit Signal9(AllocatorType* allocator) : m_Allocator(allocator), m_Slots(allocator) {} //! @brief デストラクタです。 ~Signal9() { DestroyAllSlots(m_Slots); } #else //! @brief コンストラクタです。 explicit Signal9(AllocatorType* allocator) : m_Allocator(allocator), m_Slot(NULL) {} //! @brief デストラクタです。 ~Signal9() { SafeDestroy(this->m_Slot); } #endif AllocatorType* m_Allocator; #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED SlotList m_Slots; #else SlotType* m_Slot; #endif }; //--------------------------------------------------------------------------- //! @brief シグナルを受け取るためのインターフェースです。(引数は 10 個です) //! //! @tparam TResult 返り値の型です。 //! @tparam TAllocator アロケータの型です。 //--------------------------------------------------------------------------- template< typename TResult, typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename TArg6, typename TArg7, typename TArg8, typename TArg9, typename TAllocator = os::IAllocator > class Slot10 { public: typedef TResult ResultType; typedef TAllocator AllocatorType; //! @brief コンストラクタです。 explicit Slot10(AllocatorType* allocator) : m_Allocator(allocator) {} //! @brief 自らを破棄します。 void Destroy() { AllocatorType* allocator = this->GetAllocator(); if (allocator) { this->~Slot10(); allocator->Free(this); } } //! @brief 自らを破棄します。 void Destroy(AllocatorType* allocator) { NW_NULL_ASSERT(allocator); this->~Slot10(); allocator->Free(this); } //! @brief スロットにシグナルを送信します。 virtual ResultType Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6, TArg7 arg7, TArg8 arg8, TArg9 arg9) = 0; AllocatorType* GetAllocator() { return m_Allocator; } protected: //! デストラクタです。 virtual ~Slot10() {} private: AllocatorType* m_Allocator; }; //--------------------------------------------------------------------------- //! @brief シグナルを受け取るためのクラスです。(引数は 10 個です) //! //! @tparam TResult 返り値の型です。 //! @tparam TFunction 関数か関数オブジェクトの型です。 //! @tparam TAllocator アロケータの型です。 //--------------------------------------------------------------------------- template< typename TResult, typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename TArg6, typename TArg7, typename TArg8, typename TArg9, typename TFunction, typename TAllocator = os::IAllocator > class FunctionSlot10 : public Slot10 { public: typedef TResult ResultType; typedef TFunction FunctionType; typedef TAllocator AllocatorType; //! コンストラクタです。 FunctionSlot10(AllocatorType* allocator, FunctionType function) : Slot10(allocator), m_Function(function) {} //! @brief スロットにシグナルを送信します。 virtual ResultType Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6, TArg7 arg7, TArg8 arg8, TArg9 arg9) { return m_Function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); } private: TFunction m_Function; }; //--------------------------------------------------------------------------- //! @brief スロットに合図を送るためのクラスです。(引数は 10 個です) //! //! @tparam TResult 返り値の型です。 //! @tparam TResultCombiner スロットの返り値をまとめて返してくれるコンバイナの型です。 //! @tparam TAllocator アロケータの型です。 //! @tparam TSlot スロットの型です。 //--------------------------------------------------------------------------- template< typename TResult, typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename TArg6, typename TArg7, typename TArg8, typename TArg9, typename TResultCombiner = LastValueResult, typename TAllocator = os::IAllocator, typename TSlot = Slot10 > class Signal10 { NW_DISALLOW_COPY_AND_ASSIGN(Signal10); public: typedef Signal10 SelfType; typedef TSlot SlotType; typedef TResult ResultType; typedef ut::MoveArray SlotList; typedef TResultCombiner ResultCombinerType; typedef TAllocator AllocatorType; #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED //! @brief スロット実行用関数オブジェクトです。 struct Invoker { Invoker(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6, TArg7 arg7, TArg8 arg8, TArg9 arg9) : m_arg0(arg0), m_arg1(arg1), m_arg2(arg2), m_arg3(arg3), m_arg4(arg4), m_arg5(arg5), m_arg6(arg6), m_arg7(arg7), m_arg8(arg8), m_arg9(arg9) {} ResultType operator()(SlotType* slot) const { return slot->Invoke(m_arg0, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9); } TArg0 m_arg0; TArg1 m_arg1; TArg2 m_arg2; TArg3 m_arg3; TArg4 m_arg4; TArg5 m_arg5; TArg6 m_arg6; TArg7 m_arg7; TArg8 m_arg8; TArg9 m_arg9; }; #endif //---------------------------------------- //! @name 作成/破棄 //@{ //! @brief 無効なシグナルを生成します。 //! //! @param[in] allocator アロケータです。 //! static SelfType* CreateInvalidateSignal(AllocatorType* allocator) { void* memory = allocator->Alloc(sizeof(SelfType)); if (memory) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED return new(memory) SelfType(NULL, 0, allocator); #else return new(memory) SelfType(allocator); #endif } else { return NULL; } } //! @brief 必要なメモリを事前に確保してシグナルを生成します。 //! //! @param[in] maxSlots スロットを追加できる最大数です。 //! @param[in] allocator アロケータです。 //! static SelfType* CreateFixedSizedSignal(size_t maxSlots, AllocatorType* allocator) { void* memory = allocator->Alloc(sizeof(SelfType)); if (memory) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED void* elements = allocator->Alloc(sizeof(SlotType*) * maxSlots); if (elements != NULL) { return new(memory) SelfType(elements, maxSlots, allocator); } else { allocator->Free(memory); return NULL; } #else NW_UNUSED_VARIABLE(maxSlots); return new(memory) SelfType(allocator); #endif } else { return NULL; } } //! @brief 必要になるごとにメモリを確保するシグナルを生成します。 static SelfType* CreateVariableSizeSignal(AllocatorType* allocator) { void* memory = allocator->Alloc(sizeof(SelfType)); if (memory) { return new(memory) SelfType(allocator); } else { return NULL; } } //! オブジェクトを破棄します。 void Destroy() { this->~Signal10(); this->m_Allocator->Free(this); } //@} //---------------------------------------- //! @name スロット //@{ //! @brief スロットと接続し、シグナルが送られるようにする。 //! //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! シグナルに接続できるスロット数は1つになります。 //! //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! Connect する前に必ず Disconnect するようにしてください。 //! Disconnect していない場合は、アサートで停止します。 //! //! @param[in] slot スロットです。 //! void Connect(SlotType* slot) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED bool pushed = this->m_Slots.push_back(slot); NW_ASSERT(pushed); #else NW_ASSERT(this->m_Slot == NULL); this->m_Slot = slot; #endif } //! @brief スロットを作成し、接続します。 //! //! 内部でメモリを確保します。 //! //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! シグナルに接続できるスロット数は1つになります。 //! //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! Connect する前に必ず Disconnect するようにしてください。 //! Disconnect していない場合は、アサートで停止します。 //! //! @tparam TFunction 関数ポインタまたは、関数オブジェクトの型です。 //! //! @param[in] function 関数ポインタまたは、関数オブジェクトです。 //! @param[in] allocator アロケータです。 //! //! @return 生成されたスロットです。 //! template SlotType* CreateAndConnect(TFunction function, AllocatorType* allocator) { typedef FunctionSlot10 FunctionSlotType; FunctionSlotType* slot = CreateSlot(allocator, function); this->Connect(slot); return slot; } //! @brief スロットを作成し、接続します。 //! //! 内部でメモリを確保します。 //! //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! シグナルに接続できるスロット数は1つになります。 //! //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、 //! Connect する前に必ず Disconnect するようにしてください。 //! Disconnect していない場合は、アサートで停止します。 //! //! @tparam TFunction 関数ポインタまたは、関数オブジェクトの型です。 //! //! @param[in] function 関数ポインタまたは、関数オブジェクトです。 //! //! @return 生成されたスロットです。 //! template SlotType* CreateAndConnect(TFunction function) { return CreateAndConnect(function, this->m_Allocator); } //! @brief スロットを切断します。 //! //! @param[in] slot 切断するスロットです。 //! void Disconnect(SlotType* slot) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED this->m_Slots.erase_find(slot); #else if (this->m_Slot == slot) { this->m_Slot = NULL; } #endif } //! @brief スロットを切断して、破棄します。 //! //! 関数オブジェクトにアロケータが設定されていると、オブジェクトを破棄します。 //! アロケータが設定されていないと、登録を解除して破棄は行いません。 //! //! @param[in] slot 切断するスロットです。 //! void DisconnectAndDestroy(SlotType* slot) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED this->m_Slots.erase_find(slot); slot->Destroy(); #else if (this->m_Slot == slot) { this->m_Slot = NULL; } if (slot) { slot->Destroy(); } #endif } //@} //! @brief シグナルを送信します。 ResultType operator()(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6, TArg7 arg7, TArg8 arg8, TArg9 arg9) { #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED ResultCombinerType combiner; return combiner(m_Slots.begin(), m_Slots.end(), Invoker(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)); #else if (this->m_Slot) { return this->m_Slot->Invoke(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); } else { return ResultType(); } #endif } //! @brief CreateInvalidateSignal() の実行に必要なメモリサイズを取得します。 static size_t GetMemorySizeForInvalidateSignal(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) { os::MemorySizeCalculator size(alignment); GetMemorySizeForInvalidateSignalInternal(&size); return size.GetSizeWithPadding(alignment); } //! @details :private static void GetMemorySizeForInvalidateSignalInternal(os::MemorySizeCalculator* pSize) { os::MemorySizeCalculator& size = *pSize; size += sizeof(SelfType); } //! @brief CreateFixedSizedSignal() の実行に必要なメモリサイズを取得します。 //! //! @param[in] maxSlots スロットを追加できる最大数です。 static size_t GetMemorySizeForFixedSizedSignal(size_t maxSlots, size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) { os::MemorySizeCalculator size(alignment); GetMemorySizeForFixedSizedSignalInternal(&size, maxSlots); return size.GetSizeWithPadding(alignment); } //! @details :private static void GetMemorySizeForFixedSizedSignalInternal(os::MemorySizeCalculator* pSize, size_t maxSlots) { os::MemorySizeCalculator& size = *pSize; size += sizeof(SelfType); #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED size += sizeof(SlotType*) * maxSlots; #else NW_UNUSED_VARIABLE(maxSlots); #endif } private: #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED //! @brief コンストラクタです。 Signal10(void* elements, size_t maxSlots, AllocatorType* allocator) : m_Allocator(allocator), m_Slots(elements, maxSlots, allocator) {} //! @brief コンストラクタです。 explicit Signal10(AllocatorType* allocator) : m_Allocator(allocator), m_Slots(allocator) {} //! @brief デストラクタです。 ~Signal10() { DestroyAllSlots(m_Slots); } #else //! @brief コンストラクタです。 explicit Signal10(AllocatorType* allocator) : m_Allocator(allocator), m_Slot(NULL) {} //! @brief デストラクタです。 ~Signal10() { SafeDestroy(this->m_Slot); } #endif AllocatorType* m_Allocator; #ifdef NW_SIGNAL_MULTI_SLOT_ENABLED SlotList m_Slots; #else SlotType* m_Slot; #endif };