gwenhywfar  4.99.15beta
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  void *user_data)
381 {
382  if ((void *)sig==user_data)
383  return sig;
384  return 0;
385 }
386 
387 
388 
389 int GWEN_Signal_List2_HasSignal(GWEN_SIGNAL_LIST2 *slist,
390  const GWEN_SIGNAL *sig)
391 {
392  if (GWEN_Signal_List2_ForEach(slist, GWEN_Signal__List2_hasSignal_cb,
393  (void *)sig))
394  return 1;
395  return 0;
396 }
397 
398 
399 
401 {
402  assert(sig);
403  return sig->signalObject;
404 }
405 
406 
407 
409 {
410  assert(sig);
411  assert(slot);
412  if (sig->typeOfArg1!=slot->typeOfArg1) {
414  "Signal \"%s\" and slot \"%s\" use different types for "
415  "argument 1",
416  sig->name, slot->name);
417  return GWEN_ERROR_INVALID;
418  }
419  if (sig->typeOfArg2!=slot->typeOfArg2) {
421  "Signal \"%s\" and slot \"%s\" use different types for "
422  "argument 2",
423  sig->name, slot->name);
424  return GWEN_ERROR_INVALID;
425  }
426  if (GWEN_Signal_List2_HasSignal(slot->connectedSignals, sig)) {
428  "Signal \"%s\" and slot \"%s\" already connected",
429  sig->name, slot->name);
430  return GWEN_ERROR_INVALID;
431  }
432 
433  if (GWEN_Slot_List2_HasSlot(sig->connectedSlots, slot)) {
435  "Signal \"%s\" and slot \"%s\" already connected",
436  sig->name, slot->name);
437  return GWEN_ERROR_INVALID;
438  }
439 
440  GWEN_Signal_List2_PushBack(slot->connectedSignals, sig);
441  GWEN_Slot_List2_PushBack(sig->connectedSlots, slot);
442 
443  return 0;
444 }
445 
446 
447 
449 {
450  assert(sig);
451  assert(slot);
452  if (GWEN_Signal_List2_HasSignal(slot->connectedSignals, sig)==0) {
454  "Signal \"%s\" and slot \"%s\" are not connected",
455  sig->name, slot->name);
456  return GWEN_ERROR_INVALID;
457  }
458 
459  if (GWEN_Slot_List2_HasSlot(sig->connectedSlots, slot)==0) {
461  "Signal \"%s\" and slot \"%s\" are not connected",
462  sig->name, slot->name);
463  return GWEN_ERROR_INVALID;
464  }
465 
466  GWEN_Signal_List2_Remove(slot->connectedSignals, sig);
467  GWEN_Slot_List2_Remove(sig->connectedSlots, slot);
468 
469  return 0;
470 }
471 
472 
473 
475  void *pArg1, void *pArg2, int iArg3, int iArg4)
476 {
477  GWEN_SLOT_LIST2_ITERATOR *sit;
478  int result=0;
479 
480  assert(sig);
481  sit=GWEN_Slot_List2_First(sig->connectedSlots);
482  if (sit) {
483  GWEN_SLOT *slot;
484 
485  slot=GWEN_Slot_List2Iterator_Data(sit);
486  assert(slot);
487  while (slot) {
488  if (slot->func) {
489  int rv;
490 
492  "Sending signal \"%s\" to slot \"%s\" (%p)",
493  sig->name, slot->name, slot);
494  rv=slot->func(slot, slot->userData, pArg1, pArg2, iArg3, iArg4);
495  if (rv>0) {
497  "Slot \"%s\" (%p) returned an error (%d)",
498  slot->name, slot, rv);
499  result=rv;
500  }
501  }
502  slot=GWEN_Slot_List2Iterator_Next(sit);
503  }
504  GWEN_Slot_List2Iterator_free(sit);
505  }
506 
507  return result;
508 }
509 
510 
511 
512 
513 
514 
516  const char *derivedType,
517  const char *name,
518  const char *typeOfArg1,
519  const char *typeOfArg2,
521  void *userData)
522 {
523  GWEN_SLOT *slot;
524 
525  assert(name);
527  slot->_refCount=1;
528  slot->connectedSignals=GWEN_Signal_List2_new();
529  slot->name=strdup(name);
530  if (typeOfArg1)
531  slot->typeOfArg1=GWEN_SignalObject_MkTypeId(typeOfArg1);
532  if (typeOfArg2)
533  slot->typeOfArg2=GWEN_SignalObject_MkTypeId(typeOfArg2);
534  if (derivedType)
535  slot->derivedParentType=GWEN_SignalObject_MkTypeId(derivedType);
536  slot->func=fn;
537  slot->userData=userData;
538 
539  if (GWEN_SignalObject_AddSlot(so, slot)) {
540  GWEN_Slot_free(slot);
541  return 0;
542  }
543 
544  return slot;
545 }
546 
547 
548 
550 {
551  if (slot) {
552  assert(slot->_refCount);
553  if (slot->_refCount==1) {
554  GWEN_SIGNAL_LIST2_ITERATOR *sit;
555 
556  /* remove from all connected signals */
557  sit=GWEN_Signal_List2_First(slot->connectedSignals);
558  if (sit) {
559  GWEN_SIGNAL *sig;
560 
561  sig=GWEN_Signal_List2Iterator_Data(sit);
562  assert(sig);
563  while (sig) {
565  "Disconnecting slot \"%s\" from signal \"%s\"",
566  slot->name, sig->name);
567  GWEN_Slot_List2_Remove(sig->connectedSlots, slot);
568  sig=GWEN_Signal_List2Iterator_Next(sit);
569  }
570  GWEN_Signal_List2Iterator_free(sit);
571  }
572  GWEN_Signal_List2_free(slot->connectedSignals);
573 
574  free(slot->name);
575  slot->_refCount=0;
576  GWEN_FREE_OBJECT(slot);
577  }
578  else
579  slot->_refCount--;
580  }
581 }
582 
583 
584 
586 {
587  assert(slot);
588  assert(slot->_refCount);
589  slot->_refCount++;
590 }
591 
592 
593 
595 {
596  GWEN_Slot_free(slot);
597  return 0;
598 }
599 
600 
601 
602 void GWEN_Slot_List2_freeAll(GWEN_SLOT_LIST2 *slist)
603 {
604  GWEN_Slot_List2_ForEach(slist, GWEN_Slot__List2_freeAll_cb, 0);
605  GWEN_Slot_List2_free(slist);
606 }
607 
608 
609 
611  void *user_data)
612 {
613  if ((void *)slot==user_data)
614  return slot;
615  return 0;
616 }
617 
618 
619 
620 int GWEN_Slot_List2_HasSlot(GWEN_SLOT_LIST2 *slist,
621  const GWEN_SLOT *slot)
622 {
623  if (GWEN_Slot_List2_ForEach(slist, GWEN_Slot__List2_hasSlot_cb,
624  (void *)slot))
625  return 1;
626  return 0;
627 }
628 
629 
630 
632 {
633  assert(slot);
634  return slot->signalObject;
635 }
636 
637 
638 
639 
640 
641 
642 
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:610
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:400
void GWEN_Signal_List2_freeAll(GWEN_SIGNAL_LIST2 *slist)
Definition: gwensignal.c:371
#define GWEN_FREE_OBJECT(varname)
Definition: memory.h:92
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:549
void GWEN_Slot_List2_freeAll(GWEN_SLOT_LIST2 *slist)
Definition: gwensignal.c:602
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:631
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:86
#define DBG_DEBUG(dbg_logger, format, args...)
Definition: debug.h:208
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:515
GWEN_SLOT * GWEN_Slot__List2_freeAll_cb(GWEN_SLOT *slot, GWEN_UNUSED void *user_data)
Definition: gwensignal.c:594
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
GWEN_LIST2_FUNCTIONS(TYPEMAKER2_TYPE, Typemaker2_Type)
int GWEN_Signal_Connect(GWEN_SIGNAL *sig, GWEN_SLOT *slot)
Definition: gwensignal.c:408
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
void GWEN_Signal_free(GWEN_SIGNAL *sig)
Definition: gwensignal.c:315
int GWEN_Signal_List2_HasSignal(GWEN_SIGNAL_LIST2 *slist, const GWEN_SIGNAL *sig)
Definition: gwensignal.c:389
int GWEN_Signal_Emit(GWEN_SIGNAL *sig, void *pArg1, void *pArg2, int iArg3, int iArg4)
Definition: gwensignal.c:474
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:177
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 GWEN_Slot_List2_HasSlot(GWEN_SLOT_LIST2 *slist, const GWEN_SLOT *slot)
Definition: gwensignal.c:620
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:585
int GWEN_Signal_Disconnect(GWEN_SIGNAL *sig, GWEN_SLOT *slot)
Definition: gwensignal.c:448
void GWEN_Signal_Attach(GWEN_SIGNAL *sig)
Definition: gwensignal.c:354