00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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
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
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
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
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