xref: /titanic_44/usr/src/lib/sun_fc/common/Listener.cc (revision fcf3ce441efd61da9bb2884968af01cb7c1452cc)
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  * @exception	    ... underlying exceptions will be thrown
70  */
~Listener()71 Listener::~Listener() {
72 	Lockable::lock(&staticLock);
73 	try {
74 	    for (ListenerIterator tmp = listeners.begin();
75 			tmp != listeners.end(); tmp++) {
76 		if (*tmp == this) {
77 		    listeners.erase(tmp);
78 		    Lockable::unlock(&staticLock);
79 		    return;
80 		}
81 	    }
82 	} catch (...) {
83 	    Lockable::unlock(&staticLock);
84 	    throw;
85 	}
86 	Lockable::unlock(&staticLock);
87 }
88 
89 /**
90  * @memo	    Find a listener based on the callback handle
91  * @exception	    InvalidHandleException if the callback handle does not
92  *		    match any listeners
93  * @return	    The Listener who matches the callback handle
94  * @param	    cbh The callback handle
95  */
findListener(void * cbh)96 Listener* Listener::findListener(void *cbh) {
97 	Lockable::lock(&staticLock);
98 	try {
99 	    for (ListenerIterator tmp = listeners.begin();
100 			tmp != listeners.end(); tmp++) {
101 		if (*tmp == cbh) {
102 		    Lockable::unlock(&staticLock);
103 		    return (*tmp);
104 		}
105 	    }
106 	} catch (...) {
107 	    Lockable::unlock(&staticLock);
108 	    throw;
109 	}
110 	Lockable::unlock(&staticLock);
111 	throw InvalidHandleException();
112 }
113