Reference Manual
Inti Logo
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members

signals.h

Go to the documentation of this file.
00001 /*  Inti: Integrated Foundation Classes
00002  *  Copyright (C) 2002 The Inti Development Team.
00003  *  Copyright (C) 2000 Red Hat, Inc.
00004  *  Copyright 1999, Karl Einar Nelson
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU Library General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU Library General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00019  */
00020 
00029 
00030 #ifndef INTI_SIGNALS_H
00031 #define INTI_SIGNALS_H
00032 
00033 #ifndef INTI_SLOT_H
00034 #include <inti/slot.h>
00035 #endif
00036 
00037 #ifndef INTI_CONNECTION_H
00038 #include <inti/connection.h>
00039 #endif
00040 
00041 #ifndef _CPP_VECTOR
00042 #include <vector>
00043 #endif
00044 
00045 namespace Inti {
00046         
00047 class Signal;
00048 
00051 
00052 class SlotNode : public Node
00053 {
00054         friend class Signal;
00055 
00056         SlotNode(const Slot *slot);
00057         ~SlotNode();
00058 
00059         bool is_blocked;
00060 
00061 public:
00062         bool blocked() const { return is_blocked; }
00064         
00065         virtual void block();
00067 
00068         virtual void unblock();
00070 
00071         virtual void disconnect();
00073 };
00074 
00075 // DefaultMarshal class (from marshal.h, libsigc++)
00076 
00077 template <typename R>
00078 class DefaultMarshal
00079 {
00080 public:
00081         typedef R OutType;
00082         typedef R InType;
00083 
00084 private:
00085         OutType value_;
00086 
00087 public:
00088         DefaultMarshal() :value_() {}
00089     
00090         OutType& value() { return value_; }
00091     
00092         // Return true to stop emission.
00093         bool marshal(const InType & newval)
00094         {
00095                 value_ = newval;
00096                 return false;
00097         }
00098 };
00099 
00102 
00103 class Signal
00104 {
00105         Signal(const Signal&);
00106         Signal& operator=(const Signal&);
00107 
00108 protected:
00109         typedef std::vector<SlotNode*> ConnectionList;
00111 
00112         ConnectionList connection_list;
00114 
00115 public:
00116         Signal();
00118 
00119         virtual ~Signal();
00121 
00122         SlotNode* connect(const Slot *slot);
00124 };
00125 
00128 
00129 template<typename R, typename Marshal = DefaultMarshal<R> >
00130 class Signal0 : public Signal
00131 {
00132         typedef Signal0<R> Self;
00133 
00134         static R callback(void *data)
00135         {
00136                 Self *s = static_cast<Self*>(data);
00137                 return s->emit();
00138         }
00139 
00140 public:
00141         typedef Slot0<R> SlotType;
00143 
00144         Connection connect(const SlotType *slot)
00145         { 
00146                 return Signal::connect(slot);
00147         }
00153 
00154         SlotType* slot()
00155         {
00156                 return new SignalSlot0<Self, R>(this, &callback);
00157         }
00163 
00164         R emit()
00165         {
00166                 Marshal m;
00167                 ConnectionList::iterator i = connection_list.begin();
00168                 while (i != connection_list.end())
00169                 {
00170                         if (!(*i)->blocked())
00171                         {
00172                                 SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
00173                                 if (m.marshal(slot->call()))
00174                                         break;
00175                         }
00176                         ++i;
00177                 }
00178                 return m.value();       
00179         }
00184 
00185         R operator()() 
00186         {
00187                 return emit(); 
00188         }
00190 };
00191 
00192 // Signal0 partially specialized for void return
00193 
00194 template<typename IgnoreMarshal>
00195 class Signal0<void, IgnoreMarshal> : public Signal
00196 {
00197         typedef Signal0<void, IgnoreMarshal> Self;
00198 
00199         static void callback(void *data)
00200         {
00201                 Self *s = static_cast<Self*>(data);
00202                 s->emit();
00203         }
00204 
00205 public:
00206         typedef Slot0<void> SlotType;
00207 
00208         Connection connect(const SlotType *slot)
00209         { 
00210                 return Signal::connect(slot);
00211         }
00212 
00213         SlotType* slot()
00214         {
00215                 return new SignalSlot0<Self, void>(this, &callback);
00216         }
00217 
00218         void emit()
00219         {
00220                 ConnectionList::iterator i = connection_list.begin();
00221                 while (i != connection_list.end())
00222                 {
00223                         if (!(*i)->blocked())
00224                         {
00225                                 SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
00226                                 slot->call();
00227                         }
00228                         ++i;
00229                 }
00230         }
00231                 
00232         void operator()()
00233         {
00234                 emit(); 
00235         }
00236 };
00237 
00240 
00241 template<typename R, typename P1, typename Marshal = DefaultMarshal<R> >
00242 class Signal1 : public Signal
00243 {
00244         typedef Signal1<R, P1> Self;
00245 
00246         static R callback(void *data, P1 p1)
00247         {
00248                 Self *s = static_cast<Self*>(data);
00249                 return s->emit(p1);
00250         }
00251 
00252 public:
00253         typedef Slot1<R, P1> SlotType;
00255 
00256         Connection connect(const SlotType *slot)
00257         { 
00258                 return Signal::connect(slot);
00259         }
00265 
00266         SlotType* slot()
00267         {
00268                 return new SignalSlot1<Self, R, P1>(this, &callback);
00269         }
00275 
00276         R emit(P1 p1)
00277         {
00278                 Marshal m;
00279                 ConnectionList::iterator i = connection_list.begin();
00280                 while (i != connection_list.end())
00281                 {
00282                         if (!(*i)->blocked())
00283                         {
00284                                 SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
00285                                 if (m.marshal(slot->call(p1)))
00286                                         break;
00287                         }
00288                         ++i;            
00289                 }
00290                 return m.value();       
00291         }
00297 
00298         R operator()(P1 p1) 
00299         {
00300                 return emit(p1); 
00301         }
00303 };
00304 
00305 // Signal1 partially specialized for void return
00306 
00307 template<typename P1, typename IgnoreMarshal>
00308 class Signal1<void, P1, IgnoreMarshal> : public Signal
00309 {
00310         typedef Signal1<void, P1, IgnoreMarshal> Self;
00311 
00312         static void callback(void *data, P1 p1)
00313         {
00314                 Self *s = static_cast<Self*>(data);
00315                 s->emit(p1);
00316         }
00317 
00318 public:
00319         typedef Slot1<void, P1> SlotType;
00320 
00321         Connection connect(const SlotType *slot)
00322         { 
00323                 return Signal::connect(slot);
00324         }
00325 
00326         SlotType* slot()
00327         {
00328                 return new SignalSlot1<Self, void, P1>(this, &callback);
00329         }
00330 
00331         void emit(P1 p1)
00332         {
00333                 ConnectionList::iterator i = connection_list.begin();
00334                 while (i != connection_list.end())
00335                 {
00336                         if (!(*i)->blocked())
00337                         {
00338                                 SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
00339                                 slot->call(p1);
00340                         }
00341                         ++i;
00342                 }
00343         }
00344                 
00345         void operator()(P1 p1)
00346         {
00347                 emit(p1); 
00348         }
00349 };
00350 
00354 
00355 template<typename R, typename P1, typename P2, typename Marshal = DefaultMarshal<R> >
00356 class Signal2 : public Signal
00357 {
00358         typedef Signal2<R, P1, P2> Self;
00359 
00360         static R callback(void *data, P1 p1, P2 p2)
00361         {
00362                 Self *s = static_cast<Self*>(data);
00363                 return s->emit(p1, p2);
00364         }
00365 
00366 public:
00367         typedef Slot2<R, P1, P2> SlotType;
00369 
00370         Connection connect(const SlotType *slot)
00371         { 
00372                 return Signal::connect(slot);
00373         }
00379 
00380         SlotType* slot()
00381         {
00382                 return new SignalSlot2<Self, R, P1, P2>(this, &callback);
00383         }
00389 
00390         R emit(P1 p1, P2 p2)
00391         {
00392                 Marshal m;
00393                 ConnectionList::iterator i = connection_list.begin();
00394                 while (i != connection_list.end())
00395                 {
00396                         if (!(*i)->blocked())
00397                         {
00398                                 SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
00399                                 if (m.marshal(slot->call(p1, p2)))
00400                                         break;
00401                         }
00402                         ++i;            
00403                 }
00404                 return m.value();       
00405         }
00412 
00413         R operator()(P1 p1, P2 p2) 
00414         {
00415                 return emit(p1, p2); 
00416         }
00418 };
00419 
00420 // Signal2 partially specialized for void return
00421 
00422 template<typename P1, typename P2, typename IgnoreMarshal>
00423 class Signal2<void, P1, P2, IgnoreMarshal> : public Signal
00424 {
00425         typedef Signal2<void, P1, P2, IgnoreMarshal> Self;
00426 
00427         static void callback(void *data, P1 p1, P2 p2)
00428         {
00429                 Self *s = static_cast<Self*>(data);
00430                 s->emit(p1, p2);
00431         }
00432 
00433 public:
00434         typedef Slot2<void, P1, P2> SlotType;
00435 
00436         Connection connect(const SlotType *slot)
00437         { 
00438                 return Signal::connect(slot);
00439         }
00440 
00441         SlotType* slot()
00442         {
00443                 return new SignalSlot2<Self, void, P1, P2>(this, &callback);
00444         }
00445 
00446         void emit(P1 p1, P2 p2)
00447         {
00448                 ConnectionList::iterator i = connection_list.begin();
00449                 while (i != connection_list.end())
00450                 {
00451                         if (!(*i)->blocked())
00452                         {
00453                                 SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
00454                                 slot->call(p1, p2);
00455                         }
00456                         ++i;
00457                 }
00458         }
00459                 
00460         void operator()(P1 p1, P2 p2)
00461         {
00462                 emit(p1, p2); 
00463         }
00464 };
00465 
00469 
00470 template<typename R, typename P1, typename P2, typename P3, typename Marshal = DefaultMarshal<R> >
00471 class Signal3 : public Signal
00472 {
00473         typedef Signal3<R, P1, P2, P3> Self;
00474 
00475         static R callback(void *data, P1 p1, P2 p2, P3 p3)
00476         {
00477                 Self *s = static_cast<Self*>(data);
00478                 return s->emit(p1, p2, p3);
00479         }
00480 
00481 public:
00482         typedef Slot3<R, P1, P2, P3> SlotType;
00484 
00485         Connection connect(const SlotType *slot)
00486         { 
00487                 return Signal::connect(slot);
00488         }
00494 
00495         SlotType* slot()
00496         {
00497                 return new SignalSlot3<Self, R, P1, P2, P3>(this, &callback);
00498         }
00504 
00505         R emit(P1 p1, P2 p2, P3 p3)
00506         {
00507                 Marshal m;
00508                 ConnectionList::iterator i = connection_list.begin();
00509                 while (i != connection_list.end())
00510                 {
00511                         if (!(*i)->blocked())
00512                         {
00513                                 SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
00514                                 if (m.marshal(slot->call(p1, p2, p3)))
00515                                         break;
00516                         }
00517                         ++i;            
00518                 }
00519                 return m.value();       
00520         }
00528 
00529         R operator()(P1 p1, P2 p2, P3 p3) 
00530         {
00531                 return emit(p1, p2, p3); 
00532         }
00534 };
00535 
00536 // Signal3 partially specialized for void return
00537 
00538 template<typename P1, typename P2, typename P3, typename IgnoreMarshal>
00539 class Signal3<void, P1, P2, P3, IgnoreMarshal> : public Signal
00540 {
00541         typedef Signal3<void, P1, P2, P3, IgnoreMarshal> Self;
00542 
00543         static void callback(void *data, P1 p1, P2 p2, P3 p3)
00544         {
00545                 Self *s = static_cast<Self*>(data);
00546                 s->emit(p1, p2, p3);
00547         }
00548 
00549 public:
00550         typedef Slot3<void, P1, P2, P3> SlotType;
00551 
00552         Connection connect(const SlotType *slot)
00553         { 
00554                 return Signal::connect(slot);
00555         }
00556 
00557         SlotType* slot()
00558         {
00559                 return new SignalSlot3<Self, void, P1, P2, P3>(this, &callback);
00560         }
00561 
00562         void emit(P1 p1, P2 p2, P3 p3)
00563         {
00564                 ConnectionList::iterator i = connection_list.begin();
00565                 while (i != connection_list.end())
00566                 {
00567                         if (!(*i)->blocked())
00568                         {
00569                                 SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
00570                                 slot->call(p1, p2, p3);
00571                         }
00572                         ++i;
00573                 }
00574         }
00575                 
00576         void operator()(P1 p1, P2 p2, P3 p3)
00577         {
00578                 emit(p1, p2, p3); 
00579         }
00580 };
00581 
00585 
00586 template<typename R, typename P1, typename P2, typename P3, typename P4, typename Marshal = DefaultMarshal<R> >
00587 class Signal4 : public Signal
00588 {
00589         typedef Signal4<R, P1, P2, P3, P4> Self;
00590 
00591         static R callback(void *data, P1 p1, P2 p2, P3 p3, P4 p4)
00592         {
00593                 Self *s = static_cast<Self*>(data);
00594                 return s->emit(p1, p2, p3, p4);
00595         }
00596 
00597 public:
00598         typedef Slot4<R, P1, P2, P3, P4> SlotType;
00600 
00601         Connection connect(const SlotType *slot)
00602         { 
00603                 return Signal::connect(slot);
00604         }
00610 
00611         SlotType* slot()
00612         {
00613                 return new SignalSlot4<Self, R, P1, P2, P3, P4>(this, &callback);
00614         }
00620 
00621         R emit(P1 p1, P2 p2, P3 p3, P4 p4)
00622         {
00623                 Marshal m;
00624                 ConnectionList::iterator i = connection_list.begin();
00625                 while (i != connection_list.end())
00626                 {
00627                         if (!(*i)->blocked())
00628                         {
00629                                 SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
00630                                 if (m.marshal(slot->call(p1, p2, p3, p4)))
00631                                         break;
00632                         }
00633                         ++i;            
00634                 }
00635                 return m.value();       
00636         }
00645 
00646         R operator()(P1 p1, P2 p2, P3 p3, P4 p4) 
00647         {
00648                 return emit(p1, p2, p3, p4); 
00649         }
00651 };
00652 
00653 // Signal4 partially specialized for void return
00654 
00655 template<typename P1, typename P2, typename P3, typename P4, typename IgnoreMarshal>
00656 class Signal4<void, P1, P2, P3, P4, IgnoreMarshal> : public Signal
00657 {
00658         typedef Signal4<void, P1, P2, P3, P4, IgnoreMarshal> Self;
00659 
00660         static void callback(void *data, P1 p1, P2 p2, P3 p3, P4 p4)
00661         {
00662                 Self *s = static_cast<Self*>(data);
00663                 s->emit(p1, p2, p3, p4);
00664         }
00665 
00666 public:
00667         typedef Slot4<void, P1, P2, P3, P4> SlotType;
00668 
00669         Connection connect(const SlotType *slot)
00670         { 
00671                 return Signal::connect(slot);
00672         }
00673 
00674         SlotType* slot()
00675         {
00676                 return new SignalSlot4<Self, void, P1, P2, P3, P4>(this, &callback);
00677         }
00678 
00679         void emit(P1 p1, P2 p2, P3 p3, P4 p4)
00680         {
00681                 ConnectionList::iterator i = connection_list.begin();
00682                 while (i != connection_list.end())
00683                 {
00684                         if (!(*i)->blocked())
00685                         {
00686                                 SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
00687                                 slot->call(p1, p2, p3, p4);
00688                         }
00689                         ++i;
00690                 }
00691         }
00692                 
00693         void operator()(P1 p1, P2 p2, P3 p3, P4 p4)
00694         {
00695                 emit(p1, p2, p3, p4); 
00696         }
00697 };
00698 
00702 
00703 template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename Marshal = DefaultMarshal<R> >
00704 class Signal5 : public Signal
00705 {
00706         typedef Signal5<R, P1, P2, P3, P4, P5> Self;
00707 
00708         static R callback(void *data, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
00709         {
00710                 Self *s = static_cast<Self*>(data);
00711                 return s->emit(p1, p2, p3, p4, p5);
00712         }
00713 
00714 public:
00715         typedef Slot5<R, P1, P2, P3, P4, P5> SlotType;
00717 
00718         Connection connect(const SlotType *slot)
00719         { 
00720                 return Signal::connect(slot);
00721         }
00727 
00728         SlotType* slot()
00729         {
00730                 return new SignalSlot5<Self, R, P1, P2, P3, P4, P5>(this, &callback);
00731         }
00737 
00738         R emit(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
00739         {
00740                 Marshal m;
00741                 ConnectionList::iterator i = connection_list.begin();
00742                 while (i != connection_list.end())
00743                 {
00744                         if (!(*i)->blocked())
00745                         {
00746                                 SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
00747                                 if (m.marshal(slot->call(p1, p2, p3, p4, p5)))
00748                                         break;
00749                         }
00750                         ++i;            
00751                 }
00752                 return m.value();       
00753         }
00763 
00764         R operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) 
00765         {
00766                 return emit(p1, p2, p3, p4, p5); 
00767         }
00769 };
00770 
00771 // Signal5 partially specialized for void return
00772 
00773 template<typename P1, typename P2, typename P3, typename P4, typename P5, typename IgnoreMarshal>
00774 class Signal5<void, P1, P2, P3, P4, P5, IgnoreMarshal> : public Signal
00775 {
00776         typedef Signal5<void, P1, P2, P3, P4, P5, IgnoreMarshal> Self;
00777 
00778         static void callback(void *data, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
00779         {
00780                 Self *s = static_cast<Self*>(data);
00781                 s->emit(p1, p2, p3, p4, p5);
00782         }
00783 
00784 public:
00785         typedef Slot5<void, P1, P2, P3, P4, P5> SlotType;
00786 
00787         Connection connect(const SlotType *slot)
00788         { 
00789                 return Signal::connect(slot);
00790         }
00791 
00792         SlotType* slot()
00793         {
00794                 return new SignalSlot5<Self, void, P1, P2, P3, P4, P5>(this, &callback);
00795         }
00796 
00797         void emit(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
00798         {
00799                 ConnectionList::iterator i = connection_list.begin();
00800                 while (i != connection_list.end())
00801                 {
00802                         if (!(*i)->blocked())
00803                         {
00804                                 SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
00805                                 slot->call(p1, p2, p3, p4, p5);
00806                         }
00807                         ++i;
00808                 }
00809         }
00810                 
00811         void operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
00812         {
00813                 emit(p1, p2, p3, p4, p5); 
00814         }
00815 };
00816 
00820 
00821 template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename Marshal = DefaultMarshal<R> >
00822 class Signal6 : public Signal
00823 {
00824         typedef Signal6<R, P1, P2, P3, P4, P5, P6> Self;
00825 
00826         static R callback(void *data, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6)
00827         {
00828                 Self *s = static_cast<Self*>(data);
00829                 return s->emit(p1, p2, p3, p4, p5, p6);
00830         }
00831 
00832 public:
00833         typedef Slot6<R, P1, P2, P3, P4, P5, P6> SlotType;
00835 
00836         Connection connect(const SlotType *slot)
00837         { 
00838                 return Signal::connect(slot);
00839         }
00845 
00846         SlotType* slot()
00847         {
00848                 return new SignalSlot6<Self, R, P1, P2, P3, P4, P5, P6>(this, &callback);
00849         }
00855 
00856         R emit(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6)
00857         {
00858                 Marshal m;
00859                 ConnectionList::iterator i = connection_list.begin();
00860                 while (i != connection_list.end())
00861                 {
00862                         if (!(*i)->blocked())
00863                         {
00864                                 SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
00865                                 if (m.marshal(slot->call(p1, p2, p3, p4, p5, p6)))
00866                                         break;
00867                         }
00868                         ++i;            
00869                 }
00870                 return m.value();       
00871         }
00882 
00883         R operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) 
00884         {
00885                 return emit(p1, p2, p3, p4, p5, p6); 
00886         }
00888 };
00889 
00890 /*  Signal6 partially specialized for void return
00891  */
00892  
00893 template<typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename IgnoreMarshal>
00894 class Signal6<void, P1, P2, P3, P4, P5, P6, IgnoreMarshal> : public Signal
00895 {
00896         typedef Signal6<void, P1, P2, P3, P4, P5, P6, IgnoreMarshal> Self;
00897 
00898         static void callback(void *data, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6)
00899         {
00900                 Self *s = static_cast<Self*>(data);
00901                 s->emit(p1, p2, p3, p4, p5, p6);
00902         }
00903 
00904 public:
00905         typedef Slot6<void, P1, P2, P3, P4, P5, P6> SlotType;
00906 
00907         Connection connect(const SlotType *slot)
00908         { 
00909                 return Signal::connect(slot);
00910         }
00911 
00912         SlotType* slot()
00913         {
00914                 return new SignalSlot6<Self, void, P1, P2, P3, P4, P5, P6>(this, &callback);
00915         }
00916 
00917         void emit(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6)
00918         {
00919                 ConnectionList::iterator i = connection_list.begin();
00920                 while (i != connection_list.end())
00921                 {
00922                         if (!(*i)->blocked())
00923                         {
00924                                 SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
00925                                 slot->call(p1, p2, p3, p4, p5, p6);
00926                         }
00927                         ++i;
00928                 }
00929         }
00930                 
00931         void operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6)
00932         {
00933                 emit(p1, p2, p3, p4, p5, p6); 
00934         }
00935 };
00936 
00937 } // namespace Inti
00938 
00939 #endif // INTI_SIGNALS_H
00940 
00941 
Main Page - Footer


Generated on Sun Sep 14 20:08:04 2003 for Inti by doxygen 1.3.2 written by Dimitri van Heesch, © 1997-2002