1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  *  You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 
27 
28 #include "Listener.h"
29 #include "Exceptions.h"
30 #include "Lockable.h"
31 
32 using namespace std;
33 
34 /**
35  * Global lock for list of listeners
36  */
37 pthread_mutex_t Listener::staticLock = PTHREAD_MUTEX_INITIALIZER;
38 
39 /**
40  * Global list of listeners
41  */
42 vector<Listener*> Listener::listeners;
43 
44 /**
45  * Type for listener list iteration
46  */
47 typedef vector<Listener *>::iterator ListenerIterator;
48 
49 /**
50  * @memo	    Create a new generic listener
51  * @exception	    ... underlying exceptions will be thrown
52  * @param	    userData The opaque user data for event callback
53  *
54  */
Listener(void * userData)55 Listener::Listener(void *userData) {
56 	data = userData;
57 	Lockable::lock(&staticLock);
58 	try {
59 	    listeners.insert(listeners.begin(), this);
60 	} catch (...) {
61 	    Lockable::unlock(&staticLock);
62 	    throw;
63 	}
64 	Lockable::unlock(&staticLock);
65 }
66 
67 /**
68  * @memo	    Free up a generic listener, keeping global list in sync.
69  */
~Listener()70 Listener::~Listener() {
71 	Lockable::lock(&staticLock);
72 	for (ListenerIterator tmp = listeners.begin();
73 	    tmp != listeners.end(); tmp++) {
74 		if (*tmp == this) {
75 			listeners.erase(tmp);
76 			break;
77 		}
78 	}
79 	Lockable::unlock(&staticLock);
80 }
81 
82 /**
83  * @memo	    Find a listener based on the callback handle
84  * @exception	    InvalidHandleException if the callback handle does not
85  *		    match any listeners
86  * @return	    The Listener who matches the callback handle
87  * @param	    cbh The callback handle
88  */
findListener(void * cbh)89 Listener* Listener::findListener(void *cbh) {
90 	Lockable::lock(&staticLock);
91 	try {
92 	    for (ListenerIterator tmp = listeners.begin();
93 			tmp != listeners.end(); tmp++) {
94 		if (*tmp == cbh) {
95 		    Lockable::unlock(&staticLock);
96 		    return (*tmp);
97 		}
98 	    }
99 	} catch (...) {
100 	    Lockable::unlock(&staticLock);
101 	    throw;
102 	}
103 	Lockable::unlock(&staticLock);
104 	throw InvalidHandleException();
105 }
106