gwenhywfar  5.10.1
gwensignal.c
Go to the documentation of this file.
1 /***************************************************************************
2  $RCSfile$
3  -------------------
4  cvs : $Id: stringlist.c 1067 2006-05-22 15:25:23Z christian $
5  begin : Thu Apr 03 2003
6  copyright : (C) 2003 by Martin Preuss
7  email : martin@libchipcard.de
8 
9  ***************************************************************************
10  * *
11  * This library is free software; you can redistribute it and/or *
12  * modify it under the terms of the GNU Lesser General Public *
13  * License as published by the Free Software Foundation; either *
14  * version 2.1 of the License, or (at your option) any later version. *
15  * *
16  * This library is distributed in the hope that it will be useful, *
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
19  * Lesser General Public License for more details. *
20  * *
21  * You should have received a copy of the GNU Lesser General Public *
22  * License along with this library; if not, write to the Free Software *
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
24  * MA 02111-1307 USA *
25  * *
26  ***************************************************************************/
27 
28 #ifdef HAVE_CONFIG_H
29 # include <config.h>
30 #endif
31 
32 #include "gwensignal_p.h"
33 #include <gwenhywfar/misc.h>
34 #include <gwenhywfar/debug.h>
35 #include <gwenhywfar/inherit.h>
36 #include <stdlib.h>
37 #include <assert.h>
38 #include <string.h>
39 
40 
41 
44 
45 
47 {
49 
51  so->signalList=GWEN_Signal_List2_new();
52  so->slotList=GWEN_Slot_List2_new();
53 
54  return so;
55 }
56 
57 
58 
60 {
61  if (so) {
62  GWEN_Slot_List2_freeAll(so->slotList);
63  GWEN_Signal_List2_freeAll(so->signalList);
64  GWEN_FREE_OBJECT(so);
65  }
66 }
67 
68 
69 
70 uint32_t GWEN_SignalObject_MkTypeId(const char *typeName)
71 {
72  return GWEN_Inherit_MakeId(typeName);
73 }
74 
75 
76 
78  const char *name,
79  uint32_t typeId1,
80  uint32_t typeId2)
81 {
82  GWEN_SIGNAL_LIST2_ITERATOR *sit;
83 
84  assert(so);
85  assert(name);
86 
87  sit=GWEN_Signal_List2_First(so->signalList);
88  if (sit) {
89  GWEN_SIGNAL *sig;
90 
91  sig=GWEN_Signal_List2Iterator_Data(sit);
92  assert(sig);
93  while (sig) {
94  const char *s;
95 
96  s=sig->name;
97  assert(s);
98  if (strcasecmp(s, name)==0 &&
99  (typeId1==0 || typeId1==sig->typeOfArg1) &&
100  (typeId2==0 || typeId2==sig->typeOfArg2)) {
101  GWEN_Signal_List2Iterator_free(sit);
102  return sig;
103  }
104  sig=GWEN_Signal_List2Iterator_Next(sit);
105  }
106  GWEN_Signal_List2Iterator_free(sit);
107  }
108 
109  return 0;
110 }
111 
112 
113 
115  const char *name,
116  const char *typeOfArg1,
117  const char *typeOfArg2)
118 {
119  uint32_t typeId1=0;
120  uint32_t typeId2=0;
121 
122  if (typeOfArg1)
123  typeId1=GWEN_SignalObject_MkTypeId(typeOfArg1);
124  if (typeOfArg2)
125  typeId2=GWEN_SignalObject_MkTypeId(typeOfArg2);
126  return GWEN_SignalObject__findSignal(so, name, typeId1, typeId2);
127 }
128 
129 
130 
132  const char *name,
133  uint32_t typeId1,
134  uint32_t typeId2)
135 {
136  GWEN_SLOT_LIST2_ITERATOR *sit;
137 
138  assert(so);
139  assert(name);
140 
141  sit=GWEN_Slot_List2_First(so->slotList);
142  if (sit) {
143  GWEN_SLOT *slot;
144 
145  slot=GWEN_Slot_List2Iterator_Data(sit);
146  assert(slot);
147  while (slot) {
148  const char *s;
149 
150  s=slot->name;
151  assert(s);
152  if (strcasecmp(s, name)==0 &&
153  (typeId1==0 || typeId1==slot->typeOfArg1) &&
154  (typeId2==0 || typeId2==slot->typeOfArg2)) {
155  GWEN_Slot_List2Iterator_free(sit);
156  return slot;
157  }
158  slot=GWEN_Slot_List2Iterator_Next(sit);
159  }
160  GWEN_Slot_List2Iterator_free(sit);
161  }
162 
163  return 0;
164 }
165 
166 
167 
169  const char *name,
170  const char *typeOfArg1,
171  const char *typeOfArg2)
172 {
173  uint32_t typeId1=0;
174  uint32_t typeId2=0;
175 
176  if (typeOfArg1)
177  typeId1=GWEN_SignalObject_MkTypeId(typeOfArg1);
178  if (typeOfArg2)
179  typeId2=GWEN_SignalObject_MkTypeId(typeOfArg2);
180  return GWEN_SignalObject__findSlot(so, name, typeId1, typeId2);
181 }
182 
183 
184 
186 {
187  if (GWEN_SignalObject__findSignal(so, sig->name,
188  sig->typeOfArg1,
189  sig->typeOfArg2)) {
191  "Signal \"%s\" already exists",
192  sig->name);
193  return GWEN_ERROR_INVALID;
194  }
195 
196  sig->signalObject=so;
197  GWEN_Signal_List2_PushBack(so->signalList, sig);
198  DBG_INFO(GWEN_LOGDOMAIN, "Added signal \"%s\"", sig->name);
199  return 0;
200 }
201 
202 
203 
205 {
206  if (GWEN_SignalObject__findSlot(so, slot->name,
207  slot->typeOfArg1,
208  slot->typeOfArg2)) {
210  "Slot \"%s\" already exists",
211  slot->name);
212  return GWEN_ERROR_INVALID;
213  }
214  slot->signalObject=so;
215  GWEN_Slot_List2_PushBack(so->slotList, slot);
216  DBG_INFO(GWEN_LOGDOMAIN, "Added slot \"%s\"", slot->name);
217  return 0;
218 }
219 
220 
221 
223  const char *derivedType)
224 {
225  uint32_t typeId=0;
226  GWEN_SLOT_LIST2_ITERATOR *slotIt;
227  GWEN_SIGNAL_LIST2_ITERATOR *sigIt;
228 
229  assert(so);
230  if (derivedType)
231  typeId=GWEN_SignalObject_MkTypeId(derivedType);
232 
233  slotIt=GWEN_Slot_List2_First(so->slotList);
234  if (slotIt) {
235  GWEN_SLOT *slot;
236 
237  slot=GWEN_Slot_List2Iterator_Data(slotIt);
238  assert(slot);
239  while (slot) {
240  const char *s;
241 
242  s=slot->name;
243  assert(s);
244  if (typeId==0 || slot->derivedParentType==typeId) {
245  GWEN_Slot_List2_Erase(so->slotList, slotIt);
246  GWEN_Slot_free(slot);
247  /* iterator now points to the next entry in any case (or NULL) */
248  slot=GWEN_Slot_List2Iterator_Data(slotIt);
249  }
250  else
251  slot=GWEN_Slot_List2Iterator_Next(slotIt);
252  }
253  GWEN_Slot_List2Iterator_free(slotIt);
254  }
255 
256  sigIt=GWEN_Signal_List2_First(so->signalList);
257  if (sigIt) {
258  GWEN_SIGNAL *sig;
259 
260  sig=GWEN_Signal_List2Iterator_Data(sigIt);
261  assert(sig);
262  while (sig) {
263  const char *s;
264 
265  s=sig->name;
266  assert(s);
267  if (typeId==0 || sig->derivedParentType==typeId) {
268  GWEN_Signal_List2_Erase(so->signalList, sigIt);
269  GWEN_Signal_free(sig);
270  /* iterator now points to the next entry in any case (or NULL) */
271  sig=GWEN_Signal_List2Iterator_Data(sigIt);
272  }
273  else
274  sig=GWEN_Signal_List2Iterator_Next(sigIt);
275  }
276  GWEN_Signal_List2Iterator_free(sigIt);
277  }
278 }
279 
280 
281 
282 
283 
285  const char *derivedType,
286  const char *name,
287  const char *typeOfArg1,
288  const char *typeOfArg2)
289 {
290  GWEN_SIGNAL *sig;
291 
292  assert(so);
293  assert(name);
295  sig->_refCount=1;
296  sig->connectedSlots=GWEN_Slot_List2_new();
297  sig->name=strdup(name);
298  if (typeOfArg1)
299  sig->typeOfArg1=GWEN_SignalObject_MkTypeId(typeOfArg1);
300  if (typeOfArg2)
301  sig->typeOfArg2=GWEN_SignalObject_MkTypeId(typeOfArg2);
302  if (derivedType)
303  sig->derivedParentType=GWEN_SignalObject_MkTypeId(derivedType);
304 
305  if (GWEN_SignalObject_AddSignal(so, sig)) {
306  GWEN_Signal_free(sig);
307  return 0;
308  }
309 
310  return sig;
311 }
312 
313 
314 
316 {
317  if (sig) {
318  assert(sig->_refCount);
319  if (sig->_refCount==1) {
320  GWEN_SLOT_LIST2_ITERATOR *sit;
321 
322  /* remove from all connected slots */
323  sit=GWEN_Slot_List2_First(sig->connectedSlots);
324  if (sit) {
325  GWEN_SLOT *slot;
326 
327  slot=GWEN_Slot_List2Iterator_Data(sit);
328  assert(slot);
329  while (slot) {
330  GWEN_SLOT *next;
331 
332  next=GWEN_Slot_List2Iterator_Next(sit);
334  "Disconnecting signal \"%s\" from slot \"%s\"",
335  sig->name, slot->name);
336  GWEN_Signal_List2_Remove(slot->connectedSignals, sig);
337  slot=next;
338  }
339  GWEN_Slot_List2Iterator_free(sit);
340  }
341  GWEN_Slot_List2_free(sig->connectedSlots);
342 
343  free(sig->name);
344  sig->_refCount=0;
345  GWEN_FREE_OBJECT(sig);
346  }
347  else
348  sig->_refCount--;
349  }
350 }
351 
352 
353 
355 {
356  assert(sig);
357  assert(sig->_refCount);
358  sig->_refCount++;
359 }
360 
361 
362 
364 {
365  GWEN_Signal_free(sig);
366  return 0;
367 }
368 
369 
370 
371 void GWEN_Signal_List2_freeAll(GWEN_SIGNAL_LIST2 *slist)
372 {
373  GWEN_Signal_List2_ForEach(slist, GWEN_Signal__List2_freeAll_cb, 0);
374  GWEN_Signal_List2_free(slist);
375 }
376 
377 
378 
380 {
381  if ((void *)sig==user_data)
382  return sig;
383  return 0;
384 }
385 
386 
387 
388 int GWEN_Signal_List2_HasSignal(GWEN_SIGNAL_LIST2 *slist, GWEN_SIGNAL *sig)
389 {
390  if (GWEN_Signal_List2_ForEach(slist, GWEN_Signal__List2_hasSignal_cb,
391  (void *)sig))
392  return 1;
393  return 0;
394 }
395 
396 
397 
399 {
400  assert(sig);
401  return sig->signalObject;
402 }
403 
404 
405 
407 {
408  assert(sig);
409  assert(slot);
410  if (sig->typeOfArg1!=slot->typeOfArg1) {
412  "Signal \"%s\" and slot \"%s\" use different types for "
413  "argument 1",
414  sig->name, slot->name);
415  return GWEN_ERROR_INVALID;
416  }
417  if (sig->typeOfArg2!=slot->typeOfArg2) {
419  "Signal \"%s\" and slot \"%s\" use different types for "
420  "argument 2",
421  sig->name, slot->name);
422  return GWEN_ERROR_INVALID;
423  }
424  if (GWEN_Signal_List2_HasSignal(slot->connectedSignals, sig)) {
426  "Signal \"%s\" and slot \"%s\" already connected",
427  sig->name, slot->name);
428  return GWEN_ERROR_INVALID;
429  }
430 
431  if (GWEN_Slot_List2_HasSlot(sig->connectedSlots, slot)) {
433  "Signal \"%s\" and slot \"%s\" already connected",
434  sig->name, slot->name);
435  return GWEN_ERROR_INVALID;
436  }
437 
438  GWEN_Signal_List2_PushBack(slot->connectedSignals, sig);
439  GWEN_Slot_List2_PushBack(sig->connectedSlots, slot);
440 
441  return 0;
442 }
443 
444 
445 
447 {
448  assert(sig);
449  assert(slot);
450  if (GWEN_Signal_List2_HasSignal(slot->connectedSignals, sig)==0) {
452  "Signal \"%s\" and slot \"%s\" are not connected",
453  sig->name, slot->name);
454  return GWEN_ERROR_INVALID;
455  }
456 
457  if (GWEN_Slot_List2_HasSlot(sig->connectedSlots, slot)==0) {
459  "Signal \"%s\" and slot \"%s\" are not connected",
460  sig->name, slot->name);
461  return GWEN_ERROR_INVALID;
462  }
463 
464  GWEN_Signal_List2_Remove(slot->connectedSignals, sig);
465  GWEN_Slot_List2_Remove(sig->connectedSlots, slot);
466 
467  return 0;
468 }
469 
470 
471 
473  void *pArg1, void *pArg2, int iArg3, int iArg4)
474 {
475  GWEN_SLOT_LIST2_ITERATOR *sit;
476  int result=0;
477 
478  assert(sig);
479  sit=GWEN_Slot_List2_First(sig->connectedSlots);
480  if (sit) {
481  GWEN_SLOT *slot;
482 
483  slot=GWEN_Slot_List2Iterator_Data(sit);
484  assert(slot);
485  while (slot) {
486  if (slot->func) {
487  int rv;
488 
490  "Sending signal \"%s\" to slot \"%s\" (%p)",
491  sig->name, slot->name, slot);
492  rv=slot->func(slot, slot->userData, pArg1, pArg2, iArg3, iArg4);
493  if (rv>0) {
495  "Slot \"%s\" (%p) returned an error (%d)",
496  slot->name, slot, rv);
497  result=rv;
498  }
499  }
500  slot=GWEN_Slot_List2Iterator_Next(sit);
501  }
502  GWEN_Slot_List2Iterator_free(sit);
503  }
504 
505  return result;
506 }
507 
508 
509 
510 
511 
512 
514  const char *derivedType,
515  const char *name,
516  const char *typeOfArg1,
517  const char *typeOfArg2,
519  void *userData)
520 {
521  GWEN_SLOT *slot;
522 
523  assert(name);
525  slot->_refCount=1;
526  slot->connectedSignals=GWEN_Signal_List2_new();
527  slot->name=strdup(name);
528  if (typeOfArg1)
529  slot->typeOfArg1=GWEN_SignalObject_MkTypeId(typeOfArg1);
530  if (typeOfArg2)
531  slot->typeOfArg2=GWEN_SignalObject_MkTypeId(typeOfArg2);
532  if (derivedType)
533  slot->derivedParentType=GWEN_SignalObject_MkTypeId(derivedType);
534  slot->func=fn;
535  slot->userData=userData;
536 
537  if (GWEN_SignalObject_AddSlot(so, slot)) {
538  GWEN_Slot_free(slot);
539  return 0;
540  }
541 
542  return slot;
543 }
544 
545 
546 
548 {
549  if (slot) {
550  assert(slot->_refCount);
551  if (slot->_refCount==1) {
552  GWEN_SIGNAL_LIST2_ITERATOR *sit;
553 
554  /* remove from all connected signals */
555  sit=GWEN_Signal_List2_First(slot->connectedSignals);
556  if (sit) {
557  GWEN_SIGNAL *sig;
558 
559  sig=GWEN_Signal_List2Iterator_Data(sit);
560  assert(sig);
561  while (sig) {
563  "Disconnecting slot \"%s\" from signal \"%s\"",
564  slot->name, sig->name);
565  GWEN_Slot_List2_Remove(sig->connectedSlots, slot);
566  sig=GWEN_Signal_List2Iterator_Next(sit);
567  }
568  GWEN_Signal_List2Iterator_free(sit);
569  }
570  GWEN_Signal_List2_free(slot->connectedSignals);
571 
572  free(slot->name);
573  slot->_refCount=0;
574  GWEN_FREE_OBJECT(slot);
575  }
576  else
577  slot->_refCount--;
578  }
579 }
580 
581 
582 
584 {
585  assert(slot);
586  assert(slot->_refCount);
587  slot->_refCount++;
588 }
589 
590 
591 
593 {
594  GWEN_Slot_free(slot);
595  return 0;
596 }
597 
598 
599 
600 void GWEN_Slot_List2_freeAll(GWEN_SLOT_LIST2 *slist)
601 {
602  GWEN_Slot_List2_ForEach(slist, GWEN_Slot__List2_freeAll_cb, 0);
603  GWEN_Slot_List2_free(slist);
604 }
605 
606 
607 
609  void *user_data)
610 {
611  if ((void *)slot==user_data)
612  return slot;
613  return 0;
614 }
615 
616 
617 
618 int GWEN_Slot_List2_HasSlot(GWEN_SLOT_LIST2 *slist, GWEN_SLOT *slot)
619 {
620  if (GWEN_Slot_List2_ForEach(slist, GWEN_Slot__List2_hasSlot_cb, (void *)slot))
621  return 1;
622  return 0;
623 }
624 
625 
626 
628 {
629  assert(slot);
630  return slot->signalObject;
631 }
632 
633 
634 
635 
636 
637 
638 
struct GWEN_SIGNALOBJECT GWEN_SIGNALOBJECT
Definition: gwensignal.h:65
GWEN_SLOT * GWEN_Slot__List2_hasSlot_cb(GWEN_SLOT *slot, void *user_data)
Definition: gwensignal.c:608
#define GWEN_LIST2_FUNCTIONS(t, pr)
Definition: list2.h:99
GWEN_SIGNAL * GWEN_SignalObject_FindSignal(const GWEN_SIGNALOBJECT *so, const char *name, const char *typeOfArg1, const char *typeOfArg2)
Definition: gwensignal.c:114
#define GWEN_ERROR_INVALID
Definition: error.h:67
GWEN_SIGNALOBJECT * GWEN_Signal_GetSignalObject(const GWEN_SIGNAL *sig)
Definition: gwensignal.c:398
void GWEN_Signal_List2_freeAll(GWEN_SIGNAL_LIST2 *slist)
Definition: gwensignal.c:371
#define GWEN_FREE_OBJECT(varname)
Definition: memory.h:61
GWEN_SIGNAL * GWEN_Signal__List2_hasSignal_cb(GWEN_SIGNAL *sig, void *user_data)
Definition: gwensignal.c:379
void GWEN_Slot_free(GWEN_SLOT *slot)
Definition: gwensignal.c:547
void GWEN_Slot_List2_freeAll(GWEN_SLOT_LIST2 *slist)
Definition: gwensignal.c:600
GWEN_SIGNAL * GWEN_SignalObject__findSignal(const GWEN_SIGNALOBJECT *so, const char *name, uint32_t typeId1, uint32_t typeId2)
Definition: gwensignal.c:77
GWEN_SIGNALOBJECT * GWEN_SignalObject_new(void)
Definition: gwensignal.c:46
GWEN_SIGNALOBJECT * GWEN_Slot_GetSignalObject(const GWEN_SLOT *slot)
Definition: gwensignal.c:627
int GWEN_Signal_List2_HasSignal(GWEN_SIGNAL_LIST2 *slist, GWEN_SIGNAL *sig)
Definition: gwensignal.c:388
uint32_t GWEN_Inherit_MakeId(const char *typeName)
Definition: inherit.c:140
#define GWEN_LOGDOMAIN
Definition: logger.h:35
int GWEN_SignalObject_AddSlot(GWEN_SIGNALOBJECT *so, GWEN_SLOT *slot)
Definition: gwensignal.c:204
#define GWEN_NEW_OBJECT(typ, varname)
Definition: memory.h:55
#define DBG_DEBUG(dbg_logger, format, args...)
Definition: debug.h:214
GWEN_SLOT * GWEN_Slot_new(GWEN_SIGNALOBJECT *so, const char *derivedType, const char *name, const char *typeOfArg1, const char *typeOfArg2, GWEN_SLOT_FUNCTION fn, void *userData)
Definition: gwensignal.c:513
GWEN_SLOT * GWEN_Slot__List2_freeAll_cb(GWEN_SLOT *slot, GWEN_UNUSED void *user_data)
Definition: gwensignal.c:592
struct GWEN_SIGNAL GWEN_SIGNAL
Definition: gwensignal.h:67
void GWEN_SignalObject_free(GWEN_SIGNALOBJECT *so)
Definition: gwensignal.c:59
GWEN_SLOT * GWEN_SignalObject_FindSlot(const GWEN_SIGNALOBJECT *so, const char *name, const char *typeOfArg1, const char *typeOfArg2)
Definition: gwensignal.c:168
int GWEN_Signal_Connect(GWEN_SIGNAL *sig, GWEN_SLOT *slot)
Definition: gwensignal.c:406
GWEN_SIGNAL * GWEN_Signal__List2_freeAll_cb(GWEN_SIGNAL *sig, GWEN_UNUSED void *user_data)
Definition: gwensignal.c:363
#define DBG_ERROR(dbg_logger, format, args...)
Definition: debug.h:97
int GWEN_Slot_List2_HasSlot(GWEN_SLOT_LIST2 *slist, GWEN_SLOT *slot)
Definition: gwensignal.c:618
void GWEN_Signal_free(GWEN_SIGNAL *sig)
Definition: gwensignal.c:315
int GWEN_Signal_Emit(GWEN_SIGNAL *sig, void *pArg1, void *pArg2, int iArg3, int iArg4)
Definition: gwensignal.c:472
GWEN_SIGNAL * GWEN_Signal_new(GWEN_SIGNALOBJECT *so, const char *derivedType, const char *name, const char *typeOfArg1, const char *typeOfArg2)
Definition: gwensignal.c:284
struct GWEN_SLOT GWEN_SLOT
Definition: gwensignal.h:69
void GWEN_SignalObject_RemoveForDerivedType(GWEN_SIGNALOBJECT *so, const char *derivedType)
Definition: gwensignal.c:222
#define DBG_INFO(dbg_logger, format, args...)
Definition: debug.h:181
uint32_t GWEN_SignalObject_MkTypeId(const char *typeName)
Definition: gwensignal.c:70
GWEN_SLOT * GWEN_SignalObject__findSlot(const GWEN_SIGNALOBJECT *so, const char *name, uint32_t typeId1, uint32_t typeId2)
Definition: gwensignal.c:131
int GWENHYWFAR_CB(* GWEN_SLOT_FUNCTION)(GWEN_SLOT *slot, void *userData, void *pArg1, void *pArg2, int iArg3, int iArg4)
Definition: gwensignal.h:76
int GWEN_SignalObject_AddSignal(GWEN_SIGNALOBJECT *so, GWEN_SIGNAL *sig)
Definition: gwensignal.c:185
#define GWEN_UNUSED
void GWEN_Slot_Attach(GWEN_SLOT *slot)
Definition: gwensignal.c:583
int GWEN_Signal_Disconnect(GWEN_SIGNAL *sig, GWEN_SLOT *slot)
Definition: gwensignal.c:446
void GWEN_Signal_Attach(GWEN_SIGNAL *sig)
Definition: gwensignal.c:354