<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[Freeswitch-trunk][16697] </title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<div id="header">FreeSWITCH Subversion</div>
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://fisheye.freeswitch.org/changelog/FreeSWITCH?cs=16697">16697</a></dd>
<dt>Author</dt> <dd>andrew</dd>
<dt>Date</dt> <dd>2010-02-18 15:55:46 -0600 (Thu, 18 Feb 2010)</dd>
</dl>

<h3>Log Message</h3>
<pre>Replace busy wait for XML fetch with thread cond stuff (Original patch contributed by Michael Fig / MarkeTel Systems)</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#freeswitchtrunksrcmodevent_handlersmod_erlang_eventhandle_msgc">freeswitch/trunk/src/mod/event_handlers/mod_erlang_event/handle_msg.c</a></li>
<li><a href="#freeswitchtrunksrcmodevent_handlersmod_erlang_eventmod_erlang_eventc">freeswitch/trunk/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c</a></li>
<li><a href="#freeswitchtrunksrcmodevent_handlersmod_erlang_eventmod_erlang_eventh">freeswitch/trunk/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="freeswitchtrunksrcmodevent_handlersmod_erlang_eventhandle_msgc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/src/mod/event_handlers/mod_erlang_event/handle_msg.c (16696 => 16697)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/src/mod/event_handlers/mod_erlang_event/handle_msg.c        2010-02-18 20:22:32 UTC (rev 16696)
+++ freeswitch/trunk/src/mod/event_handlers/mod_erlang_event/handle_msg.c        2010-02-18 21:55:46 UTC (rev 16697)
</span><span class="lines">@@ -166,7 +166,7 @@
</span><span class="cx"> static switch_status_t handle_msg_fetch_reply(listener_t *listener, ei_x_buff * buf, ei_x_buff * rbuf)
</span><span class="cx"> {
</span><span class="cx">         char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
</span><del>-        void *p;
</del><ins>+        fetch_reply_t *p;
</ins><span class="cx"> 
</span><span class="cx">         if (ei_decode_string_or_binary(buf-&gt;buff, &amp;buf-&gt;index, SWITCH_UUID_FORMATTED_LENGTH, uuid_str)) {
</span><span class="cx">                 ei_x_encode_tuple_header(rbuf, 2);
</span><span class="lines">@@ -179,20 +179,40 @@
</span><span class="cx">                 nbuf-&gt;index = buf-&gt;index;
</span><span class="cx">                 nbuf-&gt;buffsz = buf-&gt;buffsz;
</span><span class="cx"> 
</span><del>-                if ((p = switch_core_hash_find(listener-&gt;fetch_reply_hash, uuid_str))) {
-                        if (p == &amp;globals.TIMEOUT) {
</del><ins>+                switch_mutex_lock(globals.fetch_reply_mutex);
+                if ((p = switch_core_hash_find(globals.fetch_reply_hash, uuid_str))) {
+                        /* Get the status and release the lock ASAP. */
+                        enum { is_timeout, is_waiting, is_filled } status;
+                        if (p-&gt;state == reply_not_ready) {
+                                switch_thread_cond_wait(p-&gt;ready_or_found, globals.fetch_reply_mutex);
+                        }
+
+                        if (p-&gt;state == reply_waiting) {
+                                /* update the key with a reply */
+                                status = is_waiting;
+                                p-&gt;reply = nbuf;
+                                p-&gt;state = reply_found;
+                                strncpy(p-&gt;winner, listener-&gt;peer_nodename, MAXNODELEN);
+                                switch_thread_cond_broadcast(p-&gt;ready_or_found);
+                        } else if (p-&gt;state == reply_timeout) {
+                                status = is_timeout;
+                        } else {
+                                status = is_filled;
+                        }
+
+                        put_reply_unlock(p, uuid_str);
+
+                        /* Relay the status back to the fetch responder. */
+                        if (status == is_waiting) {
+                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, &quot;Found waiting slot for %s\n&quot;, uuid_str);
+                                ei_x_encode_atom(rbuf, &quot;ok&quot;);
+                                /* Return here to avoid freeing the reply. */
+                                return SWITCH_STATUS_SUCCESS;
+                        } else if (status == is_timeout) {
</ins><span class="cx">                                 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, &quot;Handler for %s timed out\n&quot;, uuid_str);
</span><del>-                                switch_core_hash_delete(listener-&gt;fetch_reply_hash, uuid_str);
</del><span class="cx">                                 ei_x_encode_tuple_header(rbuf, 2);
</span><span class="cx">                                 ei_x_encode_atom(rbuf, &quot;error&quot;);
</span><span class="cx">                                 ei_x_encode_atom(rbuf, &quot;timeout&quot;);
</span><del>-                        } else if (p == &amp;globals.WAITING) {
-                                /* update the key to point at a pid */
-                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, &quot;Found waiting slot for %s\n&quot;, uuid_str);
-                                switch_core_hash_delete(listener-&gt;fetch_reply_hash, uuid_str);
-                                switch_core_hash_insert(listener-&gt;fetch_reply_hash, uuid_str, nbuf);
-                                ei_x_encode_atom(rbuf, &quot;ok&quot;);
-                                return SWITCH_STATUS_SUCCESS;
</del><span class="cx">                         } else {
</span><span class="cx">                                 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, &quot;Found filled slot for %s\n&quot;, uuid_str);
</span><span class="cx">                                 ei_x_encode_tuple_header(rbuf, 2);
</span><span class="lines">@@ -200,14 +220,14 @@
</span><span class="cx">                                 ei_x_encode_atom(rbuf, &quot;duplicate_response&quot;);
</span><span class="cx">                         }
</span><span class="cx">                 } else {
</span><del>-                        /* nothin in the hash */
</del><ins>+                        /* nothing in the hash */
+                        switch_mutex_unlock(globals.fetch_reply_mutex);
</ins><span class="cx">                         switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, &quot;Empty slot for %s\n&quot;, uuid_str);
</span><span class="cx">                         ei_x_encode_tuple_header(rbuf, 2);
</span><span class="cx">                         ei_x_encode_atom(rbuf, &quot;error&quot;);
</span><span class="cx">                         ei_x_encode_atom(rbuf, &quot;invalid_uuid&quot;);
</span><span class="cx">                 }
</span><span class="cx"> 
</span><del>-                /*switch_core_hash_insert(listener-&gt;fetch_reply_hash, uuid_str, nbuf); */
</del><span class="cx">                 switch_safe_free(nbuf-&gt;buff);
</span><span class="cx">                 switch_safe_free(nbuf);
</span><span class="cx">         }
</span></span></pre></div>
<a id="freeswitchtrunksrcmodevent_handlersmod_erlang_eventmod_erlang_eventc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c (16696 => 16697)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c        2010-02-18 20:22:32 UTC (rev 16696)
+++ freeswitch/trunk/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c        2010-02-18 21:55:46 UTC (rev 16697)
</span><span class="lines">@@ -41,6 +41,8 @@
</span><span class="cx"> SWITCH_MODULE_RUNTIME_FUNCTION(mod_erlang_event_runtime);
</span><span class="cx"> SWITCH_MODULE_DEFINITION(mod_erlang_event, mod_erlang_event_load, mod_erlang_event_shutdown, mod_erlang_event_runtime);
</span><span class="cx"> 
</span><ins>+static switch_memory_pool_t *module_pool = NULL;
+
</ins><span class="cx"> static void remove_listener(listener_t *listener);
</span><span class="cx"> static switch_status_t state_handler(switch_core_session_t *session);
</span><span class="cx"> 
</span><span class="lines">@@ -377,7 +379,7 @@
</span><span class="cx">         char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
</span><span class="cx">         int type, size;
</span><span class="cx">         int i = 0;
</span><del>-        void *p = NULL;
</del><ins>+        fetch_reply_t *p = NULL;
</ins><span class="cx">         char *xmlstr;
</span><span class="cx">         struct erlang_binding *ptr;
</span><span class="cx">         switch_uuid_t uuid;
</span><span class="lines">@@ -391,74 +393,89 @@
</span><span class="cx"> 
</span><span class="cx">         section = switch_xml_parse_section_string((char *) sectionstr);
</span><span class="cx"> 
</span><del>-        for (ptr = bindings.head; ptr &amp;&amp; ptr-&gt;section != section; ptr = ptr-&gt;next);        /* just get the first match */
</del><ins>+        switch_uuid_get(&amp;uuid);
+        switch_uuid_format(uuid_str, &amp;uuid);
</ins><span class="cx"> 
</span><del>-        if (!ptr) {
-                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, &quot;no binding for %s\n&quot;, sectionstr);
-                return NULL;
-        }
</del><ins>+        for (ptr = bindings.head; ptr; ptr = ptr-&gt;next) {
+                if (ptr-&gt;section != section)
+                        continue;
</ins><span class="cx"> 
</span><del>-        if (!ptr-&gt;listener) {
-                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, &quot;NULL pointer binding!\n&quot;);
-                return NULL;                        /* our pointer is trash */
-        }
</del><ins>+                if (!ptr-&gt;listener) {
+                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, &quot;NULL pointer binding!\n&quot;);
+                        goto cleanup; /* our pointer is trash */
+                }
</ins><span class="cx"> 
</span><del>-        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, &quot;binding for %s in section %s with key %s and value %s requested from node %s\n&quot;, tag_name,
-                                          sectionstr, key_name, key_value, ptr-&gt;process.pid.node);
</del><ins>+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, &quot;binding for %s in section %s with key %s and value %s requested from node %s\n&quot;, tag_name, sectionstr, key_name, key_value, ptr-&gt;process.pid.node);
</ins><span class="cx"> 
</span><del>-        switch_uuid_get(&amp;uuid);
-        switch_uuid_format(uuid_str, &amp;uuid);
</del><ins>+                ei_x_encode_tuple_header(&amp;buf, 7);
+                ei_x_encode_atom(&amp;buf, &quot;fetch&quot;);
+                ei_x_encode_atom(&amp;buf, sectionstr);
+                _ei_x_encode_string(&amp;buf, tag_name ? tag_name : &quot;undefined&quot;);
+                _ei_x_encode_string(&amp;buf, key_name ? key_name : &quot;undefined&quot;);
+                _ei_x_encode_string(&amp;buf, key_value ? key_value : &quot;undefined&quot;);
+                _ei_x_encode_string(&amp;buf, uuid_str);
+                if (params) {
+                        ei_encode_switch_event_headers(&amp;buf, params);
+                } else {
+                        ei_x_encode_empty_list(&amp;buf);
+                }
</ins><span class="cx"> 
</span><del>-        /*switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, &quot;Request-ID&quot;, uuid_str); */
</del><ins>+                if (!p) {
+                        /* Create a new fetch object. */
+                        p = malloc(sizeof(*p));
+                        switch_thread_cond_create(&amp;p-&gt;ready_or_found, module_pool);
+                        p-&gt;usecount = 1;
+                        p-&gt;state = reply_not_ready;
+                        p-&gt;reply = NULL;
+                        switch_core_hash_insert_locked(globals.fetch_reply_hash, uuid_str, p, globals.fetch_reply_mutex);
+                }
+                /* We don't need to lock here because everybody is waiting
+                   on our condition before the action starts. */
+                p-&gt;usecount ++;
</ins><span class="cx"> 
</span><del>-        ei_x_encode_tuple_header(&amp;buf, 7);
-        ei_x_encode_atom(&amp;buf, &quot;fetch&quot;);
-        ei_x_encode_atom(&amp;buf, sectionstr);
-        _ei_x_encode_string(&amp;buf, tag_name ? tag_name : &quot;undefined&quot;);
-        _ei_x_encode_string(&amp;buf, key_name ? key_name : &quot;undefined&quot;);
-        _ei_x_encode_string(&amp;buf, key_value ? key_value : &quot;undefined&quot;);
-        _ei_x_encode_string(&amp;buf, uuid_str);
-        if (params) {
-                ei_encode_switch_event_headers(&amp;buf, params);
-        } else {
-                ei_x_encode_empty_list(&amp;buf);
</del><ins>+                switch_mutex_lock(ptr-&gt;listener-&gt;sock_mutex);
+                ei_sendto(ptr-&gt;listener-&gt;ec, ptr-&gt;listener-&gt;sockfd, &amp;ptr-&gt;process, &amp;buf);
+                switch_mutex_unlock(ptr-&gt;listener-&gt;sock_mutex);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        switch_core_hash_insert(ptr-&gt;listener-&gt;fetch_reply_hash, uuid_str, &amp;globals.WAITING);
</del><ins>+        if (!p) {
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, &quot;no binding for %s\n&quot;, sectionstr);
+                goto cleanup;
+        }
</ins><span class="cx"> 
</span><del>-        switch_mutex_lock(ptr-&gt;listener-&gt;sock_mutex);
-        ei_sendto(ptr-&gt;listener-&gt;ec, ptr-&gt;listener-&gt;sockfd, &amp;ptr-&gt;process, &amp;buf);
-        switch_mutex_unlock(ptr-&gt;listener-&gt;sock_mutex);
-
-        while (!(p = switch_core_hash_find(ptr-&gt;listener-&gt;fetch_reply_hash, uuid_str)) || p == &amp;globals.WAITING) {
-                if (i &gt; 50) {                        /* half a second timeout */
-                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, &quot;Timed out when waiting for XML fetch response\n&quot;);
-                        switch_core_hash_insert(ptr-&gt;listener-&gt;fetch_reply_hash, uuid_str, &amp;globals.TIMEOUT);        /* TODO lock this? */
-                        return NULL;
-                }
-                i++;
-                switch_yield(10000);        /* 10ms */
</del><ins>+        /* Tell the threads to be ready, and wait five seconds for a reply. */
+        switch_mutex_lock(globals.fetch_reply_mutex);
+        p-&gt;state = reply_waiting;
+        switch_thread_cond_broadcast(p-&gt;ready_or_found);
+        switch_thread_cond_timedwait(p-&gt;ready_or_found,
+                        globals.fetch_reply_mutex, 5000000);
+        if (!p-&gt;reply) {
+                p-&gt;state = reply_timeout;
+                switch_mutex_unlock(globals.fetch_reply_mutex);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, &quot;Timed out when waiting for XML fetch response\n&quot;);
+                goto cleanup;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        rep = (ei_x_buff *) p;
</del><ins>+        rep = p-&gt;reply;
+        switch_mutex_unlock(globals.fetch_reply_mutex);
</ins><span class="cx"> 
</span><span class="cx">         ei_get_type(rep-&gt;buff, &amp;rep-&gt;index, &amp;type, &amp;size);
</span><span class="cx"> 
</span><span class="cx">         if (type != ERL_STRING_EXT &amp;&amp; type != ERL_BINARY_EXT) {        /* XXX no unicode or character codes &gt; 255 */
</span><span class="cx">                 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, &quot;XML fetch response contained non ASCII characters? (was type %d of size %d)\n&quot;, type,
</span><span class="cx">                                                   size);
</span><del>-                return NULL;
</del><ins>+                goto cleanup;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">         if (!(xmlstr = malloc(size + 1))) {
</span><span class="cx">                 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, &quot;Memory Error\n&quot;);
</span><del>-                return NULL;
</del><ins>+                goto cleanup;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         ei_decode_string_or_binary(rep-&gt;buff, &amp;rep-&gt;index, size, xmlstr);
</span><span class="cx"> 
</span><del>-        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, &quot;got data %s after %d milliseconds!\n&quot;, xmlstr, i * 10);
</del><ins>+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, &quot;got data %s after %d milliseconds from %s!\n&quot;, xmlstr, i * 10, p-&gt;winner);
</ins><span class="cx"> 
</span><span class="cx">         if (zstr(xmlstr)) {
</span><span class="cx">                 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, &quot;No Result\n&quot;);
</span><span class="lines">@@ -469,14 +486,31 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         /* cleanup */
</span><del>-        switch_core_hash_delete(ptr-&gt;listener-&gt;fetch_reply_hash, uuid_str);
-        switch_safe_free(rep-&gt;buff);
-        switch_safe_free(rep);
</del><ins>+ cleanup:
+        if (p) {
+                switch_mutex_lock(globals.fetch_reply_mutex);
+                put_reply_unlock(p, uuid_str);
+        }
</ins><span class="cx"> 
</span><span class="cx">         return xml;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+void put_reply_unlock(fetch_reply_t *p, char *uuid_str)
+{
+        if (-- p-&gt;usecount == 0) {
+                switch_core_hash_delete(globals.fetch_reply_hash, uuid_str);
+                switch_thread_cond_destroy(p-&gt;ready_or_found);
+                if (p-&gt;reply) {
+                        switch_safe_free(p-&gt;reply-&gt;buff);
+                        switch_safe_free(p-&gt;reply);
+                }
+                switch_safe_free(p);
+        }
+        switch_mutex_unlock(globals.fetch_reply_mutex);
+}
+
+
</ins><span class="cx"> static switch_status_t notify_new_session(listener_t *listener, session_elem_t *session_element)
</span><span class="cx"> {
</span><span class="cx">         int result;
</span><span class="lines">@@ -921,8 +955,6 @@
</span><span class="cx">         prefs.threads++;
</span><span class="cx">         switch_mutex_unlock(globals.listener_mutex);
</span><span class="cx"> 
</span><del>-        switch_core_hash_init(&amp;listener-&gt;fetch_reply_hash, listener-&gt;pool);
-
</del><span class="cx">         switch_assert(listener != NULL);
</span><span class="cx"> 
</span><span class="cx">         if (check_inbound_acl(listener)) {
</span><span class="lines">@@ -1548,9 +1580,13 @@
</span><span class="cx">         switch_application_interface_t *app_interface;
</span><span class="cx">         switch_api_interface_t *api_interface;
</span><span class="cx"> 
</span><ins>+        module_pool = pool;
+
</ins><span class="cx">         memset(&amp;prefs, 0, sizeof(prefs));
</span><span class="cx"> 
</span><span class="cx">         switch_mutex_init(&amp;globals.listener_mutex, SWITCH_MUTEX_NESTED, pool);
</span><ins>+        switch_mutex_init(&amp;globals.fetch_reply_mutex, SWITCH_MUTEX_DEFAULT, pool);
+        switch_core_hash_init(&amp;globals.fetch_reply_hash, pool);
</ins><span class="cx"> 
</span><span class="cx">         /* intialize the unique reference stuff */
</span><span class="cx">         switch_mutex_init(&amp;globals.ref_mutex, SWITCH_MUTEX_NESTED, pool);
</span></span></pre></div>
<a id="freeswitchtrunksrcmodevent_handlersmod_erlang_eventmod_erlang_eventh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h (16696 => 16697)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h        2010-02-18 20:22:32 UTC (rev 16696)
+++ freeswitch/trunk/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h        2010-02-18 21:55:46 UTC (rev 16697)
</span><span class="lines">@@ -103,7 +103,6 @@
</span><span class="cx">         switch_log_level_t level;
</span><span class="cx">         uint8_t event_list[SWITCH_EVENT_ALL + 1];
</span><span class="cx">         switch_hash_t *event_hash;
</span><del>-        switch_hash_t *fetch_reply_hash;
</del><span class="cx">         switch_hash_t *spawn_pid_hash;
</span><span class="cx">         switch_thread_rwlock_t *rwlock;
</span><span class="cx">         switch_mutex_t *session_mutex;
</span><span class="lines">@@ -140,15 +139,27 @@
</span><span class="cx"> struct globals_struct {
</span><span class="cx">         switch_mutex_t *listener_mutex;
</span><span class="cx">         switch_event_node_t *node;
</span><ins>+        switch_mutex_t *ref_mutex;
+        switch_mutex_t *fetch_reply_mutex;
+        switch_hash_t *fetch_reply_hash;
</ins><span class="cx">         unsigned int reference0;
</span><span class="cx">         unsigned int reference1;
</span><span class="cx">         unsigned int reference2;
</span><span class="cx">         char TIMEOUT;                                /* marker for a timed out request */
</span><span class="cx">         char WAITING;                                /* marker for a request waiting for a response */
</span><del>-        switch_mutex_t *ref_mutex;
</del><span class="cx"> };
</span><span class="cx"> typedef struct globals_struct globals_t;
</span><span class="cx"> 
</span><ins>+struct fetch_reply_struct
+{
+        switch_thread_cond_t *ready_or_found;
+        int usecount;
+        enum { reply_not_ready, reply_waiting, reply_found, reply_timeout } state;
+        ei_x_buff *reply;
+        char winner[MAXNODELEN + 1];
+};
+typedef struct fetch_reply_struct fetch_reply_t;
+
</ins><span class="cx"> struct listen_list_struct {
</span><span class="cx"> #ifdef WIN32
</span><span class="cx">         SOCKET sockfd;
</span><span class="lines">@@ -236,6 +247,7 @@
</span><span class="cx"> session_elem_t *attach_call_to_registered_process(listener_t *listener, char *reg_name, switch_core_session_t *session);
</span><span class="cx"> session_elem_t *attach_call_to_pid(listener_t *listener, erlang_pid * pid, switch_core_session_t *session);
</span><span class="cx"> session_elem_t *attach_call_to_spawned_process(listener_t *listener, char *module, char *function, switch_core_session_t *session);
</span><ins>+void put_reply_unlock(fetch_reply_t *p, char *uuid_str);
</ins><span class="cx"> 
</span><span class="cx"> /* For Emacs:
</span><span class="cx">  * Local Variables:
</span></span></pre>
</div>
</div>
<div id="footer">See you at ClueCon</div>

</body>
</html>