@@ -104,6 +104,64 @@ namespace
104104
105105namespace eCAL
106106{
107+ void CPublisherImpl::SSendLayerConnectionCounters::Increment (TransportLayer::eType layer_)
108+ {
109+ switch (layer_)
110+ {
111+ case TransportLayer::eType::udp_mc:
112+ udp.fetch_add (1 , std::memory_order_relaxed);
113+ break ;
114+ case TransportLayer::eType::shm:
115+ shm.fetch_add (1 , std::memory_order_relaxed);
116+ break ;
117+ case TransportLayer::eType::tcp:
118+ tcp.fetch_add (1 , std::memory_order_relaxed);
119+ break ;
120+ default :
121+ break ;
122+ }
123+ }
124+
125+ void CPublisherImpl::SSendLayerConnectionCounters::Decrement (TransportLayer::eType layer_)
126+ {
127+ switch (layer_)
128+ {
129+ case TransportLayer::eType::udp_mc:
130+ udp.fetch_sub (1 , std::memory_order_relaxed);
131+ break ;
132+ case TransportLayer::eType::shm:
133+ shm.fetch_sub (1 , std::memory_order_relaxed);
134+ break ;
135+ case TransportLayer::eType::tcp:
136+ tcp.fetch_sub (1 , std::memory_order_relaxed);
137+ break ;
138+ default :
139+ break ;
140+ }
141+ }
142+
143+ void CPublisherImpl::SSendLayerConnectionCounters::Reset ()
144+ {
145+ udp.store (0 , std::memory_order_relaxed);
146+ shm.store (0 , std::memory_order_relaxed);
147+ tcp.store (0 , std::memory_order_relaxed);
148+ }
149+
150+ bool CPublisherImpl::SSendLayerConnectionCounters::UdpEnabled () const
151+ {
152+ return (udp.load (std::memory_order_relaxed) > 0 );
153+ }
154+
155+ bool CPublisherImpl::SSendLayerConnectionCounters::ShmEnabled () const
156+ {
157+ return (shm.load (std::memory_order_relaxed) > 0 );
158+ }
159+
160+ bool CPublisherImpl::SSendLayerConnectionCounters::TcpEnabled () const
161+ {
162+ return (tcp.load (std::memory_order_relaxed) > 0 );
163+ }
164+
107165 CPublisherImpl::CPublisherImpl (const SDataTypeInformation& topic_info_, const eCAL::eCALWriter::SAttributes& attr_, SPublisherGlobalContext global_context_)
108166 : m_publisher_id(eCAL::Util::GenerateUniqueEntityId())
109167 , m_topic_info(topic_info_)
@@ -141,6 +199,7 @@ namespace eCAL
141199 {
142200 const std::lock_guard<std::mutex> lock (m_connection_map_mutex);
143201 m_connection_map.clear ();
202+ m_connection_count.store (0 , std::memory_order_relaxed);
144203 }
145204
146205 // mark as no more created
@@ -154,6 +213,15 @@ namespace eCAL
154213 {
155214 // get payload buffer size (one time, to avoid multiple computations)
156215 const size_t payload_buf_size (payload_.GetSize ());
216+ #if ECAL_CORE_TRANSPORT_SHM
217+ const bool shm_send_enabled = m_writer_shm && m_send_layer_connection_counters.ShmEnabled ();
218+ #endif
219+ #if ECAL_CORE_TRANSPORT_UDP
220+ const bool udp_send_enabled = m_writer_udp && m_send_layer_connection_counters.UdpEnabled ();
221+ #endif
222+ #if ECAL_CORE_TRANSPORT_TCP
223+ const bool tcp_send_enabled = m_writer_tcp && m_send_layer_connection_counters.TcpEnabled ();
224+ #endif
157225
158226 // are we allowed to perform zero copy writing?
159227 bool allow_zero_copy (false );
@@ -162,11 +230,11 @@ namespace eCAL
162230#endif
163231#if ECAL_CORE_TRANSPORT_UDP
164232 // udp is active -> no zero copy
165- allow_zero_copy &= !m_writer_udp ;
233+ allow_zero_copy &= !udp_send_enabled ;
166234#endif
167235#if ECAL_CORE_TRANSPORT_TCP
168236 // tcp is active -> no zero copy
169- allow_zero_copy &= !m_writer_tcp ;
237+ allow_zero_copy &= !tcp_send_enabled ;
170238#endif
171239
172240 // create a payload copy for all layer
@@ -186,7 +254,7 @@ namespace eCAL
186254 // SHM
187255 // //////////////////////////////////////////////////////////////////////////
188256#if ECAL_CORE_TRANSPORT_SHM
189- if (m_writer_shm )
257+ if (shm_send_enabled )
190258 {
191259#ifndef NDEBUG
192260 eCAL::Logging::Log (Logging::log_level_debug3, m_attributes.topic_name + " ::CPublisherImpl::Write::SHM" );
@@ -249,7 +317,7 @@ namespace eCAL
249317 // UDP (MC)
250318 // //////////////////////////////////////////////////////////////////////////
251319#if ECAL_CORE_TRANSPORT_UDP
252- if (m_writer_udp )
320+ if (udp_send_enabled )
253321 {
254322#ifndef NDEBUG
255323 eCAL::Logging::Log (Logging::log_level_debug3, m_attributes.topic_name + " ::CPublisherImpl::Write::udp" );
@@ -298,7 +366,7 @@ namespace eCAL
298366 // TCP
299367 // //////////////////////////////////////////////////////////////////////////
300368#if ECAL_CORE_TRANSPORT_TCP
301- if (m_writer_tcp )
369+ if (tcp_send_enabled )
302370 {
303371#ifndef NDEBUG
304372 eCAL::Logging::Log (Logging::log_level_debug3, m_attributes.topic_name + " ::CPublisherImpl::Send::TCP" );
@@ -406,8 +474,8 @@ namespace eCAL
406474#endif
407475
408476 // determine if we need to start a transport layer
409- const TransportLayer::eType layer2activate = DetermineTransportLayer2Start (pub_layers, sub_layers, m_attributes.host_name == subscription_info_.host_name );
410- switch (layer2activate )
477+ const TransportLayer::eType transport_layer_for_subscription = DetermineTransportLayer (pub_layers, sub_layers, m_attributes.host_name == subscription_info_.host_name );
478+ switch (transport_layer_for_subscription )
411479 {
412480 case TransportLayer::eType::udp_mc:
413481 StartUdpLayer ();
@@ -445,27 +513,30 @@ namespace eCAL
445513
446514 if (subscription_info_iter == m_connection_map.end ())
447515 {
448- // add subscriber to connection map, connection state false
449- m_connection_map[subscription_info_] = SConnection{ data_type_info_, sub_layer_states_, false } ;
516+ m_connection_map[subscription_info_] = SConnection{ data_type_info_, sub_layer_states_, transport_layer_for_subscription, eConnectionState::pending };
517+ m_send_layer_connection_counters. Increment (transport_layer_for_subscription) ;
450518 }
451519 else
452520 {
453- // existing connection, we got the second update now
454521 auto & connection = subscription_info_iter->second ;
455522
456- // if this connection was inactive before
457- // activate it now and flag a new connection finally
458- if (!connection.state )
523+ #ifndef NDEBUG
524+ if (connection.selected_layer != transport_layer_for_subscription)
525+ {
526+ eCAL::Logging::Log (Logging::log_level_warning, m_attributes.topic_name + " ::CPublisherImpl::ApplySubscriberRegistration - selected transport layer changed unexpectedly for connection" );
527+ }
528+ #endif
529+
530+ if (connection.state == eConnectionState::pending)
459531 {
460532 is_new_connection = true ;
533+ m_connection_count.fetch_add (1 , std::memory_order_relaxed);
534+ connection.state = eConnectionState::established;
461535 }
462536
463- // update the data type, the layer states and set the state active
464- connection = SConnection{ data_type_info_, sub_layer_states_, true } ;
537+ connection. data_type_info = data_type_info_;
538+ connection. layer_states = sub_layer_states_;
465539 }
466-
467- // update connection count
468- m_connection_count = GetConnectionCount ();
469540 }
470541
471542
@@ -497,11 +568,24 @@ namespace eCAL
497568 {
498569 const std::lock_guard<std::mutex> lock (m_connection_map_mutex);
499570
500- // remove key from connection map
501- m_connection_map.erase (subscription_info_);
571+ auto subscription_info_iter = m_connection_map.find (subscription_info_);
572+ if (subscription_info_iter != m_connection_map.end ())
573+ {
574+ auto & connection = subscription_info_iter->second ;
575+ if (connection.state == eConnectionState::established)
576+ {
577+ m_connection_count.fetch_sub (1 , std::memory_order_relaxed);
578+ }
502579
503- // update connection count
504- m_connection_count = GetConnectionCount ();
580+ if (connection.state != eConnectionState::closed)
581+ {
582+ m_send_layer_connection_counters.Decrement (connection.selected_layer );
583+ connection.state = eConnectionState::closed;
584+ }
585+
586+ // remove key from connection map
587+ m_connection_map.erase (subscription_info_iter);
588+ }
505589 }
506590
507591 // fire disconnect event
@@ -702,20 +786,6 @@ namespace eCAL
702786 FireEvent (ePublisherEvent::disconnected, subscription_info_, data_type_info_);
703787 }
704788
705- size_t CPublisherImpl::GetConnectionCount ()
706- {
707- // no need to lock map here for now, map locked by caller
708- size_t count (0 );
709- for (const auto & sub : m_connection_map)
710- {
711- if (sub.second .state )
712- {
713- count++;
714- }
715- }
716- return count;
717- }
718-
719789 bool CPublisherImpl::StartUdpLayer ()
720790 {
721791#if ECAL_CORE_TRANSPORT_UDP
@@ -819,6 +889,8 @@ namespace eCAL
819889 // destroy writer
820890 m_writer_tcp.reset ();
821891#endif
892+
893+ m_send_layer_connection_counters.Reset ();
822894 }
823895
824896 size_t CPublisherImpl::PrepareWrite (long long id_, size_t len_)
@@ -840,7 +912,7 @@ namespace eCAL
840912 return snd_hash;
841913 }
842914
843- TransportLayer::eType CPublisherImpl::DetermineTransportLayer2Start (const std::vector<eTLayerType>& enabled_pub_layer_, const std::vector<eTLayerType>& enabled_sub_layer_, bool same_host_)
915+ TransportLayer::eType CPublisherImpl::DetermineTransportLayer (const std::vector<eTLayerType>& enabled_pub_layer_, const std::vector<eTLayerType>& enabled_sub_layer_, bool same_host_)
844916 {
845917 // determine the priority list to use
846918 const Publisher::Configuration::LayerPriorityVector& layer_priority_vector = same_host_ ? m_attributes.layer_priority_local : m_attributes.layer_priority_remote ;
0 commit comments