
#include "myMutexLocker.h"

#include <common/MuleDebug.h>
#include <Logger.h>
#include <map>

//#define _DEBUG_MUTEX_

typedef std::pair<wxMutex * , unsigned long> mutexThread ;

std::map< mutexThread, const char * > s_locked ;
wxMutex s_lockedMutex;

myMutexLocker::myMutexLocker ( wxMutex & mutex, const char * func )
        : m_isOk ( false ), m_mutex ( &mutex )
{
#ifdef _DEBUG_MUTEX_
        m_func = func ;
        AddDebugLogLineN(logSamSession, wxString ( wxT ( "mutex >>>>>>> " ) )
                           << ( long long unsigned ) m_mutex
                           << wxT ( " thread " ) << wxThread::GetCurrentId()
                           <<  wxT ( " " ) << wxString::FromAscii ( m_func ) );
        {
                wxMutexLocker lock(s_lockedMutex) ;
                test() ;
                s_locked[ mutexThread ( m_mutex, wxThread::GetCurrentId() ) ] = m_func ;
        }
#endif
        m_isOk = ( m_mutex->Lock() == wxMUTEX_NO_ERROR );
#ifdef _DEBUG_MUTEX_
        wxASSERT_MSG ( IsOk() , wxString ( wxT ( "Can not lock the mutex" ) ) );

        AddDebugLogLineN(logSamSession, wxString ( wxT ( "mutex ======= " ) )
                           << ( long long unsigned ) m_mutex
                           << wxT ( " thread " ) << wxThread::GetCurrentId()
                           <<  wxT ( " " ) << wxString::FromAscii ( m_func ) );
#endif
}

myMutexLocker::myMutexLocker ( wxMutex& mutex, long sid, const char * func )
        : m_isOk ( false ), m_mutex ( &mutex )
{
#ifdef _DEBUG_MUTEX_
        m_func = func  ;
        AddDebugLogLineN(logSamSession, wxString ( wxT ( "mutex >>>>>>> " ) )
                           << ( long long unsigned ) m_mutex
                           << wxT ( " thread " ) << wxThread::GetCurrentId()
                           <<  wxT ( " " ) << wxString::FromAscii ( m_func )
                           << wxT ( " (STREAM " )
                           << sid << wxT ( ")" ) );

        {
                wxMutexLocker lock(s_lockedMutex) ;
                test() ;
                s_locked[mutexThread ( m_mutex, wxThread::GetCurrentId() ) ] = m_func ;
        }
#endif
        m_isOk = ( m_mutex->Lock() == wxMUTEX_NO_ERROR );
#ifdef _DEBUG_MUTEX_
        wxASSERT_MSG ( IsOk() , wxString ( wxT ( "Can not lock the mutex" ) ) );

        AddDebugLogLineN(logSamSession, wxString ( wxT ( "mutex ======= " ) )
                           << ( long long unsigned ) m_mutex
                           << wxT ( " thread " ) << wxThread::GetCurrentId()
                           <<  wxT ( " " ) << wxString::FromAscii ( m_func )
                           << wxT ( " (STREAM " )
                           << sid << wxT ( ")" ) );
#endif
}

void myMutexLocker::test()
{
        if ( s_locked.count ( mutexThread ( m_mutex, wxThread::GetCurrentId() ) ) != 0 ) {
                wxString list ;

                for ( std::map<mutexThread, const char *>::const_iterator it = s_locked.begin(); it != s_locked.end(); it++ )

                        list << ( long long unsigned ) it->first.first << wxT ( " -- " )
                             << wxString::FromAscii ( it->second ) << wxT ( "\n" );

                AddDebugLogLineC(logSamSession, wxString ( wxT ( "mutex " ) )
                                   << ( long long unsigned ) m_mutex
                                   <<  wxT ( " ALREADY LOCKED. List of locked mutexes : \n " )
                                   << list );

        }

}

bool myMutexLocker::lockedInThread( wxMutex& mutex )
{
#ifdef _DEBUG_MUTEX_
        return (s_locked.count ( mutexThread ( &mutex, wxThread::GetCurrentId() ) ) != 0 ) ;
#else
        return true;
#endif
}


// returns true if mutex was successfully locked in ctor
bool myMutexLocker::IsOk() const
{
        return m_isOk;
}

// unlock the mutex in dtor
myMutexLocker::~myMutexLocker()
{
#ifdef _DEBUG_MUTEX_
        AddDebugLogLineN(logSamSession, wxString ( wxT ( "<<<<<<< mutex " ) )
                           << ( long long unsigned ) m_mutex
                           << wxT ( " thread " ) << wxThread::GetCurrentId()
                           <<  wxT ( " " )  << wxString::FromAscii ( m_func ) );
#endif
        if ( IsOk() ) {
#ifdef _DEBUG_MUTEX_
                {
                        wxMutexLocker lock(s_lockedMutex) ;
                        s_locked.erase ( mutexThread ( m_mutex, wxThread::GetCurrentId() ) ) ;
                }
#endif
                m_mutex->Unlock();
        }

}



