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