gwensignal.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  $RCSfile$
00003  -------------------
00004  cvs         : $Id: stringlist.c 1067 2006-05-22 15:25:23Z christian $
00005  begin       : Thu Apr 03 2003
00006  copyright   : (C) 2003 by Martin Preuss
00007  email       : martin@libchipcard.de
00008 
00009  ***************************************************************************
00010  *                                                                         *
00011  *   This library is free software; you can redistribute it and/or         *
00012  *   modify it under the terms of the GNU Lesser General Public            *
00013  *   License as published by the Free Software Foundation; either          *
00014  *   version 2.1 of the License, or (at your option) any later version.    *
00015  *                                                                         *
00016  *   This library is distributed in the hope that it will be useful,       *
00017  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00018  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00019  *   Lesser General Public License for more details.                       *
00020  *                                                                         *
00021  *   You should have received a copy of the GNU Lesser General Public      *
00022  *   License along with this library; if not, write to the Free Software   *
00023  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
00024  *   MA  02111-1307  USA                                                   *
00025  *                                                                         *
00026  ***************************************************************************/
00027 
00028 #ifdef HAVE_CONFIG_H
00029 # include <config.h>
00030 #endif
00031 
00032 #include "gwensignal_p.h"
00033 #include <gwenhywfar/misc.h>
00034 #include <gwenhywfar/debug.h>
00035 #include <gwenhywfar/inherit.h>
00036 #include <stdlib.h>
00037 #include <assert.h>
00038 #include <string.h>
00039 
00040 
00041 
00042 GWEN_LIST2_FUNCTIONS(GWEN_SIGNAL, GWEN_Signal)
00043 GWEN_LIST2_FUNCTIONS(GWEN_SLOT, GWEN_Slot)
00044 
00045 
00046 GWEN_SIGNALOBJECT *GWEN_SignalObject_new() {
00047   GWEN_SIGNALOBJECT *so;
00048 
00049   GWEN_NEW_OBJECT(GWEN_SIGNALOBJECT, so);
00050   so->signalList=GWEN_Signal_List2_new();
00051   so->slotList=GWEN_Slot_List2_new();
00052 
00053   return so;
00054 }
00055 
00056 
00057 
00058 void GWEN_SignalObject_free(GWEN_SIGNALOBJECT *so) {
00059   if (so) {
00060     GWEN_Slot_List2_freeAll(so->slotList);
00061     GWEN_Signal_List2_freeAll(so->signalList);
00062     GWEN_FREE_OBJECT(so);
00063   }
00064 }
00065 
00066 
00067 
00068 uint32_t GWEN_SignalObject_MkTypeId(const char *typeName) {
00069   return GWEN_Inherit_MakeId(typeName);
00070 }
00071 
00072 
00073 
00074 GWEN_SIGNAL *GWEN_SignalObject__findSignal(const GWEN_SIGNALOBJECT *so,
00075                                            const char *name,
00076                                            uint32_t typeId1,
00077                                            uint32_t typeId2) {
00078   GWEN_SIGNAL_LIST2_ITERATOR *sit;
00079 
00080   assert(so);
00081   assert(name);
00082 
00083   sit=GWEN_Signal_List2_First(so->signalList);
00084   if (sit) {
00085     GWEN_SIGNAL *sig;
00086 
00087     sig=GWEN_Signal_List2Iterator_Data(sit);
00088     assert(sig);
00089     while(sig) {
00090       const char *s;
00091 
00092       s=sig->name;
00093       assert(s);
00094       if (strcasecmp(s, name)==0 &&
00095           (typeId1==0 || typeId1==sig->typeOfArg1) &&
00096           (typeId2==0 || typeId2==sig->typeOfArg2)) {
00097         GWEN_Signal_List2Iterator_free(sit);
00098         return sig;
00099       }
00100       sig=GWEN_Signal_List2Iterator_Next(sit);
00101     }
00102     GWEN_Signal_List2Iterator_free(sit);
00103   }
00104 
00105   return 0;
00106 }
00107 
00108 
00109 
00110 GWEN_SIGNAL *GWEN_SignalObject_FindSignal(const GWEN_SIGNALOBJECT *so,
00111                                           const char *name,
00112                                           const char *typeOfArg1,
00113                                           const char *typeOfArg2) {
00114   uint32_t typeId1=0;
00115   uint32_t typeId2=0;
00116 
00117   if (typeOfArg1)
00118     typeId1=GWEN_SignalObject_MkTypeId(typeOfArg1);
00119   if (typeOfArg2)
00120     typeId2=GWEN_SignalObject_MkTypeId(typeOfArg2);
00121   return GWEN_SignalObject__findSignal(so, name, typeId1, typeId2);
00122 }
00123 
00124 
00125 
00126 GWEN_SLOT *GWEN_SignalObject__findSlot(const GWEN_SIGNALOBJECT *so,
00127                                        const char *name,
00128                                        uint32_t typeId1,
00129                                        uint32_t typeId2) {
00130   GWEN_SLOT_LIST2_ITERATOR *sit;
00131 
00132   assert(so);
00133   assert(name);
00134 
00135   sit=GWEN_Slot_List2_First(so->slotList);
00136   if (sit) {
00137     GWEN_SLOT *slot;
00138 
00139     slot=GWEN_Slot_List2Iterator_Data(sit);
00140     assert(slot);
00141     while(slot) {
00142       const char *s;
00143 
00144       s=slot->name;
00145       assert(s);
00146       if (strcasecmp(s, name)==0 &&
00147           (typeId1==0 || typeId1==slot->typeOfArg1) &&
00148           (typeId2==0 || typeId2==slot->typeOfArg2)) {
00149         GWEN_Slot_List2Iterator_free(sit);
00150         return slot;
00151       }
00152       slot=GWEN_Slot_List2Iterator_Next(sit);
00153     }
00154     GWEN_Slot_List2Iterator_free(sit);
00155   }
00156 
00157   return 0;
00158 }
00159 
00160 
00161 
00162 GWEN_SLOT *GWEN_SignalObject_FindSlot(const GWEN_SIGNALOBJECT *so,
00163                                       const char *name,
00164                                       const char *typeOfArg1,
00165                                       const char *typeOfArg2) {
00166   uint32_t typeId1=0;
00167   uint32_t typeId2=0;
00168 
00169   if (typeOfArg1)
00170     typeId1=GWEN_SignalObject_MkTypeId(typeOfArg1);
00171   if (typeOfArg2)
00172     typeId2=GWEN_SignalObject_MkTypeId(typeOfArg2);
00173   return GWEN_SignalObject__findSlot(so, name, typeId1, typeId2);
00174 }
00175 
00176 
00177 
00178 int GWEN_SignalObject_AddSignal(GWEN_SIGNALOBJECT *so, GWEN_SIGNAL *sig) {
00179   if (GWEN_SignalObject__findSignal(so, sig->name,
00180                                     sig->typeOfArg1,
00181                                     sig->typeOfArg2)) {
00182     DBG_ERROR(GWEN_LOGDOMAIN,
00183               "Signal \"%s\" already exists",
00184               sig->name);
00185     return GWEN_ERROR_INVALID;
00186   }
00187 
00188   sig->signalObject=so;
00189   GWEN_Signal_List2_PushBack(so->signalList, sig);
00190   DBG_INFO(GWEN_LOGDOMAIN, "Added signal \"%s\"", sig->name);
00191   return 0;
00192 }
00193 
00194 
00195 
00196 int GWEN_SignalObject_AddSlot(GWEN_SIGNALOBJECT *so, GWEN_SLOT *slot) {
00197   if (GWEN_SignalObject__findSlot(so, slot->name,
00198                                   slot->typeOfArg1,
00199                                   slot->typeOfArg2)) {
00200     DBG_ERROR(GWEN_LOGDOMAIN,
00201               "Slot \"%s\" already exists",
00202               slot->name);
00203     return GWEN_ERROR_INVALID;
00204   }
00205   slot->signalObject=so;
00206   GWEN_Slot_List2_PushBack(so->slotList, slot);
00207   DBG_INFO(GWEN_LOGDOMAIN, "Added slot \"%s\"", slot->name);
00208   return 0;
00209 }
00210 
00211 
00212 
00213 void GWEN_SignalObject_RemoveForDerivedType(GWEN_SIGNALOBJECT *so,
00214                                             const char *derivedType) {
00215   uint32_t typeId=0;
00216   GWEN_SLOT_LIST2_ITERATOR *slotIt;
00217   GWEN_SIGNAL_LIST2_ITERATOR *sigIt;
00218 
00219   assert(so);
00220   if (derivedType)
00221     typeId=GWEN_SignalObject_MkTypeId(derivedType);
00222 
00223   slotIt=GWEN_Slot_List2_First(so->slotList);
00224   if (slotIt) {
00225     GWEN_SLOT *slot;
00226 
00227     slot=GWEN_Slot_List2Iterator_Data(slotIt);
00228     assert(slot);
00229     while(slot) {
00230       const char *s;
00231 
00232       s=slot->name;
00233       assert(s);
00234       if (typeId==0 || slot->derivedParentType==typeId) {
00235         GWEN_Slot_List2_Erase(so->slotList, slotIt);
00236         GWEN_Slot_free(slot);
00237         /* iterator now points to the next entry in any case (or NULL) */
00238         slot=GWEN_Slot_List2Iterator_Data(slotIt);
00239       }
00240       else
00241         slot=GWEN_Slot_List2Iterator_Next(slotIt);
00242     }
00243     GWEN_Slot_List2Iterator_free(slotIt);
00244   }
00245 
00246   sigIt=GWEN_Signal_List2_First(so->signalList);
00247   if (sigIt) {
00248     GWEN_SIGNAL *sig;
00249 
00250     sig=GWEN_Signal_List2Iterator_Data(sigIt);
00251     assert(sig);
00252     while(sig) {
00253       const char *s;
00254 
00255       s=sig->name;
00256       assert(s);
00257       if (typeId==0 || sig->derivedParentType==typeId) {
00258         GWEN_Signal_List2_Erase(so->signalList, sigIt);
00259         GWEN_Signal_free(sig);
00260         /* iterator now points to the next entry in any case (or NULL) */
00261         sig=GWEN_Signal_List2Iterator_Data(sigIt);
00262       }
00263       else
00264         sig=GWEN_Signal_List2Iterator_Next(sigIt);
00265     }
00266     GWEN_Signal_List2Iterator_free(sigIt);
00267   }
00268 }
00269 
00270 
00271 
00272 
00273 
00274 GWEN_SIGNAL *GWEN_Signal_new(GWEN_SIGNALOBJECT *so,
00275                              const char *derivedType,
00276                              const char *name,
00277                              const char *typeOfArg1,
00278                              const char *typeOfArg2) {
00279   GWEN_SIGNAL *sig;
00280 
00281   assert(so);
00282   assert(name);
00283   GWEN_NEW_OBJECT(GWEN_SIGNAL, sig)
00284   sig->_refCount=1;
00285   sig->connectedSlots=GWEN_Slot_List2_new();
00286   sig->name=strdup(name);
00287   if (typeOfArg1)
00288     sig->typeOfArg1=GWEN_SignalObject_MkTypeId(typeOfArg1);
00289   if (typeOfArg2)
00290     sig->typeOfArg2=GWEN_SignalObject_MkTypeId(typeOfArg2);
00291   if (derivedType)
00292     sig->derivedParentType=GWEN_SignalObject_MkTypeId(derivedType);
00293 
00294   if (GWEN_SignalObject_AddSignal(so, sig)) {
00295     GWEN_Signal_free(sig);
00296     return 0;
00297   }
00298 
00299   return sig;
00300 }
00301 
00302 
00303 
00304 void GWEN_Signal_free(GWEN_SIGNAL *sig) {
00305   if (sig) {
00306     assert(sig->_refCount);
00307     if (sig->_refCount==1) {
00308       GWEN_SLOT_LIST2_ITERATOR *sit;
00309 
00310       /* remove from all connected slots */
00311       sit=GWEN_Slot_List2_First(sig->connectedSlots);
00312       if (sit) {
00313         GWEN_SLOT *slot;
00314 
00315         slot=GWEN_Slot_List2Iterator_Data(sit);
00316         assert(slot);
00317         while(slot) {
00318           GWEN_SLOT *next;
00319 
00320           next=GWEN_Slot_List2Iterator_Next(sit);
00321           DBG_ERROR(GWEN_LOGDOMAIN,
00322                     "Disconnecting signal \"%s\" from slot \"%s\"",
00323                     sig->name, slot->name);
00324           GWEN_Signal_List2_Remove(slot->connectedSignals, sig);
00325           slot=next;
00326         }
00327         GWEN_Slot_List2Iterator_free(sit);
00328       }
00329       GWEN_Slot_List2_free(sig->connectedSlots);
00330 
00331       free(sig->name);
00332       sig->_refCount=0;
00333       GWEN_FREE_OBJECT(sig);
00334     }
00335     else
00336       sig->_refCount--;
00337   }
00338 }
00339 
00340 
00341 
00342 void GWEN_Signal_Attach(GWEN_SIGNAL *sig) {
00343   assert(sig);
00344   assert(sig->_refCount);
00345   sig->_refCount++;
00346 }
00347 
00348 
00349 
00350 GWEN_SIGNAL *GWEN_Signal__List2_freeAll_cb(GWEN_SIGNAL *sig, void *user_data){
00351   GWEN_Signal_free(sig);
00352   return 0;
00353 }
00354 
00355 
00356 
00357 void GWEN_Signal_List2_freeAll(GWEN_SIGNAL_LIST2 *slist) {
00358   GWEN_Signal_List2_ForEach(slist, GWEN_Signal__List2_freeAll_cb, 0);
00359   GWEN_Signal_List2_free(slist);
00360 }
00361 
00362 
00363 
00364 GWEN_SIGNAL *GWEN_Signal__List2_hasSignal_cb(GWEN_SIGNAL *sig,
00365                                              void *user_data){
00366   if ((void*)sig==user_data)
00367     return sig;
00368   return 0;
00369 }
00370 
00371 
00372 
00373 int GWEN_Signal_List2_HasSignal(GWEN_SIGNAL_LIST2 *slist,
00374                                 const GWEN_SIGNAL *sig) {
00375   if (GWEN_Signal_List2_ForEach(slist, GWEN_Signal__List2_hasSignal_cb,
00376                                 (void*)sig))
00377     return 1;
00378   return 0;
00379 }
00380 
00381 
00382 
00383 GWEN_SIGNALOBJECT *GWEN_Signal_GetSignalObject(const GWEN_SIGNAL *sig) {
00384   assert(sig);
00385   return sig->signalObject;
00386 }
00387 
00388 
00389 
00390 int GWEN_Signal_Connect(GWEN_SIGNAL *sig, GWEN_SLOT *slot) {
00391   assert(sig);
00392   assert(slot);
00393   if (sig->typeOfArg1!=slot->typeOfArg1) {
00394     DBG_ERROR(GWEN_LOGDOMAIN,
00395               "Signal \"%s\" and slot \"%s\" use different types for "
00396               "argument 1",
00397               sig->name, slot->name);
00398     return GWEN_ERROR_INVALID;
00399   }
00400   if (sig->typeOfArg2!=slot->typeOfArg2) {
00401     DBG_ERROR(GWEN_LOGDOMAIN,
00402               "Signal \"%s\" and slot \"%s\" use different types for "
00403               "argument 2",
00404               sig->name, slot->name);
00405     return GWEN_ERROR_INVALID;
00406   }
00407   if (GWEN_Signal_List2_HasSignal(slot->connectedSignals, sig)) {
00408     DBG_ERROR(GWEN_LOGDOMAIN,
00409               "Signal \"%s\" and slot \"%s\" already connected",
00410               sig->name, slot->name);
00411     return GWEN_ERROR_INVALID;
00412   }
00413 
00414   if (GWEN_Slot_List2_HasSlot(sig->connectedSlots, slot)) {
00415     DBG_ERROR(GWEN_LOGDOMAIN,
00416               "Signal \"%s\" and slot \"%s\" already connected",
00417               sig->name, slot->name);
00418     return GWEN_ERROR_INVALID;
00419   }
00420 
00421   GWEN_Signal_List2_PushBack(slot->connectedSignals, sig);
00422   GWEN_Slot_List2_PushBack(sig->connectedSlots, slot);
00423 
00424   return 0;
00425 }
00426 
00427 
00428 
00429 int GWEN_Signal_Disconnect(GWEN_SIGNAL *sig, GWEN_SLOT *slot) {
00430   assert(sig);
00431   assert(slot);
00432   if (GWEN_Signal_List2_HasSignal(slot->connectedSignals, sig)==0) {
00433     DBG_ERROR(GWEN_LOGDOMAIN,
00434               "Signal \"%s\" and slot \"%s\" are not connected",
00435               sig->name, slot->name);
00436     return GWEN_ERROR_INVALID;
00437   }
00438 
00439   if (GWEN_Slot_List2_HasSlot(sig->connectedSlots, slot)==0) {
00440     DBG_ERROR(GWEN_LOGDOMAIN,
00441               "Signal \"%s\" and slot \"%s\" are not connected",
00442               sig->name, slot->name);
00443     return GWEN_ERROR_INVALID;
00444   }
00445 
00446   GWEN_Signal_List2_Remove(slot->connectedSignals, sig);
00447   GWEN_Slot_List2_Remove(sig->connectedSlots, slot);
00448 
00449   return 0;
00450 }
00451 
00452 
00453 
00454 int GWEN_Signal_Emit(GWEN_SIGNAL *sig,
00455                      void *pArg1, void *pArg2, int iArg3, int iArg4) {
00456   GWEN_SLOT_LIST2_ITERATOR *sit;
00457   int result=0;
00458 
00459   assert(sig);
00460   sit=GWEN_Slot_List2_First(sig->connectedSlots);
00461   if (sit) {
00462     GWEN_SLOT *slot;
00463 
00464     slot=GWEN_Slot_List2Iterator_Data(sit);
00465     assert(slot);
00466     while(slot) {
00467       if (slot->func) {
00468         int rv;
00469 
00470         DBG_DEBUG(GWEN_LOGDOMAIN,
00471                   "Sending signal \"%s\" to slot \"%s\" (%p)",
00472                   sig->name, slot->name, slot);
00473         rv=slot->func(slot, slot->userData, pArg1, pArg2, iArg3, iArg4);
00474         if (rv>0) {
00475           DBG_DEBUG(GWEN_LOGDOMAIN,
00476                     "Slot \"%s\" (%p) returned an error (%d)",
00477                     slot->name, slot, rv);
00478           result=rv;
00479         }
00480       }
00481       slot=GWEN_Slot_List2Iterator_Next(sit);
00482     }
00483     GWEN_Slot_List2Iterator_free(sit);
00484   }
00485 
00486   return result;
00487 }
00488 
00489 
00490 
00491 
00492 
00493 
00494 GWEN_SLOT *GWEN_Slot_new(GWEN_SIGNALOBJECT *so,
00495                          const char *derivedType,
00496                          const char *name,
00497                          const char *typeOfArg1,
00498                          const char *typeOfArg2,
00499                          GWEN_SLOT_FUNCTION fn,
00500                          void *userData) {
00501   GWEN_SLOT *slot;
00502 
00503   assert(name);
00504   GWEN_NEW_OBJECT(GWEN_SLOT, slot)
00505   slot->_refCount=1;
00506   slot->connectedSignals=GWEN_Signal_List2_new();
00507   slot->name=strdup(name);
00508   if (typeOfArg1)
00509     slot->typeOfArg1=GWEN_SignalObject_MkTypeId(typeOfArg1);
00510   if (typeOfArg2)
00511     slot->typeOfArg2=GWEN_SignalObject_MkTypeId(typeOfArg2);
00512   if (derivedType)
00513     slot->derivedParentType=GWEN_SignalObject_MkTypeId(derivedType);
00514   slot->func=fn;
00515   slot->userData=userData;
00516 
00517   if (GWEN_SignalObject_AddSlot(so, slot)) {
00518     GWEN_Slot_free(slot);
00519     return 0;
00520   }
00521 
00522   return slot;
00523 }
00524 
00525 
00526 
00527 void GWEN_Slot_free(GWEN_SLOT *slot) {
00528   if (slot) {
00529     assert(slot->_refCount);
00530     if (slot->_refCount==1) {
00531       GWEN_SIGNAL_LIST2_ITERATOR *sit;
00532 
00533       /* remove from all connected signals */
00534       sit=GWEN_Signal_List2_First(slot->connectedSignals);
00535       if (sit) {
00536         GWEN_SIGNAL *sig;
00537 
00538         sig=GWEN_Signal_List2Iterator_Data(sit);
00539         assert(sig);
00540         while(sig) {
00541           DBG_ERROR(GWEN_LOGDOMAIN,
00542                     "Disconnecting slot \"%s\" from signal \"%s\"",
00543                     slot->name, sig->name);
00544           GWEN_Slot_List2_Remove(sig->connectedSlots, slot);
00545           sig=GWEN_Signal_List2Iterator_Next(sit);
00546         }
00547         GWEN_Signal_List2Iterator_free(sit);
00548       }
00549       GWEN_Signal_List2_free(slot->connectedSignals);
00550 
00551       free(slot->name);
00552       slot->_refCount=0;
00553       GWEN_FREE_OBJECT(slot);
00554     }
00555     else
00556       slot->_refCount--;
00557   }
00558 }
00559 
00560 
00561 
00562 void GWEN_Slot_Attach(GWEN_SLOT *slot) {
00563   assert(slot);
00564   assert(slot->_refCount);
00565   slot->_refCount++;
00566 }
00567 
00568 
00569 
00570 GWEN_SLOT *GWEN_Slot__List2_freeAll_cb(GWEN_SLOT *slot, void *user_data) {
00571   GWEN_Slot_free(slot);
00572   return 0;
00573 }
00574 
00575 
00576 
00577 void GWEN_Slot_List2_freeAll(GWEN_SLOT_LIST2 *slist) {
00578   GWEN_Slot_List2_ForEach(slist, GWEN_Slot__List2_freeAll_cb, 0);
00579   GWEN_Slot_List2_free(slist);
00580 }
00581 
00582 
00583 
00584 GWEN_SLOT *GWEN_Slot__List2_hasSlot_cb(GWEN_SLOT *slot,
00585                                        void *user_data){
00586   if ((void*)slot==user_data)
00587     return slot;
00588   return 0;
00589 }
00590 
00591 
00592 
00593 int GWEN_Slot_List2_HasSlot(GWEN_SLOT_LIST2 *slist,
00594                             const GWEN_SLOT *slot) {
00595   if (GWEN_Slot_List2_ForEach(slist, GWEN_Slot__List2_hasSlot_cb,
00596                               (void*)slot))
00597     return 1;
00598   return 0;
00599 }
00600 
00601 
00602 
00603 GWEN_SIGNALOBJECT *GWEN_Slot_GetSignalObject(const GWEN_SLOT *slot) {
00604   assert(slot);
00605   return slot->signalObject;
00606 }
00607 
00608 
00609 
00610 
00611 
00612 
00613 

Generated on Fri Apr 11 01:53:46 2008 for gwenhywfar by  doxygen 1.5.5