1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /**
4  *******************************************************************************
5  * Copyright (C) 2001-2012, International Business Machines Corporation and    *
6  * others. All Rights Reserved.                                                *
7  *******************************************************************************
8  */
9 
10 #include "unicode/utypes.h"
11 
12 #if !UCONFIG_NO_SERVICE
13 
14 #include "servnotf.h"
15 #ifdef NOTIFIER_DEBUG
16 #include <stdio.h>
17 #endif
18 
19 U_NAMESPACE_BEGIN
20 
~EventListener()21 EventListener::~EventListener() {}
22 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(EventListener)
23 
24 static UMutex notifyLock = U_MUTEX_INITIALIZER;
25 
ICUNotifier(void)26 ICUNotifier::ICUNotifier(void)
27 : listeners(NULL)
28 {
29 }
30 
~ICUNotifier(void)31 ICUNotifier::~ICUNotifier(void) {
32     {
33         Mutex lmx(&notifyLock);
34         delete listeners;
35         listeners = NULL;
36     }
37 }
38 
39 
40 void
addListener(const EventListener * l,UErrorCode & status)41 ICUNotifier::addListener(const EventListener* l, UErrorCode& status)
42 {
43     if (U_SUCCESS(status)) {
44         if (l == NULL) {
45             status = U_ILLEGAL_ARGUMENT_ERROR;
46             return;
47         }
48 
49         if (acceptsListener(*l)) {
50             Mutex lmx(&notifyLock);
51             if (listeners == NULL) {
52                 listeners = new UVector(5, status);
53             } else {
54                 for (int i = 0, e = listeners->size(); i < e; ++i) {
55                     const EventListener* el = (const EventListener*)(listeners->elementAt(i));
56                     if (l == el) {
57                         return;
58                     }
59                 }
60             }
61 
62             listeners->addElement((void*)l, status); // cast away const
63         }
64 #ifdef NOTIFIER_DEBUG
65         else {
66             fprintf(stderr, "Listener invalid for this notifier.");
67             exit(1);
68         }
69 #endif
70     }
71 }
72 
73 void
removeListener(const EventListener * l,UErrorCode & status)74 ICUNotifier::removeListener(const EventListener *l, UErrorCode& status)
75 {
76     if (U_SUCCESS(status)) {
77         if (l == NULL) {
78             status = U_ILLEGAL_ARGUMENT_ERROR;
79             return;
80         }
81 
82         {
83             Mutex lmx(&notifyLock);
84             if (listeners != NULL) {
85                 // identity equality check
86                 for (int i = 0, e = listeners->size(); i < e; ++i) {
87                     const EventListener* el = (const EventListener*)listeners->elementAt(i);
88                     if (l == el) {
89                         listeners->removeElementAt(i);
90                         if (listeners->size() == 0) {
91                             delete listeners;
92                             listeners = NULL;
93                         }
94                         return;
95                     }
96                 }
97             }
98         }
99     }
100 }
101 
102 void
notifyChanged(void)103 ICUNotifier::notifyChanged(void)
104 {
105     if (listeners != NULL) {
106         Mutex lmx(&notifyLock);
107         if (listeners != NULL) {
108             for (int i = 0, e = listeners->size(); i < e; ++i) {
109                 EventListener* el = (EventListener*)listeners->elementAt(i);
110                 notifyListener(*el);
111             }
112         }
113     }
114 }
115 
116 U_NAMESPACE_END
117 
118 /* UCONFIG_NO_SERVICE */
119 #endif
120 
121