Change-Id: Ia02b511bfc33e101b2eccbed57cc71fe67d6a0b6
-NetworkPerformanceClient::NetworkPerformanceClient( SocketInterface *socket,
+NetworkPerformanceClient::NetworkPerformanceClient( pthread_t* thread,
+ SocketInterface *socket,
unsigned int clientId,
TriggerEventFactoryInterface& triggerEventFactory,
ClientSendDataInterface& sendDataInterface,
SocketFactoryInterface& socketFactory )
unsigned int clientId,
TriggerEventFactoryInterface& triggerEventFactory,
ClientSendDataInterface& sendDataInterface,
SocketFactoryInterface& socketFactory )
+: mThread( thread ),
+ mSocket( socket ),
mMarkerBitmask( PerformanceMarker::FILTERING_DISABLED ),
mTriggerEventFactory( triggerEventFactory ),
mSendDataInterface( sendDataInterface ),
mMarkerBitmask( PerformanceMarker::FILTERING_DISABLED ),
mTriggerEventFactory( triggerEventFactory ),
mSendDataInterface( sendDataInterface ),
+pthread_t* NetworkPerformanceClient::GetThread()
+{
+ return mThread;
+}
void NetworkPerformanceClient::ProcessCommand( char* buffer, unsigned int bufferSizeInBytes )
{
void NetworkPerformanceClient::ProcessCommand( char* buffer, unsigned int bufferSizeInBytes )
{
+// EXTERNAL INCLUDES
+#include <pthread.h>
+
// INTERNAL INCLUDES
#include <base/performance-logging/performance-marker.h>
#include <trigger-event-factory-interface.h>
#include <base/performance-logging/networking/client-send-data-interface.h>
#include <base/interfaces/socket-factory-interface.h>
// INTERNAL INCLUDES
#include <base/performance-logging/performance-marker.h>
#include <trigger-event-factory-interface.h>
#include <base/performance-logging/networking/client-send-data-interface.h>
#include <base/interfaces/socket-factory-interface.h>
-namespace boost
-{
-class thread;
-}
+ * @param thread thread pointer
* @param socket socket interface
* @param clientId unique client id
* @param triggerEventFactory used to create trigger events
* @param sendDataInterface used to send data to the socket from main thread
* @param SocketFactoryInterface used to delete the socket when the client is destroyed
*/
* @param socket socket interface
* @param clientId unique client id
* @param triggerEventFactory used to create trigger events
* @param sendDataInterface used to send data to the socket from main thread
* @param SocketFactoryInterface used to delete the socket when the client is destroyed
*/
- NetworkPerformanceClient( SocketInterface *socket,
+ NetworkPerformanceClient( pthread_t* thread,
+ SocketInterface *socket,
unsigned int clientId,
TriggerEventFactoryInterface& triggerEventFactory,
ClientSendDataInterface& sendDataInterface,
unsigned int clientId,
TriggerEventFactoryInterface& triggerEventFactory,
ClientSendDataInterface& sendDataInterface,
+ /**
+ * @brief get the thread running the client
+ * @return thread pointer
+ */
+ pthread_t* GetThread();
+
+ pthread_t* mThread; ///< thread for the client
SocketInterface* mSocket; ///< socket interface
PerformanceMarker::MarkerFilter mMarkerBitmask; ///< What markers are currently filtered
TriggerEventFactoryInterface& mTriggerEventFactory; ///< Trigger event factory
SocketInterface* mSocket; ///< socket interface
PerformanceMarker::MarkerFilter mMarkerBitmask; ///< What markers are currently filtered
TriggerEventFactoryInterface& mTriggerEventFactory; ///< Trigger event factory
// CLASS HEADER
#include "network-performance-server.h"
// CLASS HEADER
#include "network-performance-server.h"
-// EXTERNAL INCLUDES
-#include <boost/thread.hpp>
// INTERNAL INCLUDES
#include <base/performance-logging/performance-marker.h>
// INTERNAL INCLUDES
#include <base/performance-logging/performance-marker.h>
const unsigned int CONNECTION_BACKLOG = 2; ///< maximum length of the queue of pending connections.
const unsigned int SOCKET_READ_BUFFER_SIZE = 4096;
typedef Vector< NetworkPerformanceClient*> ClientList;
const unsigned int CONNECTION_BACKLOG = 2; ///< maximum length of the queue of pending connections.
const unsigned int SOCKET_READ_BUFFER_SIZE = 4096;
typedef Vector< NetworkPerformanceClient*> ClientList;
+
+/**
+ * POD passed to client thread on startup
+ */
+struct ClientThreadInfo
+{
+ NetworkPerformanceServer* server;
+ NetworkPerformanceClient* client;
+};
}
NetworkPerformanceServer::NetworkPerformanceServer( AdaptorInternalServices& adaptorServices,
}
NetworkPerformanceServer::NetworkPerformanceServer( AdaptorInternalServices& adaptorServices,
: mTriggerEventFactory( adaptorServices.GetTriggerEventFactoryInterface() ),
mSocketFactory( adaptorServices.GetSocketFactoryInterface() ),
mLogOptions( logOptions ),
: mTriggerEventFactory( adaptorServices.GetTriggerEventFactoryInterface() ),
mSocketFactory( adaptorServices.GetSocketFactoryInterface() ),
mLogOptions( logOptions ),
mListeningSocket( NULL ),
mClientUniqueId( 0 ),
mClientCount( 0 ),
mListeningSocket( NULL ),
mClientUniqueId( 0 ),
mClientCount( 0 ),
mListeningSocket->Listen( CONNECTION_BACKLOG );
// start a thread which will block waiting for new connections
mListeningSocket->Listen( CONNECTION_BACKLOG );
// start a thread which will block waiting for new connections
- mServerThread = new boost::thread(boost::bind(&NetworkPerformanceServer::ConnectionListener, this));
+ int error = pthread_create( &mServerThread, NULL, ConnectionListenerFunc, this );
+ DALI_ASSERT_ALWAYS( !error && "pthread create failed" );
Dali::Integration::Log::LogMessage(Integration::Log::DebugInfo, "~~~ NetworkPerformanceServer started on port %d ~~~ \n", SERVER_PORT + basePort);
Dali::Integration::Log::LogMessage(Integration::Log::DebugInfo, "~~~ NetworkPerformanceServer started on port %d ~~~ \n", SERVER_PORT + basePort);
mListeningSocket->ExitSelect();
// wait for the thread to exit.
mListeningSocket->ExitSelect();
// wait for the thread to exit.
+ void* exitValue;
+ pthread_join( mServerThread, &exitValue );
// close the socket
mListeningSocket->CloseSocket();
// close the socket
mListeningSocket->CloseSocket();
mSocketFactory.DestroySocket( mListeningSocket );
mSocketFactory.DestroySocket( mListeningSocket );
mListeningSocket = NULL;
// this will tell all client threads to quit
StopClients();
mListeningSocket = NULL;
// this will tell all client threads to quit
StopClients();
- // wait for all threads to exit and the client count to hit zero
- {
- boost::mutex::scoped_lock lock(mClientListMutex);
-
- while (mClientCount != 0)
- {
- mClientCountUpdated.wait(lock);
- }
- }
}
bool NetworkPerformanceServer::IsRunning() const
}
bool NetworkPerformanceServer::IsRunning() const
SocketInterface* clientSocket = mListeningSocket->Accept();
// new connection made, spawn a thread to handle it
SocketInterface* clientSocket = mListeningSocket->Accept();
// new connection made, spawn a thread to handle it
- NetworkPerformanceClient* client = AddClient( clientSocket );
- new boost::thread(boost::bind(&NetworkPerformanceServer::ClientThread, this, client));
+ pthread_t* clientThread = new pthread_t();
+
+ NetworkPerformanceClient* client = AddClient( clientSocket, clientThread );
+
+ ClientThreadInfo* info = new ClientThreadInfo;
+ info->client = client;
+ info->server = this;
+
+ int error = pthread_create( clientThread, NULL, ClientThreadFunc, info );
+ DALI_ASSERT_ALWAYS( !error && "pthread create failed" );
+
}
else // ret == SocketInterface::QUIT or SocketInterface::ERROR
{
}
else // ret == SocketInterface::QUIT or SocketInterface::ERROR
{
-NetworkPerformanceClient* NetworkPerformanceServer::AddClient( SocketInterface* clientSocket )
+void* NetworkPerformanceServer::ClientThreadFunc( void* data )
+{
+ ClientThreadInfo* info = static_cast<ClientThreadInfo*>( data );
+ info->server->ClientThread( info->client );
+ delete info;
+ return NULL;
+}
+
+NetworkPerformanceClient* NetworkPerformanceServer::AddClient( SocketInterface* clientSocket, pthread_t* clientThread )
{
// This function is only called from the listening thread
{
// This function is only called from the listening thread
- NetworkPerformanceClient* client= new NetworkPerformanceClient(clientSocket,
- mClientUniqueId++,
- mTriggerEventFactory,
- *this,
- mSocketFactory);
+ NetworkPerformanceClient* client= new NetworkPerformanceClient( clientThread,
+ clientSocket,
+ mClientUniqueId++,
+ mTriggerEventFactory,
+ *this,
+ mSocketFactory);
// protect the mClients list which can be accessed from multiple threads.
// protect the mClients list which can be accessed from multiple threads.
- boost::mutex::scoped_lock sharedDatalock( mClientListMutex );
+ Mutex::ScopedLock lock( mClientListMutex );
mClients.PushBack( client );
mClients.PushBack( client );
void NetworkPerformanceServer::DeleteClient( NetworkPerformanceClient* client )
{
// protect the mClients list while modifying
void NetworkPerformanceServer::DeleteClient( NetworkPerformanceClient* client )
{
// protect the mClients list while modifying
- boost::mutex::scoped_lock sharedDatalock( mClientListMutex );
+ Mutex::ScopedLock lock( mClientListMutex );
// remove from the list, and delete it
for( ClientList::Iterator iter = mClients.Begin(); iter != mClients.End() ; ++iter )
// remove from the list, and delete it
for( ClientList::Iterator iter = mClients.Begin(); iter != mClients.End() ; ++iter )
// if there server is shutting down, it waits for client count to hit zero
mClientCount--;
// if there server is shutting down, it waits for client count to hit zero
mClientCount--;
- // lets the server know the client count has been modified
- mClientCountUpdated.notify_one();
}
// prevent clients been added / deleted while transmiting data
}
// prevent clients been added / deleted while transmiting data
- boost::mutex::scoped_lock sharedDatalock( mClientListMutex );
+ Mutex::ScopedLock lock( mClientListMutex );
for( ClientList::Iterator iter = mClients.Begin(); iter != mClients.End() ; ++iter )
{
for( ClientList::Iterator iter = mClients.Begin(); iter != mClients.End() ; ++iter )
{
return;
}
// prevent clients been added / deleted while transmiting data
return;
}
// prevent clients been added / deleted while transmiting data
- boost::mutex::scoped_lock sharedDatalock( mClientListMutex );
+ Mutex::ScopedLock lock( mClientListMutex );
for( ClientList::Iterator iter = mClients.Begin(); iter != mClients.End() ; ++iter )
{
for( ClientList::Iterator iter = mClients.Begin(); iter != mClients.End() ; ++iter )
{
void NetworkPerformanceServer::StopClients()
{
// prevent clients been added / deleted while stopping all clients
void NetworkPerformanceServer::StopClients()
{
// prevent clients been added / deleted while stopping all clients
- boost::mutex::scoped_lock sharedDatalock( mClientListMutex );
+ Mutex::ScopedLock lock( mClientListMutex );
for( ClientList::Iterator iter = mClients.Begin(); iter != mClients.End() ; ++iter )
{
NetworkPerformanceClient* client = (*iter);
// stop the client from waiting for new commands, and exit from it's thread
client->ExitSelect();
for( ClientList::Iterator iter = mClients.Begin(); iter != mClients.End() ; ++iter )
{
NetworkPerformanceClient* client = (*iter);
// stop the client from waiting for new commands, and exit from it's thread
client->ExitSelect();
+
+ void* exitValue;
+ pthread_t* thread = client->GetThread();
+ pthread_join( *thread, &exitValue );
+ delete thread;
+
-#include <boost/thread/mutex.hpp>
-#include <boost/thread/condition_variable.hpp>
+#include <pthread.h>
+#include <dali/devel-api/common/mutex.h>
#include <dali/public-api/common/dali-vector.h>
// INTERNAL INCLUDES
#include <dali/public-api/common/dali-vector.h>
// INTERNAL INCLUDES
#include <base/performance-logging/networking/network-performance-client.h>
#include <base/interfaces/adaptor-internal-services.h>
#include <base/performance-logging/networking/network-performance-client.h>
#include <base/interfaces/adaptor-internal-services.h>
-
-namespace boost
-{
-class thread;
-}
virtual void SendData( const char* const data, unsigned int bufferSizeInBytes, unsigned int clientId );
private:
virtual void SendData( const char* const data, unsigned int bufferSizeInBytes, unsigned int clientId );
private:
+
+ /**
+ * Helper for the thread calling the entry function.
+ * @param[in] This A pointer to the current RenderThread object
+ */
+ static void* ConnectionListenerFunc( void* This )
+ {
+ ( static_cast<NetworkPerformanceServer*>( This ) )->ConnectionListener();
+ return NULL;
+ }
+
+ /**
+ * Helper for the thread calling the entry function.
+ * @param[in] This A pointer to the current RenderThread object
+ */
+ static void* ClientThreadFunc( void* data );
+
/**
* @brief Client thread function
* @param client network client object
/**
* @brief Client thread function
* @param client network client object
/**
* @brief Add a new client to the client list
* @param clientSocket client socket
/**
* @brief Add a new client to the client list
* @param clientSocket client socket
+ * @param clientThread client thread
- NetworkPerformanceClient* AddClient( SocketInterface* clientSocket );
+ NetworkPerformanceClient* AddClient( SocketInterface* clientSocket, pthread_t* clientThread );
/**
* @brief Delete a client from the client list
/**
* @brief Delete a client from the client list
SocketFactoryInterface& mSocketFactory; ///< used to create sockets
const EnvironmentOptions& mLogOptions; ///< log options
Dali::Vector< NetworkPerformanceClient* > mClients; ///< list of connected clients
SocketFactoryInterface& mSocketFactory; ///< used to create sockets
const EnvironmentOptions& mLogOptions; ///< log options
Dali::Vector< NetworkPerformanceClient* > mClients; ///< list of connected clients
- boost::thread* mServerThread; ///< thread that listens for new connections
+ pthread_t mServerThread; ///< thread that listens for new connections
SocketInterface* mListeningSocket; ///< socket used to listen for new connections
SocketInterface* mListeningSocket; ///< socket used to listen for new connections
- boost::mutex mClientListMutex; ///< mutex
- boost::condition_variable mClientCountUpdated; ///< used to say the client count has changed
+ Dali::Mutex mClientListMutex; ///< mutex
unsigned int mClientUniqueId; ///< increments for every client connection
unsigned int mClientUniqueId; ///< increments for every client connection
- unsigned int mClientCount; ///< client count
+ volatile unsigned int mClientCount; ///< client count
bool mLogFunctionInstalled; ///< whether the log function is installed
};
bool mLogFunctionInstalled; ///< whether the log function is installed
};
- // This is only called from main event thread, but may overlap with internal AddMarker calls
- // from other threads ( update, render etc).
- boost::mutex::scoped_lock sharedDatalock( mDataMutex );
-
// Get the time stamp
unsigned int seconds = 0;
unsigned int microseconds = 0;
// Get the time stamp
unsigned int seconds = 0;
unsigned int microseconds = 0;
// Add custom marker to statistics context manager
mStatContextManager.AddCustomMarker( marker, contextId );
// Add custom marker to statistics context manager
mStatContextManager.AddCustomMarker( marker, contextId );
}
void PerformanceServer::AddMarker( MarkerType markerType )
}
void PerformanceServer::AddMarker( MarkerType markerType )
- // AddMarker can be called from multiple threads, to avoid problems
- // with updating contexts and the kernel trace, lock here.
- boost::mutex::scoped_lock sharedDatalock( mDataMutex );
-
if( markerType == VSYNC )
{
// make sure log function is installed, note this will be called only from v-sync thread
if( markerType == VSYNC )
{
// make sure log function is installed, note this will be called only from v-sync thread
void PerformanceServer::LogMarker( const PerformanceMarker& marker, const char* const description )
{
void PerformanceServer::LogMarker( const PerformanceMarker& marker, const char* const description )
{
- // log to the network ( this is thread safe)
+ // log to the network ( this is thread safe )
if( mNetworkControlEnabled )
{
mNetworkServer.TransmitMarker( marker, description );
if( mNetworkControlEnabled )
{
mNetworkServer.TransmitMarker( marker, description );
// log to kernel trace
if( mPerformanceOutputBitmask & OUTPUT_KERNEL_TRACE )
{
// log to kernel trace
if( mPerformanceOutputBitmask & OUTPUT_KERNEL_TRACE )
{
+ // Kernel tracing implementation may not be thread safe
+ Mutex::ScopedLock lock( mLogMutex );
// description will be something like UPDATE_START or UPDATE_END
mKernelTrace.Trace( marker, description );
}
// description will be something like UPDATE_START or UPDATE_END
mKernelTrace.Trace( marker, description );
}
// log to system trace
if( mPerformanceOutputBitmask & OUTPUT_SYSTEM_TRACE )
{
// log to system trace
if( mPerformanceOutputBitmask & OUTPUT_SYSTEM_TRACE )
{
+ // System tracing implementation may not be thread safe
+ Mutex::ScopedLock lock( mLogMutex );
+
mSystemTrace.Trace( marker, description );
}
mSystemTrace.Trace( marker, description );
}
+ // log to Dali log ( this is thread safe )
if ( mPerformanceOutputBitmask & OUTPUT_DALI_LOG )
{
Integration::Log::LogMessage( Dali::Integration::Log::DebugInfo,
if ( mPerformanceOutputBitmask & OUTPUT_DALI_LOG )
{
Integration::Log::LogMessage( Dali::Integration::Log::DebugInfo,
// EXTERNAL INCLDUES
#include <dali/public-api/common/dali-vector.h>
// EXTERNAL INCLDUES
#include <dali/public-api/common/dali-vector.h>
+#include <dali/devel-api/common/mutex.h>
// INTERNAL INCLUDES
#include <base/performance-logging/frame-time-stats.h>
// INTERNAL INCLUDES
#include <base/performance-logging/frame-time-stats.h>
const EnvironmentOptions& mEnvironmentOptions; ///< environment options
TraceInterface& mKernelTrace; ///< kernel trace interface
TraceInterface& mSystemTrace; ///< system trace interface
const EnvironmentOptions& mEnvironmentOptions; ///< environment options
TraceInterface& mKernelTrace; ///< kernel trace interface
TraceInterface& mSystemTrace; ///< system trace interface
- boost::mutex mDataMutex; ///< mutex
+ Dali::Mutex mLogMutex; ///< mutex
NetworkPerformanceServer mNetworkServer; ///< network server
StatContextManager mStatContextManager; ///< Stat context manager
unsigned int mStatisticsLogBitmask; ///< statistics log level
NetworkPerformanceServer mNetworkServer; ///< network server
StatContextManager mStatContextManager; ///< Stat context manager
unsigned int mStatisticsLogBitmask; ///< statistics log level
{
// log to the stat contexts, can be called from multiple threads so we
// protect the data
{
// log to the stat contexts, can be called from multiple threads so we
// protect the data
+ Mutex::ScopedLock lock( mDataMutex );
for( StatContexts::Iterator it = mStatContexts.Begin(), itEnd = mStatContexts.End(); it != itEnd; ++it )
{
StatContext* context = *it;
for( StatContexts::Iterator it = mStatContexts.Begin(), itEnd = mStatContexts.End(); it != itEnd; ++it )
{
StatContext* context = *it;
{
// log to the stat contexts, can be called from multiple threads so we
// protect the data
{
// log to the stat contexts, can be called from multiple threads so we
// protect the data
+ Mutex::ScopedLock lock( mDataMutex );
StatContext* context = GetContext( contextId );
if( context )
{
StatContext* context = GetContext( contextId );
if( context )
{
+// EXTERNAL INCLUDES
+#include <dali/devel-api/common/mutex.h>
+
// INTERNAL INCLUDES
#include <base/performance-logging/performance-marker.h>
#include <base/performance-logging/statistics/stat-context.h>
// INTERNAL INCLUDES
#include <base/performance-logging/performance-marker.h>
#include <base/performance-logging/statistics/stat-context.h>
*/
StatContext* GetContext( PerformanceInterface::ContextId contextId ) const;
*/
StatContext* GetContext( PerformanceInterface::ContextId contextId ) const;
+ Dali::Mutex mDataMutex; ///< mutex
StatContexts mStatContexts; ///< The list of stat contexts
StatContextLogInterface& mLogInterface; ///< Log interface
StatContexts mStatContexts; ///< The list of stat contexts
StatContextLogInterface& mLogInterface; ///< Log interface