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