5353#include " boost/bind/bind.hpp"
5454
5555#include < thread>
56+ #include < map>
57+ #include < utility>
58+ #include < optional>
5659
5760#include < fcntl.h>
5861#ifndef _MSC_VER
@@ -70,6 +73,14 @@ IE_CORE_DEFINERUNTIMETYPED( DisplayDriverServer );
7073namespace
7174{
7275
76+ struct MergeDriverInfo
77+ {
78+ DisplayDriverPtr mergeDriver = nullptr ;
79+ int mergeCount = 0 ;
80+ };
81+
82+ using MergeMap = std::map<int , MergeDriverInfo>;
83+
7384/* Set the FD_CLOEXEC flag for the given socket descriptor, so that it will not exist on child processes.*/
7485static void fixSocketFlags ( int socketDesc )
7586{
@@ -95,7 +106,7 @@ class DisplayDriverServer::Session : public RefCounted
95106{
96107 public:
97108
98- Session ( boost::asio::io_service& io_service );
109+ Session ( boost::asio::io_service& io_service, MergeMap& mergeMap );
99110 ~Session () override ;
100111
101112 boost::asio::ip::tcp::socket& socket ();
@@ -114,6 +125,8 @@ class DisplayDriverServer::Session : public RefCounted
114125 DisplayDriverPtr m_displayDriver;
115126 DisplayDriverServerHeader m_header;
116127 CharVectorDataPtr m_buffer;
128+ MergeMap& m_mergeMap;
129+ std::optional<int > m_mergeId;
117130};
118131
119132class DisplayDriverServer ::PrivateData : public RefCounted
@@ -125,6 +138,7 @@ class DisplayDriverServer::PrivateData : public RefCounted
125138 boost::asio::io_service m_service;
126139 boost::asio::ip::tcp::acceptor m_acceptor;
127140 std::thread m_thread;
141+ MergeMap m_mergeMap;
128142
129143 PrivateData ( DisplayDriverServer::Port portNumber ) :
130144 m_service (),
@@ -196,7 +210,7 @@ DisplayDriverServer::DisplayDriverServer( DisplayDriverServer::Port portNumber )
196210{
197211 m_data = new DisplayDriverServer::PrivateData ( portNumber );
198212
199- DisplayDriverServer::SessionPtr newSession ( new DisplayDriverServer::Session ( m_data->m_service ) );
213+ DisplayDriverServer::SessionPtr newSession ( new DisplayDriverServer::Session ( m_data->m_service , m_data-> m_mergeMap ) );
200214 m_data->m_acceptor .async_accept ( newSession->socket (),
201215 boost::bind ( &DisplayDriverServer::handleAccept, this , newSession,
202216 boost::asio::placeholders::error));
@@ -280,7 +294,7 @@ void DisplayDriverServer::handleAccept( DisplayDriverServer::SessionPtr session,
280294{
281295 if (!error)
282296 {
283- DisplayDriverServer::SessionPtr newSession ( new DisplayDriverServer::Session ( m_data->m_service ) );
297+ DisplayDriverServer::SessionPtr newSession ( new DisplayDriverServer::Session ( m_data->m_service , m_data-> m_mergeMap ) );
284298 m_data->m_acceptor .async_accept ( newSession->socket (),
285299 boost::bind ( &DisplayDriverServer::handleAccept, this , newSession,
286300 boost::asio::placeholders::error));
@@ -292,8 +306,8 @@ void DisplayDriverServer::handleAccept( DisplayDriverServer::SessionPtr session,
292306 * DisplayDriverServer::Session functions
293307 */
294308
295- DisplayDriverServer::Session::Session ( boost::asio::io_service& io_service ) :
296- m_socket( io_service ), m_displayDriver(nullptr ), m_buffer( new CharVectorData( ) )
309+ DisplayDriverServer::Session::Session ( boost::asio::io_service& io_service, MergeMap& mergeMap ) :
310+ m_socket( io_service ), m_displayDriver(nullptr ), m_buffer( new CharVectorData( ) ), m_mergeMap( mergeMap )
297311{
298312}
299313
@@ -363,7 +377,19 @@ void DisplayDriverServer::Session::handleReadHeader( const boost::system::error_
363377 {
364378 try
365379 {
366- m_displayDriver->imageClose ();
380+ if ( !m_mergeId.has_value () )
381+ {
382+ m_displayDriver->imageClose ();
383+ }
384+ else
385+ {
386+ auto &m = m_mergeMap.at (m_mergeId.value ()); // Error out if not found
387+ if ( --m.mergeCount <= 0 )
388+ {
389+ m_mergeMap.erase (m_mergeId.value ());
390+ m_displayDriver->imageClose ();
391+ }
392+ }
367393 }
368394 catch ( std::exception &e )
369395 {
@@ -424,8 +450,31 @@ void DisplayDriverServer::Session::handleReadOpenParameters( const boost::system
424450 const StringData *displayType = parameters->member <StringData>( " remoteDisplayType" , true /* throw if missing */ );
425451
426452 // create a displayDriver using the factory function.
427- m_displayDriver = DisplayDriver::create ( displayType->readable (), displayWindow->readable (), dataWindow->readable (), channelNames->readable (), parameters );
453+ if ( !parameters->member <IntData>( " displayDriverServer:mergeId" , false ) )
454+ {
455+ m_displayDriver = DisplayDriver::create ( displayType->readable (), displayWindow->readable (), dataWindow->readable (), channelNames->readable (), parameters );
456+ }
457+ else
458+ {
459+ m_mergeId = parameters->member <IntData>( " displayDriverServer:mergeId" , false /* throw if missing */ )->readable ();
428460
461+ // Check if merge ID in map, if not then create display driver and session count pair with merge ID.
462+ auto &m = m_mergeMap[m_mergeId.value ()];
463+ if ( !m.mergeDriver )
464+ {
465+ const IntData *sessionClientsData = parameters->member <IntData>( " displayDriverServer:mergeClients" , true /* throw if missing */ );
466+ m.mergeDriver = DisplayDriver::create (
467+ displayType->readable (),
468+ displayWindow->readable (),
469+ displayWindow->readable (), // For merge we want dataWindow = displayWindow
470+ channelNames->readable (),
471+ parameters
472+ );
473+ m.mergeCount = sessionClientsData->readable ();
474+ }
475+ // Merge ID is now in map, so load the display driver.
476+ m_displayDriver = m.mergeDriver ;
477+ }
429478 scanLineOrder = m_displayDriver->scanLineOrderOnly ();
430479 acceptsRepeatedData = m_displayDriver->acceptsRepeatedData ();
431480 }
0 commit comments