1/*---------------------------------------------------------------------------*
2  Project:  NintendoWare
3  File:     ut_Signal.ih
4
5  Copyright (C)2010 Nintendo Co., Ltd./HAL Laboratory, Inc.  All rights reserved.
6
7  These coded instructions, statements, and computer programs contain
8  proprietary information of Nintendo of America Inc. and/or Nintendo
9  Company Ltd., and are protected by Federal copyright law.  They may
10  not be disclosed to third parties or copied or duplicated in any form,
11  in whole or in part, without the prior written consent of Nintendo.
12
13  - Auto generated code -
14 *---------------------------------------------------------------------------*/
15
16//---------------------------------------------------------------------------
17//! @brief        シグナルを受け取るためのインターフェースです。(引数は 0 個です)
18//!
19//! @tparam       TResult 返り値の型です。
20//! @tparam       TAllocator アロケータの型です。
21//---------------------------------------------------------------------------
22template<
23    typename TResult,
24    typename TAllocator = os::IAllocator
25>
26class Slot0
27{
28public:
29    typedef TResult ResultType;
30    typedef TAllocator AllocatorType;
31
32    //! @brief コンストラクタです。
33    explicit Slot0(AllocatorType* allocator) : m_Allocator(allocator) {}
34
35    //! @brief 自らを破棄します。
36    void Destroy()
37    {
38        AllocatorType* allocator = this->GetAllocator();
39        if (allocator)
40        {
41            this->~Slot0();
42            allocator->Free(this);
43        }
44    }
45
46    //! @brief 自らを破棄します。
47    void Destroy(AllocatorType* allocator)
48    {
49        NW_NULL_ASSERT(allocator);
50        this->~Slot0();
51        allocator->Free(this);
52    }
53
54    //! @brief スロットにシグナルを送信します。
55    virtual ResultType Invoke() = 0;
56
57    AllocatorType* GetAllocator() { return m_Allocator; }
58
59protected:
60    //! デストラクタです。
61    virtual ~Slot0() {}
62
63private:
64    AllocatorType* m_Allocator;
65};
66
67//---------------------------------------------------------------------------
68//! @brief        シグナルを受け取るためのクラスです。(引数は 0 個です)
69//!
70//! @tparam       TResult 返り値の型です。
71//! @tparam       TFunction 関数か関数オブジェクトの型です。
72//! @tparam       TAllocator アロケータの型です。
73//---------------------------------------------------------------------------
74template<
75    typename TResult,
76    typename TFunction,
77    typename TAllocator = os::IAllocator
78>
79class FunctionSlot0 : public Slot0<TResult, TAllocator>
80{
81public:
82    typedef TResult ResultType;
83    typedef TFunction FunctionType;
84    typedef TAllocator AllocatorType;
85
86    //! コンストラクタです。
87    FunctionSlot0(AllocatorType* allocator, FunctionType function)
88    : Slot0<TResult, TAllocator>(allocator), m_Function(function) {}
89
90    //! @brief スロットにシグナルを送信します。
91    virtual ResultType Invoke()
92    {
93        return m_Function();
94    }
95
96private:
97    TFunction m_Function;
98};
99
100//---------------------------------------------------------------------------
101//! @brief        スロットに合図を送るためのクラスです。(引数は 0 個です)
102//!
103//! @tparam       TResult 返り値の型です。
104//! @tparam       TResultCombiner スロットの返り値をまとめて返してくれるコンバイナの型です。
105//! @tparam       TAllocator アロケータの型です。
106//! @tparam       TSlot スロットの型です。
107//---------------------------------------------------------------------------
108template<
109    typename TResult,
110    typename TResultCombiner = LastValueResult<TResult>,
111    typename TAllocator = os::IAllocator,
112    typename TSlot = Slot0<TResult, TAllocator>
113>
114class Signal0
115{
116    NW_DISALLOW_COPY_AND_ASSIGN(Signal0);
117
118public:
119    typedef Signal0<TResult, TResultCombiner, TAllocator, TSlot> SelfType;
120    typedef TSlot SlotType;
121    typedef TResult ResultType;
122    typedef ut::MoveArray<SlotType*> SlotList;
123    typedef TResultCombiner ResultCombinerType;
124    typedef TAllocator AllocatorType;
125
126#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
127    //! @brief スロット実行用関数オブジェクトです。
128    struct Invoker
129    {
130        Invoker() {}
131        ResultType operator()(SlotType* slot) const
132        {
133            return slot->Invoke();
134        }
135        ;
136    };
137#endif
138
139    //----------------------------------------
140    //! @name 作成/破棄
141    //@{
142
143    //! @brief        無効なシグナルを生成します。
144    //!
145    //! @param[in]    allocator アロケータです。
146    //!
147    static SelfType* CreateInvalidateSignal(AllocatorType* allocator)
148    {
149        void* memory = allocator->Alloc(sizeof(SelfType));
150        if (memory)
151        {
152#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
153            return new(memory) SelfType(NULL, 0, allocator);
154#else
155            return new(memory) SelfType(allocator);
156#endif
157        }
158        else
159        {
160            return NULL;
161        }
162    }
163
164    //! @brief        必要なメモリを事前に確保してシグナルを生成します。
165    //!
166    //! @param[in]    maxSlots スロットを追加できる最大数です。
167    //! @param[in]    allocator アロケータです。
168    //!
169    static SelfType* CreateFixedSizedSignal(size_t maxSlots, AllocatorType* allocator)
170    {
171        void* memory = allocator->Alloc(sizeof(SelfType));
172        if (memory)
173        {
174#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
175            void* elements = allocator->Alloc(sizeof(SlotType*) * maxSlots);
176            if (elements != NULL)
177            {
178                return new(memory) SelfType(elements, maxSlots, allocator);
179            }
180            else
181            {
182                allocator->Free(memory);
183                return NULL;
184            }
185#else
186            NW_UNUSED_VARIABLE(maxSlots);
187            return new(memory) SelfType(allocator);
188#endif
189        }
190        else
191        {
192            return NULL;
193        }
194    }
195
196    //! @brief 必要になるごとにメモリを確保するシグナルを生成します。
197    static SelfType* CreateVariableSizeSignal(AllocatorType* allocator)
198    {
199        void* memory = allocator->Alloc(sizeof(SelfType));
200        if (memory)
201        {
202            return new(memory) SelfType(allocator);
203        }
204        else
205        {
206            return NULL;
207        }
208    }
209
210    //! オブジェクトを破棄します。
211    void Destroy() { this->~Signal0(); this->m_Allocator->Free(this); }
212
213    //@}
214
215    //----------------------------------------
216    //! @name スロット
217    //@{
218
219    //! @brief        スロットと接続し、シグナルが送られるようにする。
220    //!
221    //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
222    //! シグナルに接続できるスロット数は1つになります。
223    //!
224    //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
225    //! Connect する前に必ず Disconnect するようにしてください。
226    //! Disconnect していない場合は、アサートで停止します。
227    //!
228    //! @param[in]    slot スロットです。
229    //!
230    void Connect(SlotType* slot)
231    {
232#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
233        bool pushed = this->m_Slots.push_back(slot);
234        NW_ASSERT(pushed);
235#else
236        NW_ASSERT(this->m_Slot == NULL);
237        this->m_Slot = slot;
238#endif
239    }
240
241    //! @brief        スロットと接続し、シグナルが送られるようにする。
242    //!
243    //! Connect メソッドの追加の成否を取得できるようにしたものです。
244    //!
245    //! @param[in]    slot スロットです。
246    //!
247    //! @return       追加に成功すると true が返ります。
248    //!
249    bool TryConnect(SlotType* slot)
250    {
251#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
252        bool pushed = this->m_Slots.push_back(slot);
253        return pushed;
254#else
255        bool isConnectable = (this->m_Slot == NULL);
256        if (isConnectable)
257        {
258            this->m_Slot = slot;
259        }
260        return isConnectable;
261#endif
262    }
263
264    //! @brief        スロットを作成し、接続します。
265    //!
266    //! 内部でメモリを確保します。
267    //!
268    //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
269    //! シグナルに接続できるスロット数は1つになります。
270    //!
271    //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
272    //! Connect する前に必ず Disconnect するようにしてください。
273    //! Disconnect していない場合は、アサートで停止します。
274    //!
275    //! @tparam       TFunction 関数ポインタまたは、関数オブジェクトの型です。
276    //!
277    //! @param[in]    function 関数ポインタまたは、関数オブジェクトです。
278    //! @param[in]    allocator アロケータです。
279    //!
280    //! @return       生成されたスロットです。
281    //!
282    template<typename TFunction>
283    SlotType* CreateAndConnect(TFunction function, AllocatorType* allocator)
284    {
285        typedef FunctionSlot0<ResultType, TFunction, AllocatorType> FunctionSlotType;
286        FunctionSlotType* slot = CreateSlot<FunctionSlotType>(allocator, function);
287
288        this->Connect(slot);
289        return slot;
290    }
291
292    //! @brief        スロットを作成し、接続します。
293    //!
294    //! 内部でメモリを確保します。
295    //!
296    //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
297    //! シグナルに接続できるスロット数は1つになります。
298    //!
299    //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
300    //! Connect する前に必ず Disconnect するようにしてください。
301    //! Disconnect していない場合は、アサートで停止します。
302    //!
303    //! @tparam       TFunction 関数ポインタまたは、関数オブジェクトの型です。
304    //!
305    //! @param[in]    function 関数ポインタまたは、関数オブジェクトです。
306    //!
307    //! @return       生成されたスロットです。
308    //!
309    template<typename TFunction>
310    SlotType* CreateAndConnect(TFunction function)
311    {
312        return CreateAndConnect(function, this->m_Allocator);
313    }
314
315    //! @brief        スロットを切断します。
316    //!
317    //! @param[in]    slot 切断するスロットです。
318    //!
319    void Disconnect(SlotType* slot)
320    {
321#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
322        this->m_Slots.erase_find(slot);
323#else
324        if (this->m_Slot == slot)
325        {
326            this->m_Slot = NULL;
327        }
328#endif
329    }
330
331    //! @brief        スロットを切断して、破棄します。
332    //!
333    //! 関数オブジェクトにアロケータが設定されていると、オブジェクトを破棄します。
334    //! アロケータが設定されていないと、登録を解除して破棄は行いません。
335    //!
336    //! @param[in]    slot 切断するスロットです。
337    //!
338    void DisconnectAndDestroy(SlotType* slot)
339    {
340#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
341        this->m_Slots.erase_find(slot);
342        slot->Destroy();
343#else
344        if (this->m_Slot == slot)
345        {
346            this->m_Slot = NULL;
347        }
348        if (slot)
349        {
350            slot->Destroy();
351        }
352#endif
353    }
354    //@}
355
356    //! @brief シグナルを送信します。
357    ResultType operator()()
358    {
359#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
360        ResultCombinerType combiner;
361        return combiner(m_Slots.begin(), m_Slots.end(), Invoker());
362#else
363        if (this->m_Slot)
364        {
365            return this->m_Slot->Invoke();
366        }
367        else
368        {
369            return ResultType();
370        }
371#endif
372    }
373
374    //! @brief   CreateInvalidateSignal() の実行に必要なメモリサイズを取得します。
375    static size_t GetMemorySizeForInvalidateSignal(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT)
376    {
377        os::MemorySizeCalculator size(alignment);
378
379        GetMemorySizeForInvalidateSignalInternal(&size);
380
381        return size.GetSizeWithPadding(alignment);
382    }
383
384    //! @details :private
385    static void GetMemorySizeForInvalidateSignalInternal(os::MemorySizeCalculator* pSize)
386    {
387        os::MemorySizeCalculator& size = *pSize;
388
389        size += sizeof(SelfType);
390    }
391
392    //! @brief   CreateFixedSizedSignal() の実行に必要なメモリサイズを取得します。
393    //!
394    //! @param[in]    maxSlots スロットを追加できる最大数です。
395    static size_t GetMemorySizeForFixedSizedSignal(size_t maxSlots, size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT)
396    {
397        os::MemorySizeCalculator size(alignment);
398
399        GetMemorySizeForFixedSizedSignalInternal(&size, maxSlots);
400
401        return size.GetSizeWithPadding(alignment);
402    }
403
404    //! @details :private
405    static void GetMemorySizeForFixedSizedSignalInternal(os::MemorySizeCalculator* pSize, size_t maxSlots)
406    {
407        os::MemorySizeCalculator& size = *pSize;
408
409        size += sizeof(SelfType);
410
411#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
412        size += sizeof(SlotType*) * maxSlots;
413#else
414        NW_UNUSED_VARIABLE(maxSlots);
415#endif
416    }
417
418private:
419#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
420    //! @brief コンストラクタです。
421    Signal0(void* elements, size_t maxSlots, AllocatorType* allocator)
422    : m_Allocator(allocator), m_Slots(elements, maxSlots, allocator) {}
423    //! @brief コンストラクタです。
424    explicit Signal0(AllocatorType* allocator)
425    : m_Allocator(allocator), m_Slots(allocator) {}
426    //! @brief デストラクタです。
427    ~Signal0() { DestroyAllSlots(m_Slots); }
428#else
429    //! @brief コンストラクタです。
430    explicit Signal0(AllocatorType* allocator) : m_Allocator(allocator), m_Slot(NULL) {}
431    //! @brief デストラクタです。
432    ~Signal0() { SafeDestroy(this->m_Slot); }
433#endif
434
435    AllocatorType* m_Allocator;
436
437#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
438    SlotList m_Slots;
439#else
440    SlotType* m_Slot;
441#endif
442};
443
444//---------------------------------------------------------------------------
445//! @brief        シグナルを受け取るためのインターフェースです。(引数は 1 個です)
446//!
447//! @tparam       TResult 返り値の型です。
448//! @tparam       TAllocator アロケータの型です。
449//---------------------------------------------------------------------------
450template<
451    typename TResult,
452    typename TArg0,
453    typename TAllocator = os::IAllocator
454>
455class Slot1
456{
457public:
458    typedef TResult ResultType;
459    typedef TAllocator AllocatorType;
460
461    //! @brief コンストラクタです。
462    explicit Slot1(AllocatorType* allocator) : m_Allocator(allocator) {}
463
464    //! @brief 自らを破棄します。
465    void Destroy()
466    {
467        AllocatorType* allocator = this->GetAllocator();
468        if (allocator)
469        {
470            this->~Slot1();
471            allocator->Free(this);
472        }
473    }
474
475    //! @brief 自らを破棄します。
476    void Destroy(AllocatorType* allocator)
477    {
478        NW_NULL_ASSERT(allocator);
479        this->~Slot1();
480        allocator->Free(this);
481    }
482
483    //! @brief スロットにシグナルを送信します。
484    virtual ResultType Invoke(TArg0 arg0) = 0;
485
486    AllocatorType* GetAllocator() { return m_Allocator; }
487
488protected:
489    //! デストラクタです。
490    virtual ~Slot1() {}
491
492private:
493    AllocatorType* m_Allocator;
494};
495
496//---------------------------------------------------------------------------
497//! @brief        シグナルを受け取るためのクラスです。(引数は 1 個です)
498//!
499//! @tparam       TResult 返り値の型です。
500//! @tparam       TFunction 関数か関数オブジェクトの型です。
501//! @tparam       TAllocator アロケータの型です。
502//---------------------------------------------------------------------------
503template<
504    typename TResult,
505    typename TArg0,
506    typename TFunction,
507    typename TAllocator = os::IAllocator
508>
509class FunctionSlot1 : public Slot1<TResult, TArg0, TAllocator>
510{
511public:
512    typedef TResult ResultType;
513    typedef TFunction FunctionType;
514    typedef TAllocator AllocatorType;
515
516    //! コンストラクタです。
517    FunctionSlot1(AllocatorType* allocator, FunctionType function)
518    : Slot1<TResult, TArg0, TAllocator>(allocator), m_Function(function) {}
519
520    //! @brief スロットにシグナルを送信します。
521    virtual ResultType Invoke(TArg0 arg0)
522    {
523        return m_Function(arg0);
524    }
525
526private:
527    TFunction m_Function;
528};
529
530//---------------------------------------------------------------------------
531//! @brief        スロットに合図を送るためのクラスです。(引数は 1 個です)
532//!
533//! @tparam       TResult 返り値の型です。
534//! @tparam       TResultCombiner スロットの返り値をまとめて返してくれるコンバイナの型です。
535//! @tparam       TAllocator アロケータの型です。
536//! @tparam       TSlot スロットの型です。
537//---------------------------------------------------------------------------
538template<
539    typename TResult,
540    typename TArg0,
541    typename TResultCombiner = LastValueResult<TResult>,
542    typename TAllocator = os::IAllocator,
543    typename TSlot = Slot1<TResult, TArg0, TAllocator>
544>
545class Signal1
546{
547    NW_DISALLOW_COPY_AND_ASSIGN(Signal1);
548
549public:
550    typedef Signal1<TResult, TArg0, TResultCombiner, TAllocator, TSlot> SelfType;
551    typedef TSlot SlotType;
552    typedef TResult ResultType;
553    typedef ut::MoveArray<SlotType*> SlotList;
554    typedef TResultCombiner ResultCombinerType;
555    typedef TAllocator AllocatorType;
556
557#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
558    //! @brief スロット実行用関数オブジェクトです。
559    struct Invoker
560    {
561        Invoker(TArg0 arg0) : m_arg0(arg0) {}
562        ResultType operator()(SlotType* slot) const
563        {
564            return slot->Invoke(m_arg0);
565        }
566        TArg0 m_arg0;
567    };
568#endif
569
570    //----------------------------------------
571    //! @name 作成/破棄
572    //@{
573
574    //! @brief        無効なシグナルを生成します。
575    //!
576    //! @param[in]    allocator アロケータです。
577    //!
578    static SelfType* CreateInvalidateSignal(AllocatorType* allocator)
579    {
580        void* memory = allocator->Alloc(sizeof(SelfType));
581        if (memory)
582        {
583#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
584            return new(memory) SelfType(NULL, 0, allocator);
585#else
586            return new(memory) SelfType(allocator);
587#endif
588        }
589        else
590        {
591            return NULL;
592        }
593    }
594
595    //! @brief        必要なメモリを事前に確保してシグナルを生成します。
596    //!
597    //! @param[in]    maxSlots スロットを追加できる最大数です。
598    //! @param[in]    allocator アロケータです。
599    //!
600    static SelfType* CreateFixedSizedSignal(size_t maxSlots, AllocatorType* allocator)
601    {
602        void* memory = allocator->Alloc(sizeof(SelfType));
603        if (memory)
604        {
605#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
606            void* elements = allocator->Alloc(sizeof(SlotType*) * maxSlots);
607            if (elements != NULL)
608            {
609                return new(memory) SelfType(elements, maxSlots, allocator);
610            }
611            else
612            {
613                allocator->Free(memory);
614                return NULL;
615            }
616#else
617            NW_UNUSED_VARIABLE(maxSlots);
618            return new(memory) SelfType(allocator);
619#endif
620        }
621        else
622        {
623            return NULL;
624        }
625    }
626
627    //! @brief 必要になるごとにメモリを確保するシグナルを生成します。
628    static SelfType* CreateVariableSizeSignal(AllocatorType* allocator)
629    {
630        void* memory = allocator->Alloc(sizeof(SelfType));
631        if (memory)
632        {
633            return new(memory) SelfType(allocator);
634        }
635        else
636        {
637            return NULL;
638        }
639    }
640
641    //! オブジェクトを破棄します。
642    void Destroy() { this->~Signal1(); this->m_Allocator->Free(this); }
643
644    //@}
645
646    //----------------------------------------
647    //! @name スロット
648    //@{
649
650    //! @brief        スロットと接続し、シグナルが送られるようにする。
651    //!
652    //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
653    //! シグナルに接続できるスロット数は1つになります。
654    //!
655    //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
656    //! Connect する前に必ず Disconnect するようにしてください。
657    //! Disconnect していない場合は、アサートで停止します。
658    //!
659    //! @param[in]    slot スロットです。
660    //!
661    void Connect(SlotType* slot)
662    {
663#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
664        bool pushed = this->m_Slots.push_back(slot);
665        NW_ASSERT(pushed);
666#else
667        NW_ASSERT(this->m_Slot == NULL);
668        this->m_Slot = slot;
669#endif
670    }
671
672    //! @brief        スロットと接続し、シグナルが送られるようにする。
673    //!
674    //! Connect メソッドの追加の成否を取得できるようにしたものです。
675    //!
676    //! @param[in]    slot スロットです。
677    //!
678    //! @return       追加に成功すると true が返ります。
679    //!
680    bool TryConnect(SlotType* slot)
681    {
682#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
683        bool pushed = this->m_Slots.push_back(slot);
684        return pushed;
685#else
686        bool isConnectable = (this->m_Slot == NULL);
687        if (isConnectable)
688        {
689            this->m_Slot = slot;
690        }
691        return isConnectable;
692#endif
693    }
694
695    //! @brief        スロットを作成し、接続します。
696    //!
697    //! 内部でメモリを確保します。
698    //!
699    //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
700    //! シグナルに接続できるスロット数は1つになります。
701    //!
702    //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
703    //! Connect する前に必ず Disconnect するようにしてください。
704    //! Disconnect していない場合は、アサートで停止します。
705    //!
706    //! @tparam       TFunction 関数ポインタまたは、関数オブジェクトの型です。
707    //!
708    //! @param[in]    function 関数ポインタまたは、関数オブジェクトです。
709    //! @param[in]    allocator アロケータです。
710    //!
711    //! @return       生成されたスロットです。
712    //!
713    template<typename TFunction>
714    SlotType* CreateAndConnect(TFunction function, AllocatorType* allocator)
715    {
716        typedef FunctionSlot1<ResultType, TArg0, TFunction, AllocatorType> FunctionSlotType;
717        FunctionSlotType* slot = CreateSlot<FunctionSlotType>(allocator, function);
718
719        this->Connect(slot);
720        return slot;
721    }
722
723    //! @brief        スロットを作成し、接続します。
724    //!
725    //! 内部でメモリを確保します。
726    //!
727    //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
728    //! シグナルに接続できるスロット数は1つになります。
729    //!
730    //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
731    //! Connect する前に必ず Disconnect するようにしてください。
732    //! Disconnect していない場合は、アサートで停止します。
733    //!
734    //! @tparam       TFunction 関数ポインタまたは、関数オブジェクトの型です。
735    //!
736    //! @param[in]    function 関数ポインタまたは、関数オブジェクトです。
737    //!
738    //! @return       生成されたスロットです。
739    //!
740    template<typename TFunction>
741    SlotType* CreateAndConnect(TFunction function)
742    {
743        return CreateAndConnect(function, this->m_Allocator);
744    }
745
746    //! @brief        スロットを切断します。
747    //!
748    //! @param[in]    slot 切断するスロットです。
749    //!
750    void Disconnect(SlotType* slot)
751    {
752#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
753        this->m_Slots.erase_find(slot);
754#else
755        if (this->m_Slot == slot)
756        {
757            this->m_Slot = NULL;
758        }
759#endif
760    }
761
762    //! @brief        スロットを切断して、破棄します。
763    //!
764    //! 関数オブジェクトにアロケータが設定されていると、オブジェクトを破棄します。
765    //! アロケータが設定されていないと、登録を解除して破棄は行いません。
766    //!
767    //! @param[in]    slot 切断するスロットです。
768    //!
769    void DisconnectAndDestroy(SlotType* slot)
770    {
771#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
772        this->m_Slots.erase_find(slot);
773        slot->Destroy();
774#else
775        if (this->m_Slot == slot)
776        {
777            this->m_Slot = NULL;
778        }
779        if (slot)
780        {
781            slot->Destroy();
782        }
783#endif
784    }
785    //@}
786
787    //! @brief シグナルを送信します。
788    ResultType operator()(TArg0 arg0)
789    {
790#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
791        ResultCombinerType combiner;
792        return combiner(m_Slots.begin(), m_Slots.end(), Invoker(arg0));
793#else
794        if (this->m_Slot)
795        {
796            return this->m_Slot->Invoke(arg0);
797        }
798        else
799        {
800            return ResultType();
801        }
802#endif
803    }
804
805    //! @brief   CreateInvalidateSignal() の実行に必要なメモリサイズを取得します。
806    static size_t GetMemorySizeForInvalidateSignal(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT)
807    {
808        os::MemorySizeCalculator size(alignment);
809
810        GetMemorySizeForInvalidateSignalInternal(&size);
811
812        return size.GetSizeWithPadding(alignment);
813    }
814
815    //! @details :private
816    static void GetMemorySizeForInvalidateSignalInternal(os::MemorySizeCalculator* pSize)
817    {
818        os::MemorySizeCalculator& size = *pSize;
819
820        size += sizeof(SelfType);
821    }
822
823    //! @brief   CreateFixedSizedSignal() の実行に必要なメモリサイズを取得します。
824    //!
825    //! @param[in]    maxSlots スロットを追加できる最大数です。
826    static size_t GetMemorySizeForFixedSizedSignal(size_t maxSlots, size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT)
827    {
828        os::MemorySizeCalculator size(alignment);
829
830        GetMemorySizeForFixedSizedSignalInternal(&size, maxSlots);
831
832        return size.GetSizeWithPadding(alignment);
833    }
834
835    //! @details :private
836    static void GetMemorySizeForFixedSizedSignalInternal(os::MemorySizeCalculator* pSize, size_t maxSlots)
837    {
838        os::MemorySizeCalculator& size = *pSize;
839
840        size += sizeof(SelfType);
841
842#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
843        size += sizeof(SlotType*) * maxSlots;
844#else
845        NW_UNUSED_VARIABLE(maxSlots);
846#endif
847    }
848
849private:
850#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
851    //! @brief コンストラクタです。
852    Signal1(void* elements, size_t maxSlots, AllocatorType* allocator)
853    : m_Allocator(allocator), m_Slots(elements, maxSlots, allocator) {}
854    //! @brief コンストラクタです。
855    explicit Signal1(AllocatorType* allocator)
856    : m_Allocator(allocator), m_Slots(allocator) {}
857    //! @brief デストラクタです。
858    ~Signal1() { DestroyAllSlots(m_Slots); }
859#else
860    //! @brief コンストラクタです。
861    explicit Signal1(AllocatorType* allocator) : m_Allocator(allocator), m_Slot(NULL) {}
862    //! @brief デストラクタです。
863    ~Signal1() { SafeDestroy(this->m_Slot); }
864#endif
865
866    AllocatorType* m_Allocator;
867
868#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
869    SlotList m_Slots;
870#else
871    SlotType* m_Slot;
872#endif
873};
874
875//---------------------------------------------------------------------------
876//! @brief        シグナルを受け取るためのインターフェースです。(引数は 2 個です)
877//!
878//! @tparam       TResult 返り値の型です。
879//! @tparam       TAllocator アロケータの型です。
880//---------------------------------------------------------------------------
881template<
882    typename TResult,
883    typename TArg0, typename TArg1,
884    typename TAllocator = os::IAllocator
885>
886class Slot2
887{
888public:
889    typedef TResult ResultType;
890    typedef TAllocator AllocatorType;
891
892    //! @brief コンストラクタです。
893    explicit Slot2(AllocatorType* allocator) : m_Allocator(allocator) {}
894
895    //! @brief 自らを破棄します。
896    void Destroy()
897    {
898        AllocatorType* allocator = this->GetAllocator();
899        if (allocator)
900        {
901            this->~Slot2();
902            allocator->Free(this);
903        }
904    }
905
906    //! @brief 自らを破棄します。
907    void Destroy(AllocatorType* allocator)
908    {
909        NW_NULL_ASSERT(allocator);
910        this->~Slot2();
911        allocator->Free(this);
912    }
913
914    //! @brief スロットにシグナルを送信します。
915    virtual ResultType Invoke(TArg0 arg0, TArg1 arg1) = 0;
916
917    AllocatorType* GetAllocator() { return m_Allocator; }
918
919protected:
920    //! デストラクタです。
921    virtual ~Slot2() {}
922
923private:
924    AllocatorType* m_Allocator;
925};
926
927//---------------------------------------------------------------------------
928//! @brief        シグナルを受け取るためのクラスです。(引数は 2 個です)
929//!
930//! @tparam       TResult 返り値の型です。
931//! @tparam       TFunction 関数か関数オブジェクトの型です。
932//! @tparam       TAllocator アロケータの型です。
933//---------------------------------------------------------------------------
934template<
935    typename TResult,
936    typename TArg0, typename TArg1,
937    typename TFunction,
938    typename TAllocator = os::IAllocator
939>
940class FunctionSlot2 : public Slot2<TResult, TArg0, TArg1, TAllocator>
941{
942public:
943    typedef TResult ResultType;
944    typedef TFunction FunctionType;
945    typedef TAllocator AllocatorType;
946
947    //! コンストラクタです。
948    FunctionSlot2(AllocatorType* allocator, FunctionType function)
949    : Slot2<TResult, TArg0, TArg1, TAllocator>(allocator), m_Function(function) {}
950
951    //! @brief スロットにシグナルを送信します。
952    virtual ResultType Invoke(TArg0 arg0, TArg1 arg1)
953    {
954        return m_Function(arg0, arg1);
955    }
956
957private:
958    TFunction m_Function;
959};
960
961//---------------------------------------------------------------------------
962//! @brief        スロットに合図を送るためのクラスです。(引数は 2 個です)
963//!
964//! @tparam       TResult 返り値の型です。
965//! @tparam       TResultCombiner スロットの返り値をまとめて返してくれるコンバイナの型です。
966//! @tparam       TAllocator アロケータの型です。
967//! @tparam       TSlot スロットの型です。
968//---------------------------------------------------------------------------
969template<
970    typename TResult,
971    typename TArg0, typename TArg1,
972    typename TResultCombiner = LastValueResult<TResult>,
973    typename TAllocator = os::IAllocator,
974    typename TSlot = Slot2<TResult, TArg0, TArg1, TAllocator>
975>
976class Signal2
977{
978    NW_DISALLOW_COPY_AND_ASSIGN(Signal2);
979
980public:
981    typedef Signal2<TResult, TArg0, TArg1, TResultCombiner, TAllocator, TSlot> SelfType;
982    typedef TSlot SlotType;
983    typedef TResult ResultType;
984    typedef ut::MoveArray<SlotType*> SlotList;
985    typedef TResultCombiner ResultCombinerType;
986    typedef TAllocator AllocatorType;
987
988#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
989    //! @brief スロット実行用関数オブジェクトです。
990    struct Invoker
991    {
992        Invoker(TArg0 arg0, TArg1 arg1) : m_arg0(arg0), m_arg1(arg1) {}
993        ResultType operator()(SlotType* slot) const
994        {
995            return slot->Invoke(m_arg0, m_arg1);
996        }
997        TArg0 m_arg0;
998        TArg1 m_arg1;
999    };
1000#endif
1001
1002    //----------------------------------------
1003    //! @name 作成/破棄
1004    //@{
1005
1006    //! @brief        無効なシグナルを生成します。
1007    //!
1008    //! @param[in]    allocator アロケータです。
1009    //!
1010    static SelfType* CreateInvalidateSignal(AllocatorType* allocator)
1011    {
1012        void* memory = allocator->Alloc(sizeof(SelfType));
1013        if (memory)
1014        {
1015#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
1016            return new(memory) SelfType(NULL, 0, allocator);
1017#else
1018            return new(memory) SelfType(allocator);
1019#endif
1020        }
1021        else
1022        {
1023            return NULL;
1024        }
1025    }
1026
1027    //! @brief        必要なメモリを事前に確保してシグナルを生成します。
1028    //!
1029    //! @param[in]    maxSlots スロットを追加できる最大数です。
1030    //! @param[in]    allocator アロケータです。
1031    //!
1032    static SelfType* CreateFixedSizedSignal(size_t maxSlots, AllocatorType* allocator)
1033    {
1034        void* memory = allocator->Alloc(sizeof(SelfType));
1035        if (memory)
1036        {
1037#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
1038            void* elements = allocator->Alloc(sizeof(SlotType*) * maxSlots);
1039            if (elements != NULL)
1040            {
1041                return new(memory) SelfType(elements, maxSlots, allocator);
1042            }
1043            else
1044            {
1045                allocator->Free(memory);
1046                return NULL;
1047            }
1048#else
1049            NW_UNUSED_VARIABLE(maxSlots);
1050            return new(memory) SelfType(allocator);
1051#endif
1052        }
1053        else
1054        {
1055            return NULL;
1056        }
1057    }
1058
1059    //! @brief 必要になるごとにメモリを確保するシグナルを生成します。
1060    static SelfType* CreateVariableSizeSignal(AllocatorType* allocator)
1061    {
1062        void* memory = allocator->Alloc(sizeof(SelfType));
1063        if (memory)
1064        {
1065            return new(memory) SelfType(allocator);
1066        }
1067        else
1068        {
1069            return NULL;
1070        }
1071    }
1072
1073    //! オブジェクトを破棄します。
1074    void Destroy() { this->~Signal2(); this->m_Allocator->Free(this); }
1075
1076    //@}
1077
1078    //----------------------------------------
1079    //! @name スロット
1080    //@{
1081
1082    //! @brief        スロットと接続し、シグナルが送られるようにする。
1083    //!
1084    //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
1085    //! シグナルに接続できるスロット数は1つになります。
1086    //!
1087    //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
1088    //! Connect する前に必ず Disconnect するようにしてください。
1089    //! Disconnect していない場合は、アサートで停止します。
1090    //!
1091    //! @param[in]    slot スロットです。
1092    //!
1093    void Connect(SlotType* slot)
1094    {
1095#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
1096        bool pushed = this->m_Slots.push_back(slot);
1097        NW_ASSERT(pushed);
1098#else
1099        NW_ASSERT(this->m_Slot == NULL);
1100        this->m_Slot = slot;
1101#endif
1102    }
1103
1104    //! @brief        スロットと接続し、シグナルが送られるようにする。
1105    //!
1106    //! Connect メソッドの追加の成否を取得できるようにしたものです。
1107    //!
1108    //! @param[in]    slot スロットです。
1109    //!
1110    //! @return       追加に成功すると true が返ります。
1111    //!
1112    bool TryConnect(SlotType* slot)
1113    {
1114#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
1115        bool pushed = this->m_Slots.push_back(slot);
1116        return pushed;
1117#else
1118        bool isConnectable = (this->m_Slot == NULL);
1119        if (isConnectable)
1120        {
1121            this->m_Slot = slot;
1122        }
1123        return isConnectable;
1124#endif
1125    }
1126
1127    //! @brief        スロットを作成し、接続します。
1128    //!
1129    //! 内部でメモリを確保します。
1130    //!
1131    //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
1132    //! シグナルに接続できるスロット数は1つになります。
1133    //!
1134    //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
1135    //! Connect する前に必ず Disconnect するようにしてください。
1136    //! Disconnect していない場合は、アサートで停止します。
1137    //!
1138    //! @tparam       TFunction 関数ポインタまたは、関数オブジェクトの型です。
1139    //!
1140    //! @param[in]    function 関数ポインタまたは、関数オブジェクトです。
1141    //! @param[in]    allocator アロケータです。
1142    //!
1143    //! @return       生成されたスロットです。
1144    //!
1145    template<typename TFunction>
1146    SlotType* CreateAndConnect(TFunction function, AllocatorType* allocator)
1147    {
1148        typedef FunctionSlot2<ResultType, TArg0, TArg1, TFunction, AllocatorType> FunctionSlotType;
1149        FunctionSlotType* slot = CreateSlot<FunctionSlotType>(allocator, function);
1150
1151        this->Connect(slot);
1152        return slot;
1153    }
1154
1155    //! @brief        スロットを作成し、接続します。
1156    //!
1157    //! 内部でメモリを確保します。
1158    //!
1159    //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
1160    //! シグナルに接続できるスロット数は1つになります。
1161    //!
1162    //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
1163    //! Connect する前に必ず Disconnect するようにしてください。
1164    //! Disconnect していない場合は、アサートで停止します。
1165    //!
1166    //! @tparam       TFunction 関数ポインタまたは、関数オブジェクトの型です。
1167    //!
1168    //! @param[in]    function 関数ポインタまたは、関数オブジェクトです。
1169    //!
1170    //! @return       生成されたスロットです。
1171    //!
1172    template<typename TFunction>
1173    SlotType* CreateAndConnect(TFunction function)
1174    {
1175        return CreateAndConnect(function, this->m_Allocator);
1176    }
1177
1178    //! @brief        スロットを切断します。
1179    //!
1180    //! @param[in]    slot 切断するスロットです。
1181    //!
1182    void Disconnect(SlotType* slot)
1183    {
1184#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
1185        this->m_Slots.erase_find(slot);
1186#else
1187        if (this->m_Slot == slot)
1188        {
1189            this->m_Slot = NULL;
1190        }
1191#endif
1192    }
1193
1194    //! @brief        スロットを切断して、破棄します。
1195    //!
1196    //! 関数オブジェクトにアロケータが設定されていると、オブジェクトを破棄します。
1197    //! アロケータが設定されていないと、登録を解除して破棄は行いません。
1198    //!
1199    //! @param[in]    slot 切断するスロットです。
1200    //!
1201    void DisconnectAndDestroy(SlotType* slot)
1202    {
1203#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
1204        this->m_Slots.erase_find(slot);
1205        slot->Destroy();
1206#else
1207        if (this->m_Slot == slot)
1208        {
1209            this->m_Slot = NULL;
1210        }
1211        if (slot)
1212        {
1213            slot->Destroy();
1214        }
1215#endif
1216    }
1217    //@}
1218
1219    //! @brief シグナルを送信します。
1220    ResultType operator()(TArg0 arg0, TArg1 arg1)
1221    {
1222#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
1223        ResultCombinerType combiner;
1224        return combiner(m_Slots.begin(), m_Slots.end(), Invoker(arg0, arg1));
1225#else
1226        if (this->m_Slot)
1227        {
1228            return this->m_Slot->Invoke(arg0, arg1);
1229        }
1230        else
1231        {
1232            return ResultType();
1233        }
1234#endif
1235    }
1236
1237    //! @brief   CreateInvalidateSignal() の実行に必要なメモリサイズを取得します。
1238    static size_t GetMemorySizeForInvalidateSignal(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT)
1239    {
1240        os::MemorySizeCalculator size(alignment);
1241
1242        GetMemorySizeForInvalidateSignalInternal(&size);
1243
1244        return size.GetSizeWithPadding(alignment);
1245    }
1246
1247    //! @details :private
1248    static void GetMemorySizeForInvalidateSignalInternal(os::MemorySizeCalculator* pSize)
1249    {
1250        os::MemorySizeCalculator& size = *pSize;
1251
1252        size += sizeof(SelfType);
1253    }
1254
1255    //! @brief   CreateFixedSizedSignal() の実行に必要なメモリサイズを取得します。
1256    //!
1257    //! @param[in]    maxSlots スロットを追加できる最大数です。
1258    static size_t GetMemorySizeForFixedSizedSignal(size_t maxSlots, size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT)
1259    {
1260        os::MemorySizeCalculator size(alignment);
1261
1262        GetMemorySizeForFixedSizedSignalInternal(&size, maxSlots);
1263
1264        return size.GetSizeWithPadding(alignment);
1265    }
1266
1267    //! @details :private
1268    static void GetMemorySizeForFixedSizedSignalInternal(os::MemorySizeCalculator* pSize, size_t maxSlots)
1269    {
1270        os::MemorySizeCalculator& size = *pSize;
1271
1272        size += sizeof(SelfType);
1273
1274#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
1275        size += sizeof(SlotType*) * maxSlots;
1276#else
1277        NW_UNUSED_VARIABLE(maxSlots);
1278#endif
1279    }
1280
1281private:
1282#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
1283    //! @brief コンストラクタです。
1284    Signal2(void* elements, size_t maxSlots, AllocatorType* allocator)
1285    : m_Allocator(allocator), m_Slots(elements, maxSlots, allocator) {}
1286    //! @brief コンストラクタです。
1287    explicit Signal2(AllocatorType* allocator)
1288    : m_Allocator(allocator), m_Slots(allocator) {}
1289    //! @brief デストラクタです。
1290    ~Signal2() { DestroyAllSlots(m_Slots); }
1291#else
1292    //! @brief コンストラクタです。
1293    explicit Signal2(AllocatorType* allocator) : m_Allocator(allocator), m_Slot(NULL) {}
1294    //! @brief デストラクタです。
1295    ~Signal2() { SafeDestroy(this->m_Slot); }
1296#endif
1297
1298    AllocatorType* m_Allocator;
1299
1300#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
1301    SlotList m_Slots;
1302#else
1303    SlotType* m_Slot;
1304#endif
1305};
1306
1307//---------------------------------------------------------------------------
1308//! @brief        シグナルを受け取るためのインターフェースです。(引数は 3 個です)
1309//!
1310//! @tparam       TResult 返り値の型です。
1311//! @tparam       TAllocator アロケータの型です。
1312//---------------------------------------------------------------------------
1313template<
1314    typename TResult,
1315    typename TArg0, typename TArg1, typename TArg2,
1316    typename TAllocator = os::IAllocator
1317>
1318class Slot3
1319{
1320public:
1321    typedef TResult ResultType;
1322    typedef TAllocator AllocatorType;
1323
1324    //! @brief コンストラクタです。
1325    explicit Slot3(AllocatorType* allocator) : m_Allocator(allocator) {}
1326
1327    //! @brief 自らを破棄します。
1328    void Destroy()
1329    {
1330        AllocatorType* allocator = this->GetAllocator();
1331        if (allocator)
1332        {
1333            this->~Slot3();
1334            allocator->Free(this);
1335        }
1336    }
1337
1338    //! @brief 自らを破棄します。
1339    void Destroy(AllocatorType* allocator)
1340    {
1341        NW_NULL_ASSERT(allocator);
1342        this->~Slot3();
1343        allocator->Free(this);
1344    }
1345
1346    //! @brief スロットにシグナルを送信します。
1347    virtual ResultType Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2) = 0;
1348
1349    AllocatorType* GetAllocator() { return m_Allocator; }
1350
1351protected:
1352    //! デストラクタです。
1353    virtual ~Slot3() {}
1354
1355private:
1356    AllocatorType* m_Allocator;
1357};
1358
1359//---------------------------------------------------------------------------
1360//! @brief        シグナルを受け取るためのクラスです。(引数は 3 個です)
1361//!
1362//! @tparam       TResult 返り値の型です。
1363//! @tparam       TFunction 関数か関数オブジェクトの型です。
1364//! @tparam       TAllocator アロケータの型です。
1365//---------------------------------------------------------------------------
1366template<
1367    typename TResult,
1368    typename TArg0, typename TArg1, typename TArg2,
1369    typename TFunction,
1370    typename TAllocator = os::IAllocator
1371>
1372class FunctionSlot3 : public Slot3<TResult, TArg0, TArg1, TArg2, TAllocator>
1373{
1374public:
1375    typedef TResult ResultType;
1376    typedef TFunction FunctionType;
1377    typedef TAllocator AllocatorType;
1378
1379    //! コンストラクタです。
1380    FunctionSlot3(AllocatorType* allocator, FunctionType function)
1381    : Slot3<TResult, TArg0, TArg1, TArg2, TAllocator>(allocator), m_Function(function) {}
1382
1383    //! @brief スロットにシグナルを送信します。
1384    virtual ResultType Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2)
1385    {
1386        return m_Function(arg0, arg1, arg2);
1387    }
1388
1389private:
1390    TFunction m_Function;
1391};
1392
1393//---------------------------------------------------------------------------
1394//! @brief        スロットに合図を送るためのクラスです。(引数は 3 個です)
1395//!
1396//! @tparam       TResult 返り値の型です。
1397//! @tparam       TResultCombiner スロットの返り値をまとめて返してくれるコンバイナの型です。
1398//! @tparam       TAllocator アロケータの型です。
1399//! @tparam       TSlot スロットの型です。
1400//---------------------------------------------------------------------------
1401template<
1402    typename TResult,
1403    typename TArg0, typename TArg1, typename TArg2,
1404    typename TResultCombiner = LastValueResult<TResult>,
1405    typename TAllocator = os::IAllocator,
1406    typename TSlot = Slot3<TResult, TArg0, TArg1, TArg2, TAllocator>
1407>
1408class Signal3
1409{
1410    NW_DISALLOW_COPY_AND_ASSIGN(Signal3);
1411
1412public:
1413    typedef Signal3<TResult, TArg0, TArg1, TArg2, TResultCombiner, TAllocator, TSlot> SelfType;
1414    typedef TSlot SlotType;
1415    typedef TResult ResultType;
1416    typedef ut::MoveArray<SlotType*> SlotList;
1417    typedef TResultCombiner ResultCombinerType;
1418    typedef TAllocator AllocatorType;
1419
1420#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
1421    //! @brief スロット実行用関数オブジェクトです。
1422    struct Invoker
1423    {
1424        Invoker(TArg0 arg0, TArg1 arg1, TArg2 arg2) : m_arg0(arg0), m_arg1(arg1), m_arg2(arg2) {}
1425        ResultType operator()(SlotType* slot) const
1426        {
1427            return slot->Invoke(m_arg0, m_arg1, m_arg2);
1428        }
1429        TArg0 m_arg0;
1430        TArg1 m_arg1;
1431        TArg2 m_arg2;
1432    };
1433#endif
1434
1435    //----------------------------------------
1436    //! @name 作成/破棄
1437    //@{
1438
1439    //! @brief        無効なシグナルを生成します。
1440    //!
1441    //! @param[in]    allocator アロケータです。
1442    //!
1443    static SelfType* CreateInvalidateSignal(AllocatorType* allocator)
1444    {
1445        void* memory = allocator->Alloc(sizeof(SelfType));
1446        if (memory)
1447        {
1448#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
1449            return new(memory) SelfType(NULL, 0, allocator);
1450#else
1451            return new(memory) SelfType(allocator);
1452#endif
1453        }
1454        else
1455        {
1456            return NULL;
1457        }
1458    }
1459
1460    //! @brief        必要なメモリを事前に確保してシグナルを生成します。
1461    //!
1462    //! @param[in]    maxSlots スロットを追加できる最大数です。
1463    //! @param[in]    allocator アロケータです。
1464    //!
1465    static SelfType* CreateFixedSizedSignal(size_t maxSlots, AllocatorType* allocator)
1466    {
1467        void* memory = allocator->Alloc(sizeof(SelfType));
1468        if (memory)
1469        {
1470#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
1471            void* elements = allocator->Alloc(sizeof(SlotType*) * maxSlots);
1472            if (elements != NULL)
1473            {
1474                return new(memory) SelfType(elements, maxSlots, allocator);
1475            }
1476            else
1477            {
1478                allocator->Free(memory);
1479                return NULL;
1480            }
1481#else
1482            NW_UNUSED_VARIABLE(maxSlots);
1483            return new(memory) SelfType(allocator);
1484#endif
1485        }
1486        else
1487        {
1488            return NULL;
1489        }
1490    }
1491
1492    //! @brief 必要になるごとにメモリを確保するシグナルを生成します。
1493    static SelfType* CreateVariableSizeSignal(AllocatorType* allocator)
1494    {
1495        void* memory = allocator->Alloc(sizeof(SelfType));
1496        if (memory)
1497        {
1498            return new(memory) SelfType(allocator);
1499        }
1500        else
1501        {
1502            return NULL;
1503        }
1504    }
1505
1506    //! オブジェクトを破棄します。
1507    void Destroy() { this->~Signal3(); this->m_Allocator->Free(this); }
1508
1509    //@}
1510
1511    //----------------------------------------
1512    //! @name スロット
1513    //@{
1514
1515    //! @brief        スロットと接続し、シグナルが送られるようにする。
1516    //!
1517    //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
1518    //! シグナルに接続できるスロット数は1つになります。
1519    //!
1520    //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
1521    //! Connect する前に必ず Disconnect するようにしてください。
1522    //! Disconnect していない場合は、アサートで停止します。
1523    //!
1524    //! @param[in]    slot スロットです。
1525    //!
1526    void Connect(SlotType* slot)
1527    {
1528#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
1529        bool pushed = this->m_Slots.push_back(slot);
1530        NW_ASSERT(pushed);
1531#else
1532        NW_ASSERT(this->m_Slot == NULL);
1533        this->m_Slot = slot;
1534#endif
1535    }
1536
1537    //! @brief        スロットと接続し、シグナルが送られるようにする。
1538    //!
1539    //! Connect メソッドの追加の成否を取得できるようにしたものです。
1540    //!
1541    //! @param[in]    slot スロットです。
1542    //!
1543    //! @return       追加に成功すると true が返ります。
1544    //!
1545    bool TryConnect(SlotType* slot)
1546    {
1547#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
1548        bool pushed = this->m_Slots.push_back(slot);
1549        return pushed;
1550#else
1551        bool isConnectable = (this->m_Slot == NULL);
1552        if (isConnectable)
1553        {
1554            this->m_Slot = slot;
1555        }
1556        return isConnectable;
1557#endif
1558    }
1559
1560    //! @brief        スロットを作成し、接続します。
1561    //!
1562    //! 内部でメモリを確保します。
1563    //!
1564    //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
1565    //! シグナルに接続できるスロット数は1つになります。
1566    //!
1567    //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
1568    //! Connect する前に必ず Disconnect するようにしてください。
1569    //! Disconnect していない場合は、アサートで停止します。
1570    //!
1571    //! @tparam       TFunction 関数ポインタまたは、関数オブジェクトの型です。
1572    //!
1573    //! @param[in]    function 関数ポインタまたは、関数オブジェクトです。
1574    //! @param[in]    allocator アロケータです。
1575    //!
1576    //! @return       生成されたスロットです。
1577    //!
1578    template<typename TFunction>
1579    SlotType* CreateAndConnect(TFunction function, AllocatorType* allocator)
1580    {
1581        typedef FunctionSlot3<ResultType, TArg0, TArg1, TArg2, TFunction, AllocatorType> FunctionSlotType;
1582        FunctionSlotType* slot = CreateSlot<FunctionSlotType>(allocator, function);
1583
1584        this->Connect(slot);
1585        return slot;
1586    }
1587
1588    //! @brief        スロットを作成し、接続します。
1589    //!
1590    //! 内部でメモリを確保します。
1591    //!
1592    //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
1593    //! シグナルに接続できるスロット数は1つになります。
1594    //!
1595    //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
1596    //! Connect する前に必ず Disconnect するようにしてください。
1597    //! Disconnect していない場合は、アサートで停止します。
1598    //!
1599    //! @tparam       TFunction 関数ポインタまたは、関数オブジェクトの型です。
1600    //!
1601    //! @param[in]    function 関数ポインタまたは、関数オブジェクトです。
1602    //!
1603    //! @return       生成されたスロットです。
1604    //!
1605    template<typename TFunction>
1606    SlotType* CreateAndConnect(TFunction function)
1607    {
1608        return CreateAndConnect(function, this->m_Allocator);
1609    }
1610
1611    //! @brief        スロットを切断します。
1612    //!
1613    //! @param[in]    slot 切断するスロットです。
1614    //!
1615    void Disconnect(SlotType* slot)
1616    {
1617#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
1618        this->m_Slots.erase_find(slot);
1619#else
1620        if (this->m_Slot == slot)
1621        {
1622            this->m_Slot = NULL;
1623        }
1624#endif
1625    }
1626
1627    //! @brief        スロットを切断して、破棄します。
1628    //!
1629    //! 関数オブジェクトにアロケータが設定されていると、オブジェクトを破棄します。
1630    //! アロケータが設定されていないと、登録を解除して破棄は行いません。
1631    //!
1632    //! @param[in]    slot 切断するスロットです。
1633    //!
1634    void DisconnectAndDestroy(SlotType* slot)
1635    {
1636#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
1637        this->m_Slots.erase_find(slot);
1638        slot->Destroy();
1639#else
1640        if (this->m_Slot == slot)
1641        {
1642            this->m_Slot = NULL;
1643        }
1644        if (slot)
1645        {
1646            slot->Destroy();
1647        }
1648#endif
1649    }
1650    //@}
1651
1652    //! @brief シグナルを送信します。
1653    ResultType operator()(TArg0 arg0, TArg1 arg1, TArg2 arg2)
1654    {
1655#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
1656        ResultCombinerType combiner;
1657        return combiner(m_Slots.begin(), m_Slots.end(), Invoker(arg0, arg1, arg2));
1658#else
1659        if (this->m_Slot)
1660        {
1661            return this->m_Slot->Invoke(arg0, arg1, arg2);
1662        }
1663        else
1664        {
1665            return ResultType();
1666        }
1667#endif
1668    }
1669
1670    //! @brief   CreateInvalidateSignal() の実行に必要なメモリサイズを取得します。
1671    static size_t GetMemorySizeForInvalidateSignal(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT)
1672    {
1673        os::MemorySizeCalculator size(alignment);
1674
1675        GetMemorySizeForInvalidateSignalInternal(&size);
1676
1677        return size.GetSizeWithPadding(alignment);
1678    }
1679
1680    //! @details :private
1681    static void GetMemorySizeForInvalidateSignalInternal(os::MemorySizeCalculator* pSize)
1682    {
1683        os::MemorySizeCalculator& size = *pSize;
1684
1685        size += sizeof(SelfType);
1686    }
1687
1688    //! @brief   CreateFixedSizedSignal() の実行に必要なメモリサイズを取得します。
1689    //!
1690    //! @param[in]    maxSlots スロットを追加できる最大数です。
1691    static size_t GetMemorySizeForFixedSizedSignal(size_t maxSlots, size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT)
1692    {
1693        os::MemorySizeCalculator size(alignment);
1694
1695        GetMemorySizeForFixedSizedSignalInternal(&size, maxSlots);
1696
1697        return size.GetSizeWithPadding(alignment);
1698    }
1699
1700    //! @details :private
1701    static void GetMemorySizeForFixedSizedSignalInternal(os::MemorySizeCalculator* pSize, size_t maxSlots)
1702    {
1703        os::MemorySizeCalculator& size = *pSize;
1704
1705        size += sizeof(SelfType);
1706
1707#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
1708        size += sizeof(SlotType*) * maxSlots;
1709#else
1710        NW_UNUSED_VARIABLE(maxSlots);
1711#endif
1712    }
1713
1714private:
1715#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
1716    //! @brief コンストラクタです。
1717    Signal3(void* elements, size_t maxSlots, AllocatorType* allocator)
1718    : m_Allocator(allocator), m_Slots(elements, maxSlots, allocator) {}
1719    //! @brief コンストラクタです。
1720    explicit Signal3(AllocatorType* allocator)
1721    : m_Allocator(allocator), m_Slots(allocator) {}
1722    //! @brief デストラクタです。
1723    ~Signal3() { DestroyAllSlots(m_Slots); }
1724#else
1725    //! @brief コンストラクタです。
1726    explicit Signal3(AllocatorType* allocator) : m_Allocator(allocator), m_Slot(NULL) {}
1727    //! @brief デストラクタです。
1728    ~Signal3() { SafeDestroy(this->m_Slot); }
1729#endif
1730
1731    AllocatorType* m_Allocator;
1732
1733#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
1734    SlotList m_Slots;
1735#else
1736    SlotType* m_Slot;
1737#endif
1738};
1739
1740//---------------------------------------------------------------------------
1741//! @brief        シグナルを受け取るためのインターフェースです。(引数は 4 個です)
1742//!
1743//! @tparam       TResult 返り値の型です。
1744//! @tparam       TAllocator アロケータの型です。
1745//---------------------------------------------------------------------------
1746template<
1747    typename TResult,
1748    typename TArg0, typename TArg1, typename TArg2, typename TArg3,
1749    typename TAllocator = os::IAllocator
1750>
1751class Slot4
1752{
1753public:
1754    typedef TResult ResultType;
1755    typedef TAllocator AllocatorType;
1756
1757    //! @brief コンストラクタです。
1758    explicit Slot4(AllocatorType* allocator) : m_Allocator(allocator) {}
1759
1760    //! @brief 自らを破棄します。
1761    void Destroy()
1762    {
1763        AllocatorType* allocator = this->GetAllocator();
1764        if (allocator)
1765        {
1766            this->~Slot4();
1767            allocator->Free(this);
1768        }
1769    }
1770
1771    //! @brief 自らを破棄します。
1772    void Destroy(AllocatorType* allocator)
1773    {
1774        NW_NULL_ASSERT(allocator);
1775        this->~Slot4();
1776        allocator->Free(this);
1777    }
1778
1779    //! @brief スロットにシグナルを送信します。
1780    virtual ResultType Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3) = 0;
1781
1782    AllocatorType* GetAllocator() { return m_Allocator; }
1783
1784protected:
1785    //! デストラクタです。
1786    virtual ~Slot4() {}
1787
1788private:
1789    AllocatorType* m_Allocator;
1790};
1791
1792//---------------------------------------------------------------------------
1793//! @brief        シグナルを受け取るためのクラスです。(引数は 4 個です)
1794//!
1795//! @tparam       TResult 返り値の型です。
1796//! @tparam       TFunction 関数か関数オブジェクトの型です。
1797//! @tparam       TAllocator アロケータの型です。
1798//---------------------------------------------------------------------------
1799template<
1800    typename TResult,
1801    typename TArg0, typename TArg1, typename TArg2, typename TArg3,
1802    typename TFunction,
1803    typename TAllocator = os::IAllocator
1804>
1805class FunctionSlot4 : public Slot4<TResult, TArg0, TArg1, TArg2, TArg3, TAllocator>
1806{
1807public:
1808    typedef TResult ResultType;
1809    typedef TFunction FunctionType;
1810    typedef TAllocator AllocatorType;
1811
1812    //! コンストラクタです。
1813    FunctionSlot4(AllocatorType* allocator, FunctionType function)
1814    : Slot4<TResult, TArg0, TArg1, TArg2, TArg3, TAllocator>(allocator), m_Function(function) {}
1815
1816    //! @brief スロットにシグナルを送信します。
1817    virtual ResultType Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3)
1818    {
1819        return m_Function(arg0, arg1, arg2, arg3);
1820    }
1821
1822private:
1823    TFunction m_Function;
1824};
1825
1826//---------------------------------------------------------------------------
1827//! @brief        スロットに合図を送るためのクラスです。(引数は 4 個です)
1828//!
1829//! @tparam       TResult 返り値の型です。
1830//! @tparam       TResultCombiner スロットの返り値をまとめて返してくれるコンバイナの型です。
1831//! @tparam       TAllocator アロケータの型です。
1832//! @tparam       TSlot スロットの型です。
1833//---------------------------------------------------------------------------
1834template<
1835    typename TResult,
1836    typename TArg0, typename TArg1, typename TArg2, typename TArg3,
1837    typename TResultCombiner = LastValueResult<TResult>,
1838    typename TAllocator = os::IAllocator,
1839    typename TSlot = Slot4<TResult, TArg0, TArg1, TArg2, TArg3, TAllocator>
1840>
1841class Signal4
1842{
1843    NW_DISALLOW_COPY_AND_ASSIGN(Signal4);
1844
1845public:
1846    typedef Signal4<TResult, TArg0, TArg1, TArg2, TArg3, TResultCombiner, TAllocator, TSlot> SelfType;
1847    typedef TSlot SlotType;
1848    typedef TResult ResultType;
1849    typedef ut::MoveArray<SlotType*> SlotList;
1850    typedef TResultCombiner ResultCombinerType;
1851    typedef TAllocator AllocatorType;
1852
1853#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
1854    //! @brief スロット実行用関数オブジェクトです。
1855    struct Invoker
1856    {
1857        Invoker(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3) : m_arg0(arg0), m_arg1(arg1), m_arg2(arg2), m_arg3(arg3) {}
1858        ResultType operator()(SlotType* slot) const
1859        {
1860            return slot->Invoke(m_arg0, m_arg1, m_arg2, m_arg3);
1861        }
1862        TArg0 m_arg0;
1863        TArg1 m_arg1;
1864        TArg2 m_arg2;
1865        TArg3 m_arg3;
1866    };
1867#endif
1868
1869    //----------------------------------------
1870    //! @name 作成/破棄
1871    //@{
1872
1873    //! @brief        無効なシグナルを生成します。
1874    //!
1875    //! @param[in]    allocator アロケータです。
1876    //!
1877    static SelfType* CreateInvalidateSignal(AllocatorType* allocator)
1878    {
1879        void* memory = allocator->Alloc(sizeof(SelfType));
1880        if (memory)
1881        {
1882#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
1883            return new(memory) SelfType(NULL, 0, allocator);
1884#else
1885            return new(memory) SelfType(allocator);
1886#endif
1887        }
1888        else
1889        {
1890            return NULL;
1891        }
1892    }
1893
1894    //! @brief        必要なメモリを事前に確保してシグナルを生成します。
1895    //!
1896    //! @param[in]    maxSlots スロットを追加できる最大数です。
1897    //! @param[in]    allocator アロケータです。
1898    //!
1899    static SelfType* CreateFixedSizedSignal(size_t maxSlots, AllocatorType* allocator)
1900    {
1901        void* memory = allocator->Alloc(sizeof(SelfType));
1902        if (memory)
1903        {
1904#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
1905            void* elements = allocator->Alloc(sizeof(SlotType*) * maxSlots);
1906            if (elements != NULL)
1907            {
1908                return new(memory) SelfType(elements, maxSlots, allocator);
1909            }
1910            else
1911            {
1912                allocator->Free(memory);
1913                return NULL;
1914            }
1915#else
1916            NW_UNUSED_VARIABLE(maxSlots);
1917            return new(memory) SelfType(allocator);
1918#endif
1919        }
1920        else
1921        {
1922            return NULL;
1923        }
1924    }
1925
1926    //! @brief 必要になるごとにメモリを確保するシグナルを生成します。
1927    static SelfType* CreateVariableSizeSignal(AllocatorType* allocator)
1928    {
1929        void* memory = allocator->Alloc(sizeof(SelfType));
1930        if (memory)
1931        {
1932            return new(memory) SelfType(allocator);
1933        }
1934        else
1935        {
1936            return NULL;
1937        }
1938    }
1939
1940    //! オブジェクトを破棄します。
1941    void Destroy() { this->~Signal4(); this->m_Allocator->Free(this); }
1942
1943    //@}
1944
1945    //----------------------------------------
1946    //! @name スロット
1947    //@{
1948
1949    //! @brief        スロットと接続し、シグナルが送られるようにする。
1950    //!
1951    //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
1952    //! シグナルに接続できるスロット数は1つになります。
1953    //!
1954    //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
1955    //! Connect する前に必ず Disconnect するようにしてください。
1956    //! Disconnect していない場合は、アサートで停止します。
1957    //!
1958    //! @param[in]    slot スロットです。
1959    //!
1960    void Connect(SlotType* slot)
1961    {
1962#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
1963        bool pushed = this->m_Slots.push_back(slot);
1964        NW_ASSERT(pushed);
1965#else
1966        NW_ASSERT(this->m_Slot == NULL);
1967        this->m_Slot = slot;
1968#endif
1969    }
1970
1971    //! @brief        スロットと接続し、シグナルが送られるようにする。
1972    //!
1973    //! Connect メソッドの追加の成否を取得できるようにしたものです。
1974    //!
1975    //! @param[in]    slot スロットです。
1976    //!
1977    //! @return       追加に成功すると true が返ります。
1978    //!
1979    bool TryConnect(SlotType* slot)
1980    {
1981#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
1982        bool pushed = this->m_Slots.push_back(slot);
1983        return pushed;
1984#else
1985        bool isConnectable = (this->m_Slot == NULL);
1986        if (isConnectable)
1987        {
1988            this->m_Slot = slot;
1989        }
1990        return isConnectable;
1991#endif
1992    }
1993
1994    //! @brief        スロットを作成し、接続します。
1995    //!
1996    //! 内部でメモリを確保します。
1997    //!
1998    //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
1999    //! シグナルに接続できるスロット数は1つになります。
2000    //!
2001    //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
2002    //! Connect する前に必ず Disconnect するようにしてください。
2003    //! Disconnect していない場合は、アサートで停止します。
2004    //!
2005    //! @tparam       TFunction 関数ポインタまたは、関数オブジェクトの型です。
2006    //!
2007    //! @param[in]    function 関数ポインタまたは、関数オブジェクトです。
2008    //! @param[in]    allocator アロケータです。
2009    //!
2010    //! @return       生成されたスロットです。
2011    //!
2012    template<typename TFunction>
2013    SlotType* CreateAndConnect(TFunction function, AllocatorType* allocator)
2014    {
2015        typedef FunctionSlot4<ResultType, TArg0, TArg1, TArg2, TArg3, TFunction, AllocatorType> FunctionSlotType;
2016        FunctionSlotType* slot = CreateSlot<FunctionSlotType>(allocator, function);
2017
2018        this->Connect(slot);
2019        return slot;
2020    }
2021
2022    //! @brief        スロットを作成し、接続します。
2023    //!
2024    //! 内部でメモリを確保します。
2025    //!
2026    //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
2027    //! シグナルに接続できるスロット数は1つになります。
2028    //!
2029    //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
2030    //! Connect する前に必ず Disconnect するようにしてください。
2031    //! Disconnect していない場合は、アサートで停止します。
2032    //!
2033    //! @tparam       TFunction 関数ポインタまたは、関数オブジェクトの型です。
2034    //!
2035    //! @param[in]    function 関数ポインタまたは、関数オブジェクトです。
2036    //!
2037    //! @return       生成されたスロットです。
2038    //!
2039    template<typename TFunction>
2040    SlotType* CreateAndConnect(TFunction function)
2041    {
2042        return CreateAndConnect(function, this->m_Allocator);
2043    }
2044
2045    //! @brief        スロットを切断します。
2046    //!
2047    //! @param[in]    slot 切断するスロットです。
2048    //!
2049    void Disconnect(SlotType* slot)
2050    {
2051#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
2052        this->m_Slots.erase_find(slot);
2053#else
2054        if (this->m_Slot == slot)
2055        {
2056            this->m_Slot = NULL;
2057        }
2058#endif
2059    }
2060
2061    //! @brief        スロットを切断して、破棄します。
2062    //!
2063    //! 関数オブジェクトにアロケータが設定されていると、オブジェクトを破棄します。
2064    //! アロケータが設定されていないと、登録を解除して破棄は行いません。
2065    //!
2066    //! @param[in]    slot 切断するスロットです。
2067    //!
2068    void DisconnectAndDestroy(SlotType* slot)
2069    {
2070#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
2071        this->m_Slots.erase_find(slot);
2072        slot->Destroy();
2073#else
2074        if (this->m_Slot == slot)
2075        {
2076            this->m_Slot = NULL;
2077        }
2078        if (slot)
2079        {
2080            slot->Destroy();
2081        }
2082#endif
2083    }
2084    //@}
2085
2086    //! @brief シグナルを送信します。
2087    ResultType operator()(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3)
2088    {
2089#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
2090        ResultCombinerType combiner;
2091        return combiner(m_Slots.begin(), m_Slots.end(), Invoker(arg0, arg1, arg2, arg3));
2092#else
2093        if (this->m_Slot)
2094        {
2095            return this->m_Slot->Invoke(arg0, arg1, arg2, arg3);
2096        }
2097        else
2098        {
2099            return ResultType();
2100        }
2101#endif
2102    }
2103
2104    //! @brief   CreateInvalidateSignal() の実行に必要なメモリサイズを取得します。
2105    static size_t GetMemorySizeForInvalidateSignal(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT)
2106    {
2107        os::MemorySizeCalculator size(alignment);
2108
2109        GetMemorySizeForInvalidateSignalInternal(&size);
2110
2111        return size.GetSizeWithPadding(alignment);
2112    }
2113
2114    //! @details :private
2115    static void GetMemorySizeForInvalidateSignalInternal(os::MemorySizeCalculator* pSize)
2116    {
2117        os::MemorySizeCalculator& size = *pSize;
2118
2119        size += sizeof(SelfType);
2120    }
2121
2122    //! @brief   CreateFixedSizedSignal() の実行に必要なメモリサイズを取得します。
2123    //!
2124    //! @param[in]    maxSlots スロットを追加できる最大数です。
2125    static size_t GetMemorySizeForFixedSizedSignal(size_t maxSlots, size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT)
2126    {
2127        os::MemorySizeCalculator size(alignment);
2128
2129        GetMemorySizeForFixedSizedSignalInternal(&size, maxSlots);
2130
2131        return size.GetSizeWithPadding(alignment);
2132    }
2133
2134    //! @details :private
2135    static void GetMemorySizeForFixedSizedSignalInternal(os::MemorySizeCalculator* pSize, size_t maxSlots)
2136    {
2137        os::MemorySizeCalculator& size = *pSize;
2138
2139        size += sizeof(SelfType);
2140
2141#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
2142        size += sizeof(SlotType*) * maxSlots;
2143#else
2144        NW_UNUSED_VARIABLE(maxSlots);
2145#endif
2146    }
2147
2148private:
2149#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
2150    //! @brief コンストラクタです。
2151    Signal4(void* elements, size_t maxSlots, AllocatorType* allocator)
2152    : m_Allocator(allocator), m_Slots(elements, maxSlots, allocator) {}
2153    //! @brief コンストラクタです。
2154    explicit Signal4(AllocatorType* allocator)
2155    : m_Allocator(allocator), m_Slots(allocator) {}
2156    //! @brief デストラクタです。
2157    ~Signal4() { DestroyAllSlots(m_Slots); }
2158#else
2159    //! @brief コンストラクタです。
2160    explicit Signal4(AllocatorType* allocator) : m_Allocator(allocator), m_Slot(NULL) {}
2161    //! @brief デストラクタです。
2162    ~Signal4() { SafeDestroy(this->m_Slot); }
2163#endif
2164
2165    AllocatorType* m_Allocator;
2166
2167#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
2168    SlotList m_Slots;
2169#else
2170    SlotType* m_Slot;
2171#endif
2172};
2173
2174//---------------------------------------------------------------------------
2175//! @brief        シグナルを受け取るためのインターフェースです。(引数は 5 個です)
2176//!
2177//! @tparam       TResult 返り値の型です。
2178//! @tparam       TAllocator アロケータの型です。
2179//---------------------------------------------------------------------------
2180template<
2181    typename TResult,
2182    typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4,
2183    typename TAllocator = os::IAllocator
2184>
2185class Slot5
2186{
2187public:
2188    typedef TResult ResultType;
2189    typedef TAllocator AllocatorType;
2190
2191    //! @brief コンストラクタです。
2192    explicit Slot5(AllocatorType* allocator) : m_Allocator(allocator) {}
2193
2194    //! @brief 自らを破棄します。
2195    void Destroy()
2196    {
2197        AllocatorType* allocator = this->GetAllocator();
2198        if (allocator)
2199        {
2200            this->~Slot5();
2201            allocator->Free(this);
2202        }
2203    }
2204
2205    //! @brief 自らを破棄します。
2206    void Destroy(AllocatorType* allocator)
2207    {
2208        NW_NULL_ASSERT(allocator);
2209        this->~Slot5();
2210        allocator->Free(this);
2211    }
2212
2213    //! @brief スロットにシグナルを送信します。
2214    virtual ResultType Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4) = 0;
2215
2216    AllocatorType* GetAllocator() { return m_Allocator; }
2217
2218protected:
2219    //! デストラクタです。
2220    virtual ~Slot5() {}
2221
2222private:
2223    AllocatorType* m_Allocator;
2224};
2225
2226//---------------------------------------------------------------------------
2227//! @brief        シグナルを受け取るためのクラスです。(引数は 5 個です)
2228//!
2229//! @tparam       TResult 返り値の型です。
2230//! @tparam       TFunction 関数か関数オブジェクトの型です。
2231//! @tparam       TAllocator アロケータの型です。
2232//---------------------------------------------------------------------------
2233template<
2234    typename TResult,
2235    typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4,
2236    typename TFunction,
2237    typename TAllocator = os::IAllocator
2238>
2239class FunctionSlot5 : public Slot5<TResult, TArg0, TArg1, TArg2, TArg3, TArg4, TAllocator>
2240{
2241public:
2242    typedef TResult ResultType;
2243    typedef TFunction FunctionType;
2244    typedef TAllocator AllocatorType;
2245
2246    //! コンストラクタです。
2247    FunctionSlot5(AllocatorType* allocator, FunctionType function)
2248    : Slot5<TResult, TArg0, TArg1, TArg2, TArg3, TArg4, TAllocator>(allocator), m_Function(function) {}
2249
2250    //! @brief スロットにシグナルを送信します。
2251    virtual ResultType Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4)
2252    {
2253        return m_Function(arg0, arg1, arg2, arg3, arg4);
2254    }
2255
2256private:
2257    TFunction m_Function;
2258};
2259
2260//---------------------------------------------------------------------------
2261//! @brief        スロットに合図を送るためのクラスです。(引数は 5 個です)
2262//!
2263//! @tparam       TResult 返り値の型です。
2264//! @tparam       TResultCombiner スロットの返り値をまとめて返してくれるコンバイナの型です。
2265//! @tparam       TAllocator アロケータの型です。
2266//! @tparam       TSlot スロットの型です。
2267//---------------------------------------------------------------------------
2268template<
2269    typename TResult,
2270    typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4,
2271    typename TResultCombiner = LastValueResult<TResult>,
2272    typename TAllocator = os::IAllocator,
2273    typename TSlot = Slot5<TResult, TArg0, TArg1, TArg2, TArg3, TArg4, TAllocator>
2274>
2275class Signal5
2276{
2277    NW_DISALLOW_COPY_AND_ASSIGN(Signal5);
2278
2279public:
2280    typedef Signal5<TResult, TArg0, TArg1, TArg2, TArg3, TArg4, TResultCombiner, TAllocator, TSlot> SelfType;
2281    typedef TSlot SlotType;
2282    typedef TResult ResultType;
2283    typedef ut::MoveArray<SlotType*> SlotList;
2284    typedef TResultCombiner ResultCombinerType;
2285    typedef TAllocator AllocatorType;
2286
2287#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
2288    //! @brief スロット実行用関数オブジェクトです。
2289    struct Invoker
2290    {
2291        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) {}
2292        ResultType operator()(SlotType* slot) const
2293        {
2294            return slot->Invoke(m_arg0, m_arg1, m_arg2, m_arg3, m_arg4);
2295        }
2296        TArg0 m_arg0;
2297        TArg1 m_arg1;
2298        TArg2 m_arg2;
2299        TArg3 m_arg3;
2300        TArg4 m_arg4;
2301    };
2302#endif
2303
2304    //----------------------------------------
2305    //! @name 作成/破棄
2306    //@{
2307
2308    //! @brief        無効なシグナルを生成します。
2309    //!
2310    //! @param[in]    allocator アロケータです。
2311    //!
2312    static SelfType* CreateInvalidateSignal(AllocatorType* allocator)
2313    {
2314        void* memory = allocator->Alloc(sizeof(SelfType));
2315        if (memory)
2316        {
2317#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
2318            return new(memory) SelfType(NULL, 0, allocator);
2319#else
2320            return new(memory) SelfType(allocator);
2321#endif
2322        }
2323        else
2324        {
2325            return NULL;
2326        }
2327    }
2328
2329    //! @brief        必要なメモリを事前に確保してシグナルを生成します。
2330    //!
2331    //! @param[in]    maxSlots スロットを追加できる最大数です。
2332    //! @param[in]    allocator アロケータです。
2333    //!
2334    static SelfType* CreateFixedSizedSignal(size_t maxSlots, AllocatorType* allocator)
2335    {
2336        void* memory = allocator->Alloc(sizeof(SelfType));
2337        if (memory)
2338        {
2339#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
2340            void* elements = allocator->Alloc(sizeof(SlotType*) * maxSlots);
2341            if (elements != NULL)
2342            {
2343                return new(memory) SelfType(elements, maxSlots, allocator);
2344            }
2345            else
2346            {
2347                allocator->Free(memory);
2348                return NULL;
2349            }
2350#else
2351            NW_UNUSED_VARIABLE(maxSlots);
2352            return new(memory) SelfType(allocator);
2353#endif
2354        }
2355        else
2356        {
2357            return NULL;
2358        }
2359    }
2360
2361    //! @brief 必要になるごとにメモリを確保するシグナルを生成します。
2362    static SelfType* CreateVariableSizeSignal(AllocatorType* allocator)
2363    {
2364        void* memory = allocator->Alloc(sizeof(SelfType));
2365        if (memory)
2366        {
2367            return new(memory) SelfType(allocator);
2368        }
2369        else
2370        {
2371            return NULL;
2372        }
2373    }
2374
2375    //! オブジェクトを破棄します。
2376    void Destroy() { this->~Signal5(); this->m_Allocator->Free(this); }
2377
2378    //@}
2379
2380    //----------------------------------------
2381    //! @name スロット
2382    //@{
2383
2384    //! @brief        スロットと接続し、シグナルが送られるようにする。
2385    //!
2386    //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
2387    //! シグナルに接続できるスロット数は1つになります。
2388    //!
2389    //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
2390    //! Connect する前に必ず Disconnect するようにしてください。
2391    //! Disconnect していない場合は、アサートで停止します。
2392    //!
2393    //! @param[in]    slot スロットです。
2394    //!
2395    void Connect(SlotType* slot)
2396    {
2397#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
2398        bool pushed = this->m_Slots.push_back(slot);
2399        NW_ASSERT(pushed);
2400#else
2401        NW_ASSERT(this->m_Slot == NULL);
2402        this->m_Slot = slot;
2403#endif
2404    }
2405
2406    //! @brief        スロットと接続し、シグナルが送られるようにする。
2407    //!
2408    //! Connect メソッドの追加の成否を取得できるようにしたものです。
2409    //!
2410    //! @param[in]    slot スロットです。
2411    //!
2412    //! @return       追加に成功すると true が返ります。
2413    //!
2414    bool TryConnect(SlotType* slot)
2415    {
2416#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
2417        bool pushed = this->m_Slots.push_back(slot);
2418        return pushed;
2419#else
2420        bool isConnectable = (this->m_Slot == NULL);
2421        if (isConnectable)
2422        {
2423            this->m_Slot = slot;
2424        }
2425        return isConnectable;
2426#endif
2427    }
2428
2429    //! @brief        スロットを作成し、接続します。
2430    //!
2431    //! 内部でメモリを確保します。
2432    //!
2433    //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
2434    //! シグナルに接続できるスロット数は1つになります。
2435    //!
2436    //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
2437    //! Connect する前に必ず Disconnect するようにしてください。
2438    //! Disconnect していない場合は、アサートで停止します。
2439    //!
2440    //! @tparam       TFunction 関数ポインタまたは、関数オブジェクトの型です。
2441    //!
2442    //! @param[in]    function 関数ポインタまたは、関数オブジェクトです。
2443    //! @param[in]    allocator アロケータです。
2444    //!
2445    //! @return       生成されたスロットです。
2446    //!
2447    template<typename TFunction>
2448    SlotType* CreateAndConnect(TFunction function, AllocatorType* allocator)
2449    {
2450        typedef FunctionSlot5<ResultType, TArg0, TArg1, TArg2, TArg3, TArg4, TFunction, AllocatorType> FunctionSlotType;
2451        FunctionSlotType* slot = CreateSlot<FunctionSlotType>(allocator, function);
2452
2453        this->Connect(slot);
2454        return slot;
2455    }
2456
2457    //! @brief        スロットを作成し、接続します。
2458    //!
2459    //! 内部でメモリを確保します。
2460    //!
2461    //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
2462    //! シグナルに接続できるスロット数は1つになります。
2463    //!
2464    //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
2465    //! Connect する前に必ず Disconnect するようにしてください。
2466    //! Disconnect していない場合は、アサートで停止します。
2467    //!
2468    //! @tparam       TFunction 関数ポインタまたは、関数オブジェクトの型です。
2469    //!
2470    //! @param[in]    function 関数ポインタまたは、関数オブジェクトです。
2471    //!
2472    //! @return       生成されたスロットです。
2473    //!
2474    template<typename TFunction>
2475    SlotType* CreateAndConnect(TFunction function)
2476    {
2477        return CreateAndConnect(function, this->m_Allocator);
2478    }
2479
2480    //! @brief        スロットを切断します。
2481    //!
2482    //! @param[in]    slot 切断するスロットです。
2483    //!
2484    void Disconnect(SlotType* slot)
2485    {
2486#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
2487        this->m_Slots.erase_find(slot);
2488#else
2489        if (this->m_Slot == slot)
2490        {
2491            this->m_Slot = NULL;
2492        }
2493#endif
2494    }
2495
2496    //! @brief        スロットを切断して、破棄します。
2497    //!
2498    //! 関数オブジェクトにアロケータが設定されていると、オブジェクトを破棄します。
2499    //! アロケータが設定されていないと、登録を解除して破棄は行いません。
2500    //!
2501    //! @param[in]    slot 切断するスロットです。
2502    //!
2503    void DisconnectAndDestroy(SlotType* slot)
2504    {
2505#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
2506        this->m_Slots.erase_find(slot);
2507        slot->Destroy();
2508#else
2509        if (this->m_Slot == slot)
2510        {
2511            this->m_Slot = NULL;
2512        }
2513        if (slot)
2514        {
2515            slot->Destroy();
2516        }
2517#endif
2518    }
2519    //@}
2520
2521    //! @brief シグナルを送信します。
2522    ResultType operator()(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4)
2523    {
2524#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
2525        ResultCombinerType combiner;
2526        return combiner(m_Slots.begin(), m_Slots.end(), Invoker(arg0, arg1, arg2, arg3, arg4));
2527#else
2528        if (this->m_Slot)
2529        {
2530            return this->m_Slot->Invoke(arg0, arg1, arg2, arg3, arg4);
2531        }
2532        else
2533        {
2534            return ResultType();
2535        }
2536#endif
2537    }
2538
2539    //! @brief   CreateInvalidateSignal() の実行に必要なメモリサイズを取得します。
2540    static size_t GetMemorySizeForInvalidateSignal(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT)
2541    {
2542        os::MemorySizeCalculator size(alignment);
2543
2544        GetMemorySizeForInvalidateSignalInternal(&size);
2545
2546        return size.GetSizeWithPadding(alignment);
2547    }
2548
2549    //! @details :private
2550    static void GetMemorySizeForInvalidateSignalInternal(os::MemorySizeCalculator* pSize)
2551    {
2552        os::MemorySizeCalculator& size = *pSize;
2553
2554        size += sizeof(SelfType);
2555    }
2556
2557    //! @brief   CreateFixedSizedSignal() の実行に必要なメモリサイズを取得します。
2558    //!
2559    //! @param[in]    maxSlots スロットを追加できる最大数です。
2560    static size_t GetMemorySizeForFixedSizedSignal(size_t maxSlots, size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT)
2561    {
2562        os::MemorySizeCalculator size(alignment);
2563
2564        GetMemorySizeForFixedSizedSignalInternal(&size, maxSlots);
2565
2566        return size.GetSizeWithPadding(alignment);
2567    }
2568
2569    //! @details :private
2570    static void GetMemorySizeForFixedSizedSignalInternal(os::MemorySizeCalculator* pSize, size_t maxSlots)
2571    {
2572        os::MemorySizeCalculator& size = *pSize;
2573
2574        size += sizeof(SelfType);
2575
2576#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
2577        size += sizeof(SlotType*) * maxSlots;
2578#else
2579        NW_UNUSED_VARIABLE(maxSlots);
2580#endif
2581    }
2582
2583private:
2584#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
2585    //! @brief コンストラクタです。
2586    Signal5(void* elements, size_t maxSlots, AllocatorType* allocator)
2587    : m_Allocator(allocator), m_Slots(elements, maxSlots, allocator) {}
2588    //! @brief コンストラクタです。
2589    explicit Signal5(AllocatorType* allocator)
2590    : m_Allocator(allocator), m_Slots(allocator) {}
2591    //! @brief デストラクタです。
2592    ~Signal5() { DestroyAllSlots(m_Slots); }
2593#else
2594    //! @brief コンストラクタです。
2595    explicit Signal5(AllocatorType* allocator) : m_Allocator(allocator), m_Slot(NULL) {}
2596    //! @brief デストラクタです。
2597    ~Signal5() { SafeDestroy(this->m_Slot); }
2598#endif
2599
2600    AllocatorType* m_Allocator;
2601
2602#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
2603    SlotList m_Slots;
2604#else
2605    SlotType* m_Slot;
2606#endif
2607};
2608
2609//---------------------------------------------------------------------------
2610//! @brief        シグナルを受け取るためのインターフェースです。(引数は 6 個です)
2611//!
2612//! @tparam       TResult 返り値の型です。
2613//! @tparam       TAllocator アロケータの型です。
2614//---------------------------------------------------------------------------
2615template<
2616    typename TResult,
2617    typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5,
2618    typename TAllocator = os::IAllocator
2619>
2620class Slot6
2621{
2622public:
2623    typedef TResult ResultType;
2624    typedef TAllocator AllocatorType;
2625
2626    //! @brief コンストラクタです。
2627    explicit Slot6(AllocatorType* allocator) : m_Allocator(allocator) {}
2628
2629    //! @brief 自らを破棄します。
2630    void Destroy()
2631    {
2632        AllocatorType* allocator = this->GetAllocator();
2633        if (allocator)
2634        {
2635            this->~Slot6();
2636            allocator->Free(this);
2637        }
2638    }
2639
2640    //! @brief 自らを破棄します。
2641    void Destroy(AllocatorType* allocator)
2642    {
2643        NW_NULL_ASSERT(allocator);
2644        this->~Slot6();
2645        allocator->Free(this);
2646    }
2647
2648    //! @brief スロットにシグナルを送信します。
2649    virtual ResultType Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5) = 0;
2650
2651    AllocatorType* GetAllocator() { return m_Allocator; }
2652
2653protected:
2654    //! デストラクタです。
2655    virtual ~Slot6() {}
2656
2657private:
2658    AllocatorType* m_Allocator;
2659};
2660
2661//---------------------------------------------------------------------------
2662//! @brief        シグナルを受け取るためのクラスです。(引数は 6 個です)
2663//!
2664//! @tparam       TResult 返り値の型です。
2665//! @tparam       TFunction 関数か関数オブジェクトの型です。
2666//! @tparam       TAllocator アロケータの型です。
2667//---------------------------------------------------------------------------
2668template<
2669    typename TResult,
2670    typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5,
2671    typename TFunction,
2672    typename TAllocator = os::IAllocator
2673>
2674class FunctionSlot6 : public Slot6<TResult, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TAllocator>
2675{
2676public:
2677    typedef TResult ResultType;
2678    typedef TFunction FunctionType;
2679    typedef TAllocator AllocatorType;
2680
2681    //! コンストラクタです。
2682    FunctionSlot6(AllocatorType* allocator, FunctionType function)
2683    : Slot6<TResult, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TAllocator>(allocator), m_Function(function) {}
2684
2685    //! @brief スロットにシグナルを送信します。
2686    virtual ResultType Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5)
2687    {
2688        return m_Function(arg0, arg1, arg2, arg3, arg4, arg5);
2689    }
2690
2691private:
2692    TFunction m_Function;
2693};
2694
2695//---------------------------------------------------------------------------
2696//! @brief        スロットに合図を送るためのクラスです。(引数は 6 個です)
2697//!
2698//! @tparam       TResult 返り値の型です。
2699//! @tparam       TResultCombiner スロットの返り値をまとめて返してくれるコンバイナの型です。
2700//! @tparam       TAllocator アロケータの型です。
2701//! @tparam       TSlot スロットの型です。
2702//---------------------------------------------------------------------------
2703template<
2704    typename TResult,
2705    typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5,
2706    typename TResultCombiner = LastValueResult<TResult>,
2707    typename TAllocator = os::IAllocator,
2708    typename TSlot = Slot6<TResult, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TAllocator>
2709>
2710class Signal6
2711{
2712    NW_DISALLOW_COPY_AND_ASSIGN(Signal6);
2713
2714public:
2715    typedef Signal6<TResult, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TResultCombiner, TAllocator, TSlot> SelfType;
2716    typedef TSlot SlotType;
2717    typedef TResult ResultType;
2718    typedef ut::MoveArray<SlotType*> SlotList;
2719    typedef TResultCombiner ResultCombinerType;
2720    typedef TAllocator AllocatorType;
2721
2722#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
2723    //! @brief スロット実行用関数オブジェクトです。
2724    struct Invoker
2725    {
2726        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) {}
2727        ResultType operator()(SlotType* slot) const
2728        {
2729            return slot->Invoke(m_arg0, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5);
2730        }
2731        TArg0 m_arg0;
2732        TArg1 m_arg1;
2733        TArg2 m_arg2;
2734        TArg3 m_arg3;
2735        TArg4 m_arg4;
2736        TArg5 m_arg5;
2737    };
2738#endif
2739
2740    //----------------------------------------
2741    //! @name 作成/破棄
2742    //@{
2743
2744    //! @brief        無効なシグナルを生成します。
2745    //!
2746    //! @param[in]    allocator アロケータです。
2747    //!
2748    static SelfType* CreateInvalidateSignal(AllocatorType* allocator)
2749    {
2750        void* memory = allocator->Alloc(sizeof(SelfType));
2751        if (memory)
2752        {
2753#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
2754            return new(memory) SelfType(NULL, 0, allocator);
2755#else
2756            return new(memory) SelfType(allocator);
2757#endif
2758        }
2759        else
2760        {
2761            return NULL;
2762        }
2763    }
2764
2765    //! @brief        必要なメモリを事前に確保してシグナルを生成します。
2766    //!
2767    //! @param[in]    maxSlots スロットを追加できる最大数です。
2768    //! @param[in]    allocator アロケータです。
2769    //!
2770    static SelfType* CreateFixedSizedSignal(size_t maxSlots, AllocatorType* allocator)
2771    {
2772        void* memory = allocator->Alloc(sizeof(SelfType));
2773        if (memory)
2774        {
2775#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
2776            void* elements = allocator->Alloc(sizeof(SlotType*) * maxSlots);
2777            if (elements != NULL)
2778            {
2779                return new(memory) SelfType(elements, maxSlots, allocator);
2780            }
2781            else
2782            {
2783                allocator->Free(memory);
2784                return NULL;
2785            }
2786#else
2787            NW_UNUSED_VARIABLE(maxSlots);
2788            return new(memory) SelfType(allocator);
2789#endif
2790        }
2791        else
2792        {
2793            return NULL;
2794        }
2795    }
2796
2797    //! @brief 必要になるごとにメモリを確保するシグナルを生成します。
2798    static SelfType* CreateVariableSizeSignal(AllocatorType* allocator)
2799    {
2800        void* memory = allocator->Alloc(sizeof(SelfType));
2801        if (memory)
2802        {
2803            return new(memory) SelfType(allocator);
2804        }
2805        else
2806        {
2807            return NULL;
2808        }
2809    }
2810
2811    //! オブジェクトを破棄します。
2812    void Destroy() { this->~Signal6(); this->m_Allocator->Free(this); }
2813
2814    //@}
2815
2816    //----------------------------------------
2817    //! @name スロット
2818    //@{
2819
2820    //! @brief        スロットと接続し、シグナルが送られるようにする。
2821    //!
2822    //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
2823    //! シグナルに接続できるスロット数は1つになります。
2824    //!
2825    //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
2826    //! Connect する前に必ず Disconnect するようにしてください。
2827    //! Disconnect していない場合は、アサートで停止します。
2828    //!
2829    //! @param[in]    slot スロットです。
2830    //!
2831    void Connect(SlotType* slot)
2832    {
2833#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
2834        bool pushed = this->m_Slots.push_back(slot);
2835        NW_ASSERT(pushed);
2836#else
2837        NW_ASSERT(this->m_Slot == NULL);
2838        this->m_Slot = slot;
2839#endif
2840    }
2841
2842    //! @brief        スロットと接続し、シグナルが送られるようにする。
2843    //!
2844    //! Connect メソッドの追加の成否を取得できるようにしたものです。
2845    //!
2846    //! @param[in]    slot スロットです。
2847    //!
2848    //! @return       追加に成功すると true が返ります。
2849    //!
2850    bool TryConnect(SlotType* slot)
2851    {
2852#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
2853        bool pushed = this->m_Slots.push_back(slot);
2854        return pushed;
2855#else
2856        bool isConnectable = (this->m_Slot == NULL);
2857        if (isConnectable)
2858        {
2859            this->m_Slot = slot;
2860        }
2861        return isConnectable;
2862#endif
2863    }
2864
2865    //! @brief        スロットを作成し、接続します。
2866    //!
2867    //! 内部でメモリを確保します。
2868    //!
2869    //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
2870    //! シグナルに接続できるスロット数は1つになります。
2871    //!
2872    //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
2873    //! Connect する前に必ず Disconnect するようにしてください。
2874    //! Disconnect していない場合は、アサートで停止します。
2875    //!
2876    //! @tparam       TFunction 関数ポインタまたは、関数オブジェクトの型です。
2877    //!
2878    //! @param[in]    function 関数ポインタまたは、関数オブジェクトです。
2879    //! @param[in]    allocator アロケータです。
2880    //!
2881    //! @return       生成されたスロットです。
2882    //!
2883    template<typename TFunction>
2884    SlotType* CreateAndConnect(TFunction function, AllocatorType* allocator)
2885    {
2886        typedef FunctionSlot6<ResultType, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TFunction, AllocatorType> FunctionSlotType;
2887        FunctionSlotType* slot = CreateSlot<FunctionSlotType>(allocator, function);
2888
2889        this->Connect(slot);
2890        return slot;
2891    }
2892
2893    //! @brief        スロットを作成し、接続します。
2894    //!
2895    //! 内部でメモリを確保します。
2896    //!
2897    //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
2898    //! シグナルに接続できるスロット数は1つになります。
2899    //!
2900    //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
2901    //! Connect する前に必ず Disconnect するようにしてください。
2902    //! Disconnect していない場合は、アサートで停止します。
2903    //!
2904    //! @tparam       TFunction 関数ポインタまたは、関数オブジェクトの型です。
2905    //!
2906    //! @param[in]    function 関数ポインタまたは、関数オブジェクトです。
2907    //!
2908    //! @return       生成されたスロットです。
2909    //!
2910    template<typename TFunction>
2911    SlotType* CreateAndConnect(TFunction function)
2912    {
2913        return CreateAndConnect(function, this->m_Allocator);
2914    }
2915
2916    //! @brief        スロットを切断します。
2917    //!
2918    //! @param[in]    slot 切断するスロットです。
2919    //!
2920    void Disconnect(SlotType* slot)
2921    {
2922#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
2923        this->m_Slots.erase_find(slot);
2924#else
2925        if (this->m_Slot == slot)
2926        {
2927            this->m_Slot = NULL;
2928        }
2929#endif
2930    }
2931
2932    //! @brief        スロットを切断して、破棄します。
2933    //!
2934    //! 関数オブジェクトにアロケータが設定されていると、オブジェクトを破棄します。
2935    //! アロケータが設定されていないと、登録を解除して破棄は行いません。
2936    //!
2937    //! @param[in]    slot 切断するスロットです。
2938    //!
2939    void DisconnectAndDestroy(SlotType* slot)
2940    {
2941#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
2942        this->m_Slots.erase_find(slot);
2943        slot->Destroy();
2944#else
2945        if (this->m_Slot == slot)
2946        {
2947            this->m_Slot = NULL;
2948        }
2949        if (slot)
2950        {
2951            slot->Destroy();
2952        }
2953#endif
2954    }
2955    //@}
2956
2957    //! @brief シグナルを送信します。
2958    ResultType operator()(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5)
2959    {
2960#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
2961        ResultCombinerType combiner;
2962        return combiner(m_Slots.begin(), m_Slots.end(), Invoker(arg0, arg1, arg2, arg3, arg4, arg5));
2963#else
2964        if (this->m_Slot)
2965        {
2966            return this->m_Slot->Invoke(arg0, arg1, arg2, arg3, arg4, arg5);
2967        }
2968        else
2969        {
2970            return ResultType();
2971        }
2972#endif
2973    }
2974
2975    //! @brief   CreateInvalidateSignal() の実行に必要なメモリサイズを取得します。
2976    static size_t GetMemorySizeForInvalidateSignal(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT)
2977    {
2978        os::MemorySizeCalculator size(alignment);
2979
2980        GetMemorySizeForInvalidateSignalInternal(&size);
2981
2982        return size.GetSizeWithPadding(alignment);
2983    }
2984
2985    //! @details :private
2986    static void GetMemorySizeForInvalidateSignalInternal(os::MemorySizeCalculator* pSize)
2987    {
2988        os::MemorySizeCalculator& size = *pSize;
2989
2990        size += sizeof(SelfType);
2991    }
2992
2993    //! @brief   CreateFixedSizedSignal() の実行に必要なメモリサイズを取得します。
2994    //!
2995    //! @param[in]    maxSlots スロットを追加できる最大数です。
2996    static size_t GetMemorySizeForFixedSizedSignal(size_t maxSlots, size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT)
2997    {
2998        os::MemorySizeCalculator size(alignment);
2999
3000        GetMemorySizeForFixedSizedSignalInternal(&size, maxSlots);
3001
3002        return size.GetSizeWithPadding(alignment);
3003    }
3004
3005    //! @details :private
3006    static void GetMemorySizeForFixedSizedSignalInternal(os::MemorySizeCalculator* pSize, size_t maxSlots)
3007    {
3008        os::MemorySizeCalculator& size = *pSize;
3009
3010        size += sizeof(SelfType);
3011
3012#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
3013        size += sizeof(SlotType*) * maxSlots;
3014#else
3015        NW_UNUSED_VARIABLE(maxSlots);
3016#endif
3017    }
3018
3019private:
3020#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
3021    //! @brief コンストラクタです。
3022    Signal6(void* elements, size_t maxSlots, AllocatorType* allocator)
3023    : m_Allocator(allocator), m_Slots(elements, maxSlots, allocator) {}
3024    //! @brief コンストラクタです。
3025    explicit Signal6(AllocatorType* allocator)
3026    : m_Allocator(allocator), m_Slots(allocator) {}
3027    //! @brief デストラクタです。
3028    ~Signal6() { DestroyAllSlots(m_Slots); }
3029#else
3030    //! @brief コンストラクタです。
3031    explicit Signal6(AllocatorType* allocator) : m_Allocator(allocator), m_Slot(NULL) {}
3032    //! @brief デストラクタです。
3033    ~Signal6() { SafeDestroy(this->m_Slot); }
3034#endif
3035
3036    AllocatorType* m_Allocator;
3037
3038#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
3039    SlotList m_Slots;
3040#else
3041    SlotType* m_Slot;
3042#endif
3043};
3044
3045//---------------------------------------------------------------------------
3046//! @brief        シグナルを受け取るためのインターフェースです。(引数は 7 個です)
3047//!
3048//! @tparam       TResult 返り値の型です。
3049//! @tparam       TAllocator アロケータの型です。
3050//---------------------------------------------------------------------------
3051template<
3052    typename TResult,
3053    typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename TArg6,
3054    typename TAllocator = os::IAllocator
3055>
3056class Slot7
3057{
3058public:
3059    typedef TResult ResultType;
3060    typedef TAllocator AllocatorType;
3061
3062    //! @brief コンストラクタです。
3063    explicit Slot7(AllocatorType* allocator) : m_Allocator(allocator) {}
3064
3065    //! @brief 自らを破棄します。
3066    void Destroy()
3067    {
3068        AllocatorType* allocator = this->GetAllocator();
3069        if (allocator)
3070        {
3071            this->~Slot7();
3072            allocator->Free(this);
3073        }
3074    }
3075
3076    //! @brief 自らを破棄します。
3077    void Destroy(AllocatorType* allocator)
3078    {
3079        NW_NULL_ASSERT(allocator);
3080        this->~Slot7();
3081        allocator->Free(this);
3082    }
3083
3084    //! @brief スロットにシグナルを送信します。
3085    virtual ResultType Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6) = 0;
3086
3087    AllocatorType* GetAllocator() { return m_Allocator; }
3088
3089protected:
3090    //! デストラクタです。
3091    virtual ~Slot7() {}
3092
3093private:
3094    AllocatorType* m_Allocator;
3095};
3096
3097//---------------------------------------------------------------------------
3098//! @brief        シグナルを受け取るためのクラスです。(引数は 7 個です)
3099//!
3100//! @tparam       TResult 返り値の型です。
3101//! @tparam       TFunction 関数か関数オブジェクトの型です。
3102//! @tparam       TAllocator アロケータの型です。
3103//---------------------------------------------------------------------------
3104template<
3105    typename TResult,
3106    typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename TArg6,
3107    typename TFunction,
3108    typename TAllocator = os::IAllocator
3109>
3110class FunctionSlot7 : public Slot7<TResult, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TAllocator>
3111{
3112public:
3113    typedef TResult ResultType;
3114    typedef TFunction FunctionType;
3115    typedef TAllocator AllocatorType;
3116
3117    //! コンストラクタです。
3118    FunctionSlot7(AllocatorType* allocator, FunctionType function)
3119    : Slot7<TResult, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TAllocator>(allocator), m_Function(function) {}
3120
3121    //! @brief スロットにシグナルを送信します。
3122    virtual ResultType Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6)
3123    {
3124        return m_Function(arg0, arg1, arg2, arg3, arg4, arg5, arg6);
3125    }
3126
3127private:
3128    TFunction m_Function;
3129};
3130
3131//---------------------------------------------------------------------------
3132//! @brief        スロットに合図を送るためのクラスです。(引数は 7 個です)
3133//!
3134//! @tparam       TResult 返り値の型です。
3135//! @tparam       TResultCombiner スロットの返り値をまとめて返してくれるコンバイナの型です。
3136//! @tparam       TAllocator アロケータの型です。
3137//! @tparam       TSlot スロットの型です。
3138//---------------------------------------------------------------------------
3139template<
3140    typename TResult,
3141    typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename TArg6,
3142    typename TResultCombiner = LastValueResult<TResult>,
3143    typename TAllocator = os::IAllocator,
3144    typename TSlot = Slot7<TResult, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TAllocator>
3145>
3146class Signal7
3147{
3148    NW_DISALLOW_COPY_AND_ASSIGN(Signal7);
3149
3150public:
3151    typedef Signal7<TResult, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TResultCombiner, TAllocator, TSlot> SelfType;
3152    typedef TSlot SlotType;
3153    typedef TResult ResultType;
3154    typedef ut::MoveArray<SlotType*> SlotList;
3155    typedef TResultCombiner ResultCombinerType;
3156    typedef TAllocator AllocatorType;
3157
3158#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
3159    //! @brief スロット実行用関数オブジェクトです。
3160    struct Invoker
3161    {
3162        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) {}
3163        ResultType operator()(SlotType* slot) const
3164        {
3165            return slot->Invoke(m_arg0, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6);
3166        }
3167        TArg0 m_arg0;
3168        TArg1 m_arg1;
3169        TArg2 m_arg2;
3170        TArg3 m_arg3;
3171        TArg4 m_arg4;
3172        TArg5 m_arg5;
3173        TArg6 m_arg6;
3174    };
3175#endif
3176
3177    //----------------------------------------
3178    //! @name 作成/破棄
3179    //@{
3180
3181    //! @brief        無効なシグナルを生成します。
3182    //!
3183    //! @param[in]    allocator アロケータです。
3184    //!
3185    static SelfType* CreateInvalidateSignal(AllocatorType* allocator)
3186    {
3187        void* memory = allocator->Alloc(sizeof(SelfType));
3188        if (memory)
3189        {
3190#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
3191            return new(memory) SelfType(NULL, 0, allocator);
3192#else
3193            return new(memory) SelfType(allocator);
3194#endif
3195        }
3196        else
3197        {
3198            return NULL;
3199        }
3200    }
3201
3202    //! @brief        必要なメモリを事前に確保してシグナルを生成します。
3203    //!
3204    //! @param[in]    maxSlots スロットを追加できる最大数です。
3205    //! @param[in]    allocator アロケータです。
3206    //!
3207    static SelfType* CreateFixedSizedSignal(size_t maxSlots, AllocatorType* allocator)
3208    {
3209        void* memory = allocator->Alloc(sizeof(SelfType));
3210        if (memory)
3211        {
3212#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
3213            void* elements = allocator->Alloc(sizeof(SlotType*) * maxSlots);
3214            if (elements != NULL)
3215            {
3216                return new(memory) SelfType(elements, maxSlots, allocator);
3217            }
3218            else
3219            {
3220                allocator->Free(memory);
3221                return NULL;
3222            }
3223#else
3224            NW_UNUSED_VARIABLE(maxSlots);
3225            return new(memory) SelfType(allocator);
3226#endif
3227        }
3228        else
3229        {
3230            return NULL;
3231        }
3232    }
3233
3234    //! @brief 必要になるごとにメモリを確保するシグナルを生成します。
3235    static SelfType* CreateVariableSizeSignal(AllocatorType* allocator)
3236    {
3237        void* memory = allocator->Alloc(sizeof(SelfType));
3238        if (memory)
3239        {
3240            return new(memory) SelfType(allocator);
3241        }
3242        else
3243        {
3244            return NULL;
3245        }
3246    }
3247
3248    //! オブジェクトを破棄します。
3249    void Destroy() { this->~Signal7(); this->m_Allocator->Free(this); }
3250
3251    //@}
3252
3253    //----------------------------------------
3254    //! @name スロット
3255    //@{
3256
3257    //! @brief        スロットと接続し、シグナルが送られるようにする。
3258    //!
3259    //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
3260    //! シグナルに接続できるスロット数は1つになります。
3261    //!
3262    //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
3263    //! Connect する前に必ず Disconnect するようにしてください。
3264    //! Disconnect していない場合は、アサートで停止します。
3265    //!
3266    //! @param[in]    slot スロットです。
3267    //!
3268    void Connect(SlotType* slot)
3269    {
3270#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
3271        bool pushed = this->m_Slots.push_back(slot);
3272        NW_ASSERT(pushed);
3273#else
3274        NW_ASSERT(this->m_Slot == NULL);
3275        this->m_Slot = slot;
3276#endif
3277    }
3278
3279    //! @brief        スロットと接続し、シグナルが送られるようにする。
3280    //!
3281    //! Connect メソッドの追加の成否を取得できるようにしたものです。
3282    //!
3283    //! @param[in]    slot スロットです。
3284    //!
3285    //! @return       追加に成功すると true が返ります。
3286    //!
3287    bool TryConnect(SlotType* slot)
3288    {
3289#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
3290        bool pushed = this->m_Slots.push_back(slot);
3291        return pushed;
3292#else
3293        bool isConnectable = (this->m_Slot == NULL);
3294        if (isConnectable)
3295        {
3296            this->m_Slot = slot;
3297        }
3298        return isConnectable;
3299#endif
3300    }
3301
3302    //! @brief        スロットを作成し、接続します。
3303    //!
3304    //! 内部でメモリを確保します。
3305    //!
3306    //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
3307    //! シグナルに接続できるスロット数は1つになります。
3308    //!
3309    //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
3310    //! Connect する前に必ず Disconnect するようにしてください。
3311    //! Disconnect していない場合は、アサートで停止します。
3312    //!
3313    //! @tparam       TFunction 関数ポインタまたは、関数オブジェクトの型です。
3314    //!
3315    //! @param[in]    function 関数ポインタまたは、関数オブジェクトです。
3316    //! @param[in]    allocator アロケータです。
3317    //!
3318    //! @return       生成されたスロットです。
3319    //!
3320    template<typename TFunction>
3321    SlotType* CreateAndConnect(TFunction function, AllocatorType* allocator)
3322    {
3323        typedef FunctionSlot7<ResultType, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TFunction, AllocatorType> FunctionSlotType;
3324        FunctionSlotType* slot = CreateSlot<FunctionSlotType>(allocator, function);
3325
3326        this->Connect(slot);
3327        return slot;
3328    }
3329
3330    //! @brief        スロットを作成し、接続します。
3331    //!
3332    //! 内部でメモリを確保します。
3333    //!
3334    //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
3335    //! シグナルに接続できるスロット数は1つになります。
3336    //!
3337    //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
3338    //! Connect する前に必ず Disconnect するようにしてください。
3339    //! Disconnect していない場合は、アサートで停止します。
3340    //!
3341    //! @tparam       TFunction 関数ポインタまたは、関数オブジェクトの型です。
3342    //!
3343    //! @param[in]    function 関数ポインタまたは、関数オブジェクトです。
3344    //!
3345    //! @return       生成されたスロットです。
3346    //!
3347    template<typename TFunction>
3348    SlotType* CreateAndConnect(TFunction function)
3349    {
3350        return CreateAndConnect(function, this->m_Allocator);
3351    }
3352
3353    //! @brief        スロットを切断します。
3354    //!
3355    //! @param[in]    slot 切断するスロットです。
3356    //!
3357    void Disconnect(SlotType* slot)
3358    {
3359#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
3360        this->m_Slots.erase_find(slot);
3361#else
3362        if (this->m_Slot == slot)
3363        {
3364            this->m_Slot = NULL;
3365        }
3366#endif
3367    }
3368
3369    //! @brief        スロットを切断して、破棄します。
3370    //!
3371    //! 関数オブジェクトにアロケータが設定されていると、オブジェクトを破棄します。
3372    //! アロケータが設定されていないと、登録を解除して破棄は行いません。
3373    //!
3374    //! @param[in]    slot 切断するスロットです。
3375    //!
3376    void DisconnectAndDestroy(SlotType* slot)
3377    {
3378#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
3379        this->m_Slots.erase_find(slot);
3380        slot->Destroy();
3381#else
3382        if (this->m_Slot == slot)
3383        {
3384            this->m_Slot = NULL;
3385        }
3386        if (slot)
3387        {
3388            slot->Destroy();
3389        }
3390#endif
3391    }
3392    //@}
3393
3394    //! @brief シグナルを送信します。
3395    ResultType operator()(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6)
3396    {
3397#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
3398        ResultCombinerType combiner;
3399        return combiner(m_Slots.begin(), m_Slots.end(), Invoker(arg0, arg1, arg2, arg3, arg4, arg5, arg6));
3400#else
3401        if (this->m_Slot)
3402        {
3403            return this->m_Slot->Invoke(arg0, arg1, arg2, arg3, arg4, arg5, arg6);
3404        }
3405        else
3406        {
3407            return ResultType();
3408        }
3409#endif
3410    }
3411
3412    //! @brief   CreateInvalidateSignal() の実行に必要なメモリサイズを取得します。
3413    static size_t GetMemorySizeForInvalidateSignal(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT)
3414    {
3415        os::MemorySizeCalculator size(alignment);
3416
3417        GetMemorySizeForInvalidateSignalInternal(&size);
3418
3419        return size.GetSizeWithPadding(alignment);
3420    }
3421
3422    //! @details :private
3423    static void GetMemorySizeForInvalidateSignalInternal(os::MemorySizeCalculator* pSize)
3424    {
3425        os::MemorySizeCalculator& size = *pSize;
3426
3427        size += sizeof(SelfType);
3428    }
3429
3430    //! @brief   CreateFixedSizedSignal() の実行に必要なメモリサイズを取得します。
3431    //!
3432    //! @param[in]    maxSlots スロットを追加できる最大数です。
3433    static size_t GetMemorySizeForFixedSizedSignal(size_t maxSlots, size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT)
3434    {
3435        os::MemorySizeCalculator size(alignment);
3436
3437        GetMemorySizeForFixedSizedSignalInternal(&size, maxSlots);
3438
3439        return size.GetSizeWithPadding(alignment);
3440    }
3441
3442    //! @details :private
3443    static void GetMemorySizeForFixedSizedSignalInternal(os::MemorySizeCalculator* pSize, size_t maxSlots)
3444    {
3445        os::MemorySizeCalculator& size = *pSize;
3446
3447        size += sizeof(SelfType);
3448
3449#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
3450        size += sizeof(SlotType*) * maxSlots;
3451#else
3452        NW_UNUSED_VARIABLE(maxSlots);
3453#endif
3454    }
3455
3456private:
3457#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
3458    //! @brief コンストラクタです。
3459    Signal7(void* elements, size_t maxSlots, AllocatorType* allocator)
3460    : m_Allocator(allocator), m_Slots(elements, maxSlots, allocator) {}
3461    //! @brief コンストラクタです。
3462    explicit Signal7(AllocatorType* allocator)
3463    : m_Allocator(allocator), m_Slots(allocator) {}
3464    //! @brief デストラクタです。
3465    ~Signal7() { DestroyAllSlots(m_Slots); }
3466#else
3467    //! @brief コンストラクタです。
3468    explicit Signal7(AllocatorType* allocator) : m_Allocator(allocator), m_Slot(NULL) {}
3469    //! @brief デストラクタです。
3470    ~Signal7() { SafeDestroy(this->m_Slot); }
3471#endif
3472
3473    AllocatorType* m_Allocator;
3474
3475#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
3476    SlotList m_Slots;
3477#else
3478    SlotType* m_Slot;
3479#endif
3480};
3481
3482//---------------------------------------------------------------------------
3483//! @brief        シグナルを受け取るためのインターフェースです。(引数は 8 個です)
3484//!
3485//! @tparam       TResult 返り値の型です。
3486//! @tparam       TAllocator アロケータの型です。
3487//---------------------------------------------------------------------------
3488template<
3489    typename TResult,
3490    typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename TArg6, typename TArg7,
3491    typename TAllocator = os::IAllocator
3492>
3493class Slot8
3494{
3495public:
3496    typedef TResult ResultType;
3497    typedef TAllocator AllocatorType;
3498
3499    //! @brief コンストラクタです。
3500    explicit Slot8(AllocatorType* allocator) : m_Allocator(allocator) {}
3501
3502    //! @brief 自らを破棄します。
3503    void Destroy()
3504    {
3505        AllocatorType* allocator = this->GetAllocator();
3506        if (allocator)
3507        {
3508            this->~Slot8();
3509            allocator->Free(this);
3510        }
3511    }
3512
3513    //! @brief 自らを破棄します。
3514    void Destroy(AllocatorType* allocator)
3515    {
3516        NW_NULL_ASSERT(allocator);
3517        this->~Slot8();
3518        allocator->Free(this);
3519    }
3520
3521    //! @brief スロットにシグナルを送信します。
3522    virtual ResultType Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6, TArg7 arg7) = 0;
3523
3524    AllocatorType* GetAllocator() { return m_Allocator; }
3525
3526protected:
3527    //! デストラクタです。
3528    virtual ~Slot8() {}
3529
3530private:
3531    AllocatorType* m_Allocator;
3532};
3533
3534//---------------------------------------------------------------------------
3535//! @brief        シグナルを受け取るためのクラスです。(引数は 8 個です)
3536//!
3537//! @tparam       TResult 返り値の型です。
3538//! @tparam       TFunction 関数か関数オブジェクトの型です。
3539//! @tparam       TAllocator アロケータの型です。
3540//---------------------------------------------------------------------------
3541template<
3542    typename TResult,
3543    typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename TArg6, typename TArg7,
3544    typename TFunction,
3545    typename TAllocator = os::IAllocator
3546>
3547class FunctionSlot8 : public Slot8<TResult, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TAllocator>
3548{
3549public:
3550    typedef TResult ResultType;
3551    typedef TFunction FunctionType;
3552    typedef TAllocator AllocatorType;
3553
3554    //! コンストラクタです。
3555    FunctionSlot8(AllocatorType* allocator, FunctionType function)
3556    : Slot8<TResult, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TAllocator>(allocator), m_Function(function) {}
3557
3558    //! @brief スロットにシグナルを送信します。
3559    virtual ResultType Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6, TArg7 arg7)
3560    {
3561        return m_Function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
3562    }
3563
3564private:
3565    TFunction m_Function;
3566};
3567
3568//---------------------------------------------------------------------------
3569//! @brief        スロットに合図を送るためのクラスです。(引数は 8 個です)
3570//!
3571//! @tparam       TResult 返り値の型です。
3572//! @tparam       TResultCombiner スロットの返り値をまとめて返してくれるコンバイナの型です。
3573//! @tparam       TAllocator アロケータの型です。
3574//! @tparam       TSlot スロットの型です。
3575//---------------------------------------------------------------------------
3576template<
3577    typename TResult,
3578    typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename TArg6, typename TArg7,
3579    typename TResultCombiner = LastValueResult<TResult>,
3580    typename TAllocator = os::IAllocator,
3581    typename TSlot = Slot8<TResult, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TAllocator>
3582>
3583class Signal8
3584{
3585    NW_DISALLOW_COPY_AND_ASSIGN(Signal8);
3586
3587public:
3588    typedef Signal8<TResult, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TResultCombiner, TAllocator, TSlot> SelfType;
3589    typedef TSlot SlotType;
3590    typedef TResult ResultType;
3591    typedef ut::MoveArray<SlotType*> SlotList;
3592    typedef TResultCombiner ResultCombinerType;
3593    typedef TAllocator AllocatorType;
3594
3595#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
3596    //! @brief スロット実行用関数オブジェクトです。
3597    struct Invoker
3598    {
3599        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) {}
3600        ResultType operator()(SlotType* slot) const
3601        {
3602            return slot->Invoke(m_arg0, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7);
3603        }
3604        TArg0 m_arg0;
3605        TArg1 m_arg1;
3606        TArg2 m_arg2;
3607        TArg3 m_arg3;
3608        TArg4 m_arg4;
3609        TArg5 m_arg5;
3610        TArg6 m_arg6;
3611        TArg7 m_arg7;
3612    };
3613#endif
3614
3615    //----------------------------------------
3616    //! @name 作成/破棄
3617    //@{
3618
3619    //! @brief        無効なシグナルを生成します。
3620    //!
3621    //! @param[in]    allocator アロケータです。
3622    //!
3623    static SelfType* CreateInvalidateSignal(AllocatorType* allocator)
3624    {
3625        void* memory = allocator->Alloc(sizeof(SelfType));
3626        if (memory)
3627        {
3628#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
3629            return new(memory) SelfType(NULL, 0, allocator);
3630#else
3631            return new(memory) SelfType(allocator);
3632#endif
3633        }
3634        else
3635        {
3636            return NULL;
3637        }
3638    }
3639
3640    //! @brief        必要なメモリを事前に確保してシグナルを生成します。
3641    //!
3642    //! @param[in]    maxSlots スロットを追加できる最大数です。
3643    //! @param[in]    allocator アロケータです。
3644    //!
3645    static SelfType* CreateFixedSizedSignal(size_t maxSlots, AllocatorType* allocator)
3646    {
3647        void* memory = allocator->Alloc(sizeof(SelfType));
3648        if (memory)
3649        {
3650#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
3651            void* elements = allocator->Alloc(sizeof(SlotType*) * maxSlots);
3652            if (elements != NULL)
3653            {
3654                return new(memory) SelfType(elements, maxSlots, allocator);
3655            }
3656            else
3657            {
3658                allocator->Free(memory);
3659                return NULL;
3660            }
3661#else
3662            NW_UNUSED_VARIABLE(maxSlots);
3663            return new(memory) SelfType(allocator);
3664#endif
3665        }
3666        else
3667        {
3668            return NULL;
3669        }
3670    }
3671
3672    //! @brief 必要になるごとにメモリを確保するシグナルを生成します。
3673    static SelfType* CreateVariableSizeSignal(AllocatorType* allocator)
3674    {
3675        void* memory = allocator->Alloc(sizeof(SelfType));
3676        if (memory)
3677        {
3678            return new(memory) SelfType(allocator);
3679        }
3680        else
3681        {
3682            return NULL;
3683        }
3684    }
3685
3686    //! オブジェクトを破棄します。
3687    void Destroy() { this->~Signal8(); this->m_Allocator->Free(this); }
3688
3689    //@}
3690
3691    //----------------------------------------
3692    //! @name スロット
3693    //@{
3694
3695    //! @brief        スロットと接続し、シグナルが送られるようにする。
3696    //!
3697    //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
3698    //! シグナルに接続できるスロット数は1つになります。
3699    //!
3700    //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
3701    //! Connect する前に必ず Disconnect するようにしてください。
3702    //! Disconnect していない場合は、アサートで停止します。
3703    //!
3704    //! @param[in]    slot スロットです。
3705    //!
3706    void Connect(SlotType* slot)
3707    {
3708#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
3709        bool pushed = this->m_Slots.push_back(slot);
3710        NW_ASSERT(pushed);
3711#else
3712        NW_ASSERT(this->m_Slot == NULL);
3713        this->m_Slot = slot;
3714#endif
3715    }
3716
3717    //! @brief        スロットと接続し、シグナルが送られるようにする。
3718    //!
3719    //! Connect メソッドの追加の成否を取得できるようにしたものです。
3720    //!
3721    //! @param[in]    slot スロットです。
3722    //!
3723    //! @return       追加に成功すると true が返ります。
3724    //!
3725    bool TryConnect(SlotType* slot)
3726    {
3727#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
3728        bool pushed = this->m_Slots.push_back(slot);
3729        return pushed;
3730#else
3731        bool isConnectable = (this->m_Slot == NULL);
3732        if (isConnectable)
3733        {
3734            this->m_Slot = slot;
3735        }
3736        return isConnectable;
3737#endif
3738    }
3739
3740    //! @brief        スロットを作成し、接続します。
3741    //!
3742    //! 内部でメモリを確保します。
3743    //!
3744    //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
3745    //! シグナルに接続できるスロット数は1つになります。
3746    //!
3747    //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
3748    //! Connect する前に必ず Disconnect するようにしてください。
3749    //! Disconnect していない場合は、アサートで停止します。
3750    //!
3751    //! @tparam       TFunction 関数ポインタまたは、関数オブジェクトの型です。
3752    //!
3753    //! @param[in]    function 関数ポインタまたは、関数オブジェクトです。
3754    //! @param[in]    allocator アロケータです。
3755    //!
3756    //! @return       生成されたスロットです。
3757    //!
3758    template<typename TFunction>
3759    SlotType* CreateAndConnect(TFunction function, AllocatorType* allocator)
3760    {
3761        typedef FunctionSlot8<ResultType, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TFunction, AllocatorType> FunctionSlotType;
3762        FunctionSlotType* slot = CreateSlot<FunctionSlotType>(allocator, function);
3763
3764        this->Connect(slot);
3765        return slot;
3766    }
3767
3768    //! @brief        スロットを作成し、接続します。
3769    //!
3770    //! 内部でメモリを確保します。
3771    //!
3772    //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
3773    //! シグナルに接続できるスロット数は1つになります。
3774    //!
3775    //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
3776    //! Connect する前に必ず Disconnect するようにしてください。
3777    //! Disconnect していない場合は、アサートで停止します。
3778    //!
3779    //! @tparam       TFunction 関数ポインタまたは、関数オブジェクトの型です。
3780    //!
3781    //! @param[in]    function 関数ポインタまたは、関数オブジェクトです。
3782    //!
3783    //! @return       生成されたスロットです。
3784    //!
3785    template<typename TFunction>
3786    SlotType* CreateAndConnect(TFunction function)
3787    {
3788        return CreateAndConnect(function, this->m_Allocator);
3789    }
3790
3791    //! @brief        スロットを切断します。
3792    //!
3793    //! @param[in]    slot 切断するスロットです。
3794    //!
3795    void Disconnect(SlotType* slot)
3796    {
3797#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
3798        this->m_Slots.erase_find(slot);
3799#else
3800        if (this->m_Slot == slot)
3801        {
3802            this->m_Slot = NULL;
3803        }
3804#endif
3805    }
3806
3807    //! @brief        スロットを切断して、破棄します。
3808    //!
3809    //! 関数オブジェクトにアロケータが設定されていると、オブジェクトを破棄します。
3810    //! アロケータが設定されていないと、登録を解除して破棄は行いません。
3811    //!
3812    //! @param[in]    slot 切断するスロットです。
3813    //!
3814    void DisconnectAndDestroy(SlotType* slot)
3815    {
3816#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
3817        this->m_Slots.erase_find(slot);
3818        slot->Destroy();
3819#else
3820        if (this->m_Slot == slot)
3821        {
3822            this->m_Slot = NULL;
3823        }
3824        if (slot)
3825        {
3826            slot->Destroy();
3827        }
3828#endif
3829    }
3830    //@}
3831
3832    //! @brief シグナルを送信します。
3833    ResultType operator()(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6, TArg7 arg7)
3834    {
3835#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
3836        ResultCombinerType combiner;
3837        return combiner(m_Slots.begin(), m_Slots.end(), Invoker(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7));
3838#else
3839        if (this->m_Slot)
3840        {
3841            return this->m_Slot->Invoke(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
3842        }
3843        else
3844        {
3845            return ResultType();
3846        }
3847#endif
3848    }
3849
3850    //! @brief   CreateInvalidateSignal() の実行に必要なメモリサイズを取得します。
3851    static size_t GetMemorySizeForInvalidateSignal(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT)
3852    {
3853        os::MemorySizeCalculator size(alignment);
3854
3855        GetMemorySizeForInvalidateSignalInternal(&size);
3856
3857        return size.GetSizeWithPadding(alignment);
3858    }
3859
3860    //! @details :private
3861    static void GetMemorySizeForInvalidateSignalInternal(os::MemorySizeCalculator* pSize)
3862    {
3863        os::MemorySizeCalculator& size = *pSize;
3864
3865        size += sizeof(SelfType);
3866    }
3867
3868    //! @brief   CreateFixedSizedSignal() の実行に必要なメモリサイズを取得します。
3869    //!
3870    //! @param[in]    maxSlots スロットを追加できる最大数です。
3871    static size_t GetMemorySizeForFixedSizedSignal(size_t maxSlots, size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT)
3872    {
3873        os::MemorySizeCalculator size(alignment);
3874
3875        GetMemorySizeForFixedSizedSignalInternal(&size, maxSlots);
3876
3877        return size.GetSizeWithPadding(alignment);
3878    }
3879
3880    //! @details :private
3881    static void GetMemorySizeForFixedSizedSignalInternal(os::MemorySizeCalculator* pSize, size_t maxSlots)
3882    {
3883        os::MemorySizeCalculator& size = *pSize;
3884
3885        size += sizeof(SelfType);
3886
3887#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
3888        size += sizeof(SlotType*) * maxSlots;
3889#else
3890        NW_UNUSED_VARIABLE(maxSlots);
3891#endif
3892    }
3893
3894private:
3895#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
3896    //! @brief コンストラクタです。
3897    Signal8(void* elements, size_t maxSlots, AllocatorType* allocator)
3898    : m_Allocator(allocator), m_Slots(elements, maxSlots, allocator) {}
3899    //! @brief コンストラクタです。
3900    explicit Signal8(AllocatorType* allocator)
3901    : m_Allocator(allocator), m_Slots(allocator) {}
3902    //! @brief デストラクタです。
3903    ~Signal8() { DestroyAllSlots(m_Slots); }
3904#else
3905    //! @brief コンストラクタです。
3906    explicit Signal8(AllocatorType* allocator) : m_Allocator(allocator), m_Slot(NULL) {}
3907    //! @brief デストラクタです。
3908    ~Signal8() { SafeDestroy(this->m_Slot); }
3909#endif
3910
3911    AllocatorType* m_Allocator;
3912
3913#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
3914    SlotList m_Slots;
3915#else
3916    SlotType* m_Slot;
3917#endif
3918};
3919
3920//---------------------------------------------------------------------------
3921//! @brief        シグナルを受け取るためのインターフェースです。(引数は 9 個です)
3922//!
3923//! @tparam       TResult 返り値の型です。
3924//! @tparam       TAllocator アロケータの型です。
3925//---------------------------------------------------------------------------
3926template<
3927    typename TResult,
3928    typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename TArg6, typename TArg7, typename TArg8,
3929    typename TAllocator = os::IAllocator
3930>
3931class Slot9
3932{
3933public:
3934    typedef TResult ResultType;
3935    typedef TAllocator AllocatorType;
3936
3937    //! @brief コンストラクタです。
3938    explicit Slot9(AllocatorType* allocator) : m_Allocator(allocator) {}
3939
3940    //! @brief 自らを破棄します。
3941    void Destroy()
3942    {
3943        AllocatorType* allocator = this->GetAllocator();
3944        if (allocator)
3945        {
3946            this->~Slot9();
3947            allocator->Free(this);
3948        }
3949    }
3950
3951    //! @brief 自らを破棄します。
3952    void Destroy(AllocatorType* allocator)
3953    {
3954        NW_NULL_ASSERT(allocator);
3955        this->~Slot9();
3956        allocator->Free(this);
3957    }
3958
3959    //! @brief スロットにシグナルを送信します。
3960    virtual ResultType Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6, TArg7 arg7, TArg8 arg8) = 0;
3961
3962    AllocatorType* GetAllocator() { return m_Allocator; }
3963
3964protected:
3965    //! デストラクタです。
3966    virtual ~Slot9() {}
3967
3968private:
3969    AllocatorType* m_Allocator;
3970};
3971
3972//---------------------------------------------------------------------------
3973//! @brief        シグナルを受け取るためのクラスです。(引数は 9 個です)
3974//!
3975//! @tparam       TResult 返り値の型です。
3976//! @tparam       TFunction 関数か関数オブジェクトの型です。
3977//! @tparam       TAllocator アロケータの型です。
3978//---------------------------------------------------------------------------
3979template<
3980    typename TResult,
3981    typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename TArg6, typename TArg7, typename TArg8,
3982    typename TFunction,
3983    typename TAllocator = os::IAllocator
3984>
3985class FunctionSlot9 : public Slot9<TResult, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TAllocator>
3986{
3987public:
3988    typedef TResult ResultType;
3989    typedef TFunction FunctionType;
3990    typedef TAllocator AllocatorType;
3991
3992    //! コンストラクタです。
3993    FunctionSlot9(AllocatorType* allocator, FunctionType function)
3994    : Slot9<TResult, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TAllocator>(allocator), m_Function(function) {}
3995
3996    //! @brief スロットにシグナルを送信します。
3997    virtual ResultType Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6, TArg7 arg7, TArg8 arg8)
3998    {
3999        return m_Function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
4000    }
4001
4002private:
4003    TFunction m_Function;
4004};
4005
4006//---------------------------------------------------------------------------
4007//! @brief        スロットに合図を送るためのクラスです。(引数は 9 個です)
4008//!
4009//! @tparam       TResult 返り値の型です。
4010//! @tparam       TResultCombiner スロットの返り値をまとめて返してくれるコンバイナの型です。
4011//! @tparam       TAllocator アロケータの型です。
4012//! @tparam       TSlot スロットの型です。
4013//---------------------------------------------------------------------------
4014template<
4015    typename TResult,
4016    typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename TArg6, typename TArg7, typename TArg8,
4017    typename TResultCombiner = LastValueResult<TResult>,
4018    typename TAllocator = os::IAllocator,
4019    typename TSlot = Slot9<TResult, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TAllocator>
4020>
4021class Signal9
4022{
4023    NW_DISALLOW_COPY_AND_ASSIGN(Signal9);
4024
4025public:
4026    typedef Signal9<TResult, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TResultCombiner, TAllocator, TSlot> SelfType;
4027    typedef TSlot SlotType;
4028    typedef TResult ResultType;
4029    typedef ut::MoveArray<SlotType*> SlotList;
4030    typedef TResultCombiner ResultCombinerType;
4031    typedef TAllocator AllocatorType;
4032
4033#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
4034    //! @brief スロット実行用関数オブジェクトです。
4035    struct Invoker
4036    {
4037        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) {}
4038        ResultType operator()(SlotType* slot) const
4039        {
4040            return slot->Invoke(m_arg0, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8);
4041        }
4042        TArg0 m_arg0;
4043        TArg1 m_arg1;
4044        TArg2 m_arg2;
4045        TArg3 m_arg3;
4046        TArg4 m_arg4;
4047        TArg5 m_arg5;
4048        TArg6 m_arg6;
4049        TArg7 m_arg7;
4050        TArg8 m_arg8;
4051    };
4052#endif
4053
4054    //----------------------------------------
4055    //! @name 作成/破棄
4056    //@{
4057
4058    //! @brief        無効なシグナルを生成します。
4059    //!
4060    //! @param[in]    allocator アロケータです。
4061    //!
4062    static SelfType* CreateInvalidateSignal(AllocatorType* allocator)
4063    {
4064        void* memory = allocator->Alloc(sizeof(SelfType));
4065        if (memory)
4066        {
4067#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
4068            return new(memory) SelfType(NULL, 0, allocator);
4069#else
4070            return new(memory) SelfType(allocator);
4071#endif
4072        }
4073        else
4074        {
4075            return NULL;
4076        }
4077    }
4078
4079    //! @brief        必要なメモリを事前に確保してシグナルを生成します。
4080    //!
4081    //! @param[in]    maxSlots スロットを追加できる最大数です。
4082    //! @param[in]    allocator アロケータです。
4083    //!
4084    static SelfType* CreateFixedSizedSignal(size_t maxSlots, AllocatorType* allocator)
4085    {
4086        void* memory = allocator->Alloc(sizeof(SelfType));
4087        if (memory)
4088        {
4089#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
4090            void* elements = allocator->Alloc(sizeof(SlotType*) * maxSlots);
4091            if (elements != NULL)
4092            {
4093                return new(memory) SelfType(elements, maxSlots, allocator);
4094            }
4095            else
4096            {
4097                allocator->Free(memory);
4098                return NULL;
4099            }
4100#else
4101            NW_UNUSED_VARIABLE(maxSlots);
4102            return new(memory) SelfType(allocator);
4103#endif
4104        }
4105        else
4106        {
4107            return NULL;
4108        }
4109    }
4110
4111    //! @brief 必要になるごとにメモリを確保するシグナルを生成します。
4112    static SelfType* CreateVariableSizeSignal(AllocatorType* allocator)
4113    {
4114        void* memory = allocator->Alloc(sizeof(SelfType));
4115        if (memory)
4116        {
4117            return new(memory) SelfType(allocator);
4118        }
4119        else
4120        {
4121            return NULL;
4122        }
4123    }
4124
4125    //! オブジェクトを破棄します。
4126    void Destroy() { this->~Signal9(); this->m_Allocator->Free(this); }
4127
4128    //@}
4129
4130    //----------------------------------------
4131    //! @name スロット
4132    //@{
4133
4134    //! @brief        スロットと接続し、シグナルが送られるようにする。
4135    //!
4136    //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
4137    //! シグナルに接続できるスロット数は1つになります。
4138    //!
4139    //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
4140    //! Connect する前に必ず Disconnect するようにしてください。
4141    //! Disconnect していない場合は、アサートで停止します。
4142    //!
4143    //! @param[in]    slot スロットです。
4144    //!
4145    void Connect(SlotType* slot)
4146    {
4147#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
4148        bool pushed = this->m_Slots.push_back(slot);
4149        NW_ASSERT(pushed);
4150#else
4151        NW_ASSERT(this->m_Slot == NULL);
4152        this->m_Slot = slot;
4153#endif
4154    }
4155
4156    //! @brief        スロットと接続し、シグナルが送られるようにする。
4157    //!
4158    //! Connect メソッドの追加の成否を取得できるようにしたものです。
4159    //!
4160    //! @param[in]    slot スロットです。
4161    //!
4162    //! @return       追加に成功すると true が返ります。
4163    //!
4164    bool TryConnect(SlotType* slot)
4165    {
4166#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
4167        bool pushed = this->m_Slots.push_back(slot);
4168        return pushed;
4169#else
4170        bool isConnectable = (this->m_Slot == NULL);
4171        if (isConnectable)
4172        {
4173            this->m_Slot = slot;
4174        }
4175        return isConnectable;
4176#endif
4177    }
4178
4179    //! @brief        スロットを作成し、接続します。
4180    //!
4181    //! 内部でメモリを確保します。
4182    //!
4183    //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
4184    //! シグナルに接続できるスロット数は1つになります。
4185    //!
4186    //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
4187    //! Connect する前に必ず Disconnect するようにしてください。
4188    //! Disconnect していない場合は、アサートで停止します。
4189    //!
4190    //! @tparam       TFunction 関数ポインタまたは、関数オブジェクトの型です。
4191    //!
4192    //! @param[in]    function 関数ポインタまたは、関数オブジェクトです。
4193    //! @param[in]    allocator アロケータです。
4194    //!
4195    //! @return       生成されたスロットです。
4196    //!
4197    template<typename TFunction>
4198    SlotType* CreateAndConnect(TFunction function, AllocatorType* allocator)
4199    {
4200        typedef FunctionSlot9<ResultType, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TFunction, AllocatorType> FunctionSlotType;
4201        FunctionSlotType* slot = CreateSlot<FunctionSlotType>(allocator, function);
4202
4203        this->Connect(slot);
4204        return slot;
4205    }
4206
4207    //! @brief        スロットを作成し、接続します。
4208    //!
4209    //! 内部でメモリを確保します。
4210    //!
4211    //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
4212    //! シグナルに接続できるスロット数は1つになります。
4213    //!
4214    //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
4215    //! Connect する前に必ず Disconnect するようにしてください。
4216    //! Disconnect していない場合は、アサートで停止します。
4217    //!
4218    //! @tparam       TFunction 関数ポインタまたは、関数オブジェクトの型です。
4219    //!
4220    //! @param[in]    function 関数ポインタまたは、関数オブジェクトです。
4221    //!
4222    //! @return       生成されたスロットです。
4223    //!
4224    template<typename TFunction>
4225    SlotType* CreateAndConnect(TFunction function)
4226    {
4227        return CreateAndConnect(function, this->m_Allocator);
4228    }
4229
4230    //! @brief        スロットを切断します。
4231    //!
4232    //! @param[in]    slot 切断するスロットです。
4233    //!
4234    void Disconnect(SlotType* slot)
4235    {
4236#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
4237        this->m_Slots.erase_find(slot);
4238#else
4239        if (this->m_Slot == slot)
4240        {
4241            this->m_Slot = NULL;
4242        }
4243#endif
4244    }
4245
4246    //! @brief        スロットを切断して、破棄します。
4247    //!
4248    //! 関数オブジェクトにアロケータが設定されていると、オブジェクトを破棄します。
4249    //! アロケータが設定されていないと、登録を解除して破棄は行いません。
4250    //!
4251    //! @param[in]    slot 切断するスロットです。
4252    //!
4253    void DisconnectAndDestroy(SlotType* slot)
4254    {
4255#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
4256        this->m_Slots.erase_find(slot);
4257        slot->Destroy();
4258#else
4259        if (this->m_Slot == slot)
4260        {
4261            this->m_Slot = NULL;
4262        }
4263        if (slot)
4264        {
4265            slot->Destroy();
4266        }
4267#endif
4268    }
4269    //@}
4270
4271    //! @brief シグナルを送信します。
4272    ResultType operator()(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6, TArg7 arg7, TArg8 arg8)
4273    {
4274#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
4275        ResultCombinerType combiner;
4276        return combiner(m_Slots.begin(), m_Slots.end(), Invoker(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8));
4277#else
4278        if (this->m_Slot)
4279        {
4280            return this->m_Slot->Invoke(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
4281        }
4282        else
4283        {
4284            return ResultType();
4285        }
4286#endif
4287    }
4288
4289    //! @brief   CreateInvalidateSignal() の実行に必要なメモリサイズを取得します。
4290    static size_t GetMemorySizeForInvalidateSignal(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT)
4291    {
4292        os::MemorySizeCalculator size(alignment);
4293
4294        GetMemorySizeForInvalidateSignalInternal(&size);
4295
4296        return size.GetSizeWithPadding(alignment);
4297    }
4298
4299    //! @details :private
4300    static void GetMemorySizeForInvalidateSignalInternal(os::MemorySizeCalculator* pSize)
4301    {
4302        os::MemorySizeCalculator& size = *pSize;
4303
4304        size += sizeof(SelfType);
4305    }
4306
4307    //! @brief   CreateFixedSizedSignal() の実行に必要なメモリサイズを取得します。
4308    //!
4309    //! @param[in]    maxSlots スロットを追加できる最大数です。
4310    static size_t GetMemorySizeForFixedSizedSignal(size_t maxSlots, size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT)
4311    {
4312        os::MemorySizeCalculator size(alignment);
4313
4314        GetMemorySizeForFixedSizedSignalInternal(&size, maxSlots);
4315
4316        return size.GetSizeWithPadding(alignment);
4317    }
4318
4319    //! @details :private
4320    static void GetMemorySizeForFixedSizedSignalInternal(os::MemorySizeCalculator* pSize, size_t maxSlots)
4321    {
4322        os::MemorySizeCalculator& size = *pSize;
4323
4324        size += sizeof(SelfType);
4325
4326#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
4327        size += sizeof(SlotType*) * maxSlots;
4328#else
4329        NW_UNUSED_VARIABLE(maxSlots);
4330#endif
4331    }
4332
4333private:
4334#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
4335    //! @brief コンストラクタです。
4336    Signal9(void* elements, size_t maxSlots, AllocatorType* allocator)
4337    : m_Allocator(allocator), m_Slots(elements, maxSlots, allocator) {}
4338    //! @brief コンストラクタです。
4339    explicit Signal9(AllocatorType* allocator)
4340    : m_Allocator(allocator), m_Slots(allocator) {}
4341    //! @brief デストラクタです。
4342    ~Signal9() { DestroyAllSlots(m_Slots); }
4343#else
4344    //! @brief コンストラクタです。
4345    explicit Signal9(AllocatorType* allocator) : m_Allocator(allocator), m_Slot(NULL) {}
4346    //! @brief デストラクタです。
4347    ~Signal9() { SafeDestroy(this->m_Slot); }
4348#endif
4349
4350    AllocatorType* m_Allocator;
4351
4352#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
4353    SlotList m_Slots;
4354#else
4355    SlotType* m_Slot;
4356#endif
4357};
4358
4359//---------------------------------------------------------------------------
4360//! @brief        シグナルを受け取るためのインターフェースです。(引数は 10 個です)
4361//!
4362//! @tparam       TResult 返り値の型です。
4363//! @tparam       TAllocator アロケータの型です。
4364//---------------------------------------------------------------------------
4365template<
4366    typename TResult,
4367    typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename TArg6, typename TArg7, typename TArg8, typename TArg9,
4368    typename TAllocator = os::IAllocator
4369>
4370class Slot10
4371{
4372public:
4373    typedef TResult ResultType;
4374    typedef TAllocator AllocatorType;
4375
4376    //! @brief コンストラクタです。
4377    explicit Slot10(AllocatorType* allocator) : m_Allocator(allocator) {}
4378
4379    //! @brief 自らを破棄します。
4380    void Destroy()
4381    {
4382        AllocatorType* allocator = this->GetAllocator();
4383        if (allocator)
4384        {
4385            this->~Slot10();
4386            allocator->Free(this);
4387        }
4388    }
4389
4390    //! @brief 自らを破棄します。
4391    void Destroy(AllocatorType* allocator)
4392    {
4393        NW_NULL_ASSERT(allocator);
4394        this->~Slot10();
4395        allocator->Free(this);
4396    }
4397
4398    //! @brief スロットにシグナルを送信します。
4399    virtual ResultType Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6, TArg7 arg7, TArg8 arg8, TArg9 arg9) = 0;
4400
4401    AllocatorType* GetAllocator() { return m_Allocator; }
4402
4403protected:
4404    //! デストラクタです。
4405    virtual ~Slot10() {}
4406
4407private:
4408    AllocatorType* m_Allocator;
4409};
4410
4411//---------------------------------------------------------------------------
4412//! @brief        シグナルを受け取るためのクラスです。(引数は 10 個です)
4413//!
4414//! @tparam       TResult 返り値の型です。
4415//! @tparam       TFunction 関数か関数オブジェクトの型です。
4416//! @tparam       TAllocator アロケータの型です。
4417//---------------------------------------------------------------------------
4418template<
4419    typename TResult,
4420    typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename TArg6, typename TArg7, typename TArg8, typename TArg9,
4421    typename TFunction,
4422    typename TAllocator = os::IAllocator
4423>
4424class FunctionSlot10 : public Slot10<TResult, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TAllocator>
4425{
4426public:
4427    typedef TResult ResultType;
4428    typedef TFunction FunctionType;
4429    typedef TAllocator AllocatorType;
4430
4431    //! コンストラクタです。
4432    FunctionSlot10(AllocatorType* allocator, FunctionType function)
4433    : Slot10<TResult, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TAllocator>(allocator), m_Function(function) {}
4434
4435    //! @brief スロットにシグナルを送信します。
4436    virtual ResultType Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6, TArg7 arg7, TArg8 arg8, TArg9 arg9)
4437    {
4438        return m_Function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
4439    }
4440
4441private:
4442    TFunction m_Function;
4443};
4444
4445//---------------------------------------------------------------------------
4446//! @brief        スロットに合図を送るためのクラスです。(引数は 10 個です)
4447//!
4448//! @tparam       TResult 返り値の型です。
4449//! @tparam       TResultCombiner スロットの返り値をまとめて返してくれるコンバイナの型です。
4450//! @tparam       TAllocator アロケータの型です。
4451//! @tparam       TSlot スロットの型です。
4452//---------------------------------------------------------------------------
4453template<
4454    typename TResult,
4455    typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename TArg6, typename TArg7, typename TArg8, typename TArg9,
4456    typename TResultCombiner = LastValueResult<TResult>,
4457    typename TAllocator = os::IAllocator,
4458    typename TSlot = Slot10<TResult, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TAllocator>
4459>
4460class Signal10
4461{
4462    NW_DISALLOW_COPY_AND_ASSIGN(Signal10);
4463
4464public:
4465    typedef Signal10<TResult, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TResultCombiner, TAllocator, TSlot> SelfType;
4466    typedef TSlot SlotType;
4467    typedef TResult ResultType;
4468    typedef ut::MoveArray<SlotType*> SlotList;
4469    typedef TResultCombiner ResultCombinerType;
4470    typedef TAllocator AllocatorType;
4471
4472#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
4473    //! @brief スロット実行用関数オブジェクトです。
4474    struct Invoker
4475    {
4476        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) {}
4477        ResultType operator()(SlotType* slot) const
4478        {
4479            return slot->Invoke(m_arg0, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9);
4480        }
4481        TArg0 m_arg0;
4482        TArg1 m_arg1;
4483        TArg2 m_arg2;
4484        TArg3 m_arg3;
4485        TArg4 m_arg4;
4486        TArg5 m_arg5;
4487        TArg6 m_arg6;
4488        TArg7 m_arg7;
4489        TArg8 m_arg8;
4490        TArg9 m_arg9;
4491    };
4492#endif
4493
4494    //----------------------------------------
4495    //! @name 作成/破棄
4496    //@{
4497
4498    //! @brief        無効なシグナルを生成します。
4499    //!
4500    //! @param[in]    allocator アロケータです。
4501    //!
4502    static SelfType* CreateInvalidateSignal(AllocatorType* allocator)
4503    {
4504        void* memory = allocator->Alloc(sizeof(SelfType));
4505        if (memory)
4506        {
4507#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
4508            return new(memory) SelfType(NULL, 0, allocator);
4509#else
4510            return new(memory) SelfType(allocator);
4511#endif
4512        }
4513        else
4514        {
4515            return NULL;
4516        }
4517    }
4518
4519    //! @brief        必要なメモリを事前に確保してシグナルを生成します。
4520    //!
4521    //! @param[in]    maxSlots スロットを追加できる最大数です。
4522    //! @param[in]    allocator アロケータです。
4523    //!
4524    static SelfType* CreateFixedSizedSignal(size_t maxSlots, AllocatorType* allocator)
4525    {
4526        void* memory = allocator->Alloc(sizeof(SelfType));
4527        if (memory)
4528        {
4529#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
4530            void* elements = allocator->Alloc(sizeof(SlotType*) * maxSlots);
4531            if (elements != NULL)
4532            {
4533                return new(memory) SelfType(elements, maxSlots, allocator);
4534            }
4535            else
4536            {
4537                allocator->Free(memory);
4538                return NULL;
4539            }
4540#else
4541            NW_UNUSED_VARIABLE(maxSlots);
4542            return new(memory) SelfType(allocator);
4543#endif
4544        }
4545        else
4546        {
4547            return NULL;
4548        }
4549    }
4550
4551    //! @brief 必要になるごとにメモリを確保するシグナルを生成します。
4552    static SelfType* CreateVariableSizeSignal(AllocatorType* allocator)
4553    {
4554        void* memory = allocator->Alloc(sizeof(SelfType));
4555        if (memory)
4556        {
4557            return new(memory) SelfType(allocator);
4558        }
4559        else
4560        {
4561            return NULL;
4562        }
4563    }
4564
4565    //! オブジェクトを破棄します。
4566    void Destroy() { this->~Signal10(); this->m_Allocator->Free(this); }
4567
4568    //@}
4569
4570    //----------------------------------------
4571    //! @name スロット
4572    //@{
4573
4574    //! @brief        スロットと接続し、シグナルが送られるようにする。
4575    //!
4576    //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
4577    //! シグナルに接続できるスロット数は1つになります。
4578    //!
4579    //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
4580    //! Connect する前に必ず Disconnect するようにしてください。
4581    //! Disconnect していない場合は、アサートで停止します。
4582    //!
4583    //! @param[in]    slot スロットです。
4584    //!
4585    void Connect(SlotType* slot)
4586    {
4587#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
4588        bool pushed = this->m_Slots.push_back(slot);
4589        NW_ASSERT(pushed);
4590#else
4591        NW_ASSERT(this->m_Slot == NULL);
4592        this->m_Slot = slot;
4593#endif
4594    }
4595
4596    //! @brief        スロットと接続し、シグナルが送られるようにする。
4597    //!
4598    //! Connect メソッドの追加の成否を取得できるようにしたものです。
4599    //!
4600    //! @param[in]    slot スロットです。
4601    //!
4602    //! @return       追加に成功すると true が返ります。
4603    //!
4604    bool TryConnect(SlotType* slot)
4605    {
4606#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
4607        bool pushed = this->m_Slots.push_back(slot);
4608        return pushed;
4609#else
4610        bool isConnectable = (this->m_Slot == NULL);
4611        if (isConnectable)
4612        {
4613            this->m_Slot = slot;
4614        }
4615        return isConnectable;
4616#endif
4617    }
4618
4619    //! @brief        スロットを作成し、接続します。
4620    //!
4621    //! 内部でメモリを確保します。
4622    //!
4623    //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
4624    //! シグナルに接続できるスロット数は1つになります。
4625    //!
4626    //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
4627    //! Connect する前に必ず Disconnect するようにしてください。
4628    //! Disconnect していない場合は、アサートで停止します。
4629    //!
4630    //! @tparam       TFunction 関数ポインタまたは、関数オブジェクトの型です。
4631    //!
4632    //! @param[in]    function 関数ポインタまたは、関数オブジェクトです。
4633    //! @param[in]    allocator アロケータです。
4634    //!
4635    //! @return       生成されたスロットです。
4636    //!
4637    template<typename TFunction>
4638    SlotType* CreateAndConnect(TFunction function, AllocatorType* allocator)
4639    {
4640        typedef FunctionSlot10<ResultType, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TFunction, AllocatorType> FunctionSlotType;
4641        FunctionSlotType* slot = CreateSlot<FunctionSlotType>(allocator, function);
4642
4643        this->Connect(slot);
4644        return slot;
4645    }
4646
4647    //! @brief        スロットを作成し、接続します。
4648    //!
4649    //! 内部でメモリを確保します。
4650    //!
4651    //! "nw/ut/ut_Config.h"の"NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
4652    //! シグナルに接続できるスロット数は1つになります。
4653    //!
4654    //! "NW_SIGNAL_MULTI_SLOT_ENABLED"定義が無効の場合、
4655    //! Connect する前に必ず Disconnect するようにしてください。
4656    //! Disconnect していない場合は、アサートで停止します。
4657    //!
4658    //! @tparam       TFunction 関数ポインタまたは、関数オブジェクトの型です。
4659    //!
4660    //! @param[in]    function 関数ポインタまたは、関数オブジェクトです。
4661    //!
4662    //! @return       生成されたスロットです。
4663    //!
4664    template<typename TFunction>
4665    SlotType* CreateAndConnect(TFunction function)
4666    {
4667        return CreateAndConnect(function, this->m_Allocator);
4668    }
4669
4670    //! @brief        スロットを切断します。
4671    //!
4672    //! @param[in]    slot 切断するスロットです。
4673    //!
4674    void Disconnect(SlotType* slot)
4675    {
4676#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
4677        this->m_Slots.erase_find(slot);
4678#else
4679        if (this->m_Slot == slot)
4680        {
4681            this->m_Slot = NULL;
4682        }
4683#endif
4684    }
4685
4686    //! @brief        スロットを切断して、破棄します。
4687    //!
4688    //! 関数オブジェクトにアロケータが設定されていると、オブジェクトを破棄します。
4689    //! アロケータが設定されていないと、登録を解除して破棄は行いません。
4690    //!
4691    //! @param[in]    slot 切断するスロットです。
4692    //!
4693    void DisconnectAndDestroy(SlotType* slot)
4694    {
4695#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
4696        this->m_Slots.erase_find(slot);
4697        slot->Destroy();
4698#else
4699        if (this->m_Slot == slot)
4700        {
4701            this->m_Slot = NULL;
4702        }
4703        if (slot)
4704        {
4705            slot->Destroy();
4706        }
4707#endif
4708    }
4709    //@}
4710
4711    //! @brief シグナルを送信します。
4712    ResultType operator()(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6, TArg7 arg7, TArg8 arg8, TArg9 arg9)
4713    {
4714#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
4715        ResultCombinerType combiner;
4716        return combiner(m_Slots.begin(), m_Slots.end(), Invoker(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9));
4717#else
4718        if (this->m_Slot)
4719        {
4720            return this->m_Slot->Invoke(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
4721        }
4722        else
4723        {
4724            return ResultType();
4725        }
4726#endif
4727    }
4728
4729    //! @brief   CreateInvalidateSignal() の実行に必要なメモリサイズを取得します。
4730    static size_t GetMemorySizeForInvalidateSignal(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT)
4731    {
4732        os::MemorySizeCalculator size(alignment);
4733
4734        GetMemorySizeForInvalidateSignalInternal(&size);
4735
4736        return size.GetSizeWithPadding(alignment);
4737    }
4738
4739    //! @details :private
4740    static void GetMemorySizeForInvalidateSignalInternal(os::MemorySizeCalculator* pSize)
4741    {
4742        os::MemorySizeCalculator& size = *pSize;
4743
4744        size += sizeof(SelfType);
4745    }
4746
4747    //! @brief   CreateFixedSizedSignal() の実行に必要なメモリサイズを取得します。
4748    //!
4749    //! @param[in]    maxSlots スロットを追加できる最大数です。
4750    static size_t GetMemorySizeForFixedSizedSignal(size_t maxSlots, size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT)
4751    {
4752        os::MemorySizeCalculator size(alignment);
4753
4754        GetMemorySizeForFixedSizedSignalInternal(&size, maxSlots);
4755
4756        return size.GetSizeWithPadding(alignment);
4757    }
4758
4759    //! @details :private
4760    static void GetMemorySizeForFixedSizedSignalInternal(os::MemorySizeCalculator* pSize, size_t maxSlots)
4761    {
4762        os::MemorySizeCalculator& size = *pSize;
4763
4764        size += sizeof(SelfType);
4765
4766#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
4767        size += sizeof(SlotType*) * maxSlots;
4768#else
4769        NW_UNUSED_VARIABLE(maxSlots);
4770#endif
4771    }
4772
4773private:
4774#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
4775    //! @brief コンストラクタです。
4776    Signal10(void* elements, size_t maxSlots, AllocatorType* allocator)
4777    : m_Allocator(allocator), m_Slots(elements, maxSlots, allocator) {}
4778    //! @brief コンストラクタです。
4779    explicit Signal10(AllocatorType* allocator)
4780    : m_Allocator(allocator), m_Slots(allocator) {}
4781    //! @brief デストラクタです。
4782    ~Signal10() { DestroyAllSlots(m_Slots); }
4783#else
4784    //! @brief コンストラクタです。
4785    explicit Signal10(AllocatorType* allocator) : m_Allocator(allocator), m_Slot(NULL) {}
4786    //! @brief デストラクタです。
4787    ~Signal10() { SafeDestroy(this->m_Slot); }
4788#endif
4789
4790    AllocatorType* m_Allocator;
4791
4792#ifdef NW_SIGNAL_MULTI_SLOT_ENABLED
4793    SlotList m_Slots;
4794#else
4795    SlotType* m_Slot;
4796#endif
4797};
4798
4799