// @(#)root/tmva $Id$
// Author: Andreas Hoecker, Joerg Stelzer, Helge Voss

/**********************************************************************************
 * Project: TMVA - a Root-integrated toolkit for multivariate data analysis       *
 * Package: TMVA                                                                  *
 * Class  : Types                                                                 *
 * Web    : http://tmva.sourceforge.net                                           *
 *                                                                                *
 * Description:                                                                   *
 *      Implementation                                                            *
 *                                                                                *
 * Authors (alphabetical):                                                        *
 *      Andreas Hoecker <Andreas.Hocker@cern.ch> - CERN, Switzerland              *
 *      Joerg Stelzer   <Joerg.Stelzer@cern.ch>  - CERN, Switzerland              *
 *      Helge Voss      <Helge.Voss@cern.ch>     - MPI-K Heidelberg, Germany      *
 *                                                                                *
 * Copyright (c) 2005:                                                            *
 *      CERN, Switzerland                                                         *
 *      U. of Victoria, Canada                                                    *
 *      MPI-K Heidelberg, Germany                                                 *
 *                                                                                *
 * Redistribution and use in source and binary forms, with or without             *
 * modification, are permitted according to the terms listed in LICENSE           *
 * (http://mva.sourceforge.net/license.txt)                                       *
 **********************************************************************************/

#include <map>
#include <iostream>
#if __cplusplus > 199711L
#include <mutex>
#endif

#include "TMVA/Types.h"
#include "TMVA/MsgLogger.h"

#if __cplusplus > 199711L
std::atomic<TMVA::Types*> TMVA::Types::fgTypesPtr{0};
static std::mutex gTypesMutex;
#else
TMVA::Types* TMVA::Types::fgTypesPtr = 0;
#endif

//_______________________________________________________________________
TMVA::Types::Types()
   : fLogger( new MsgLogger("Types") )
{
   // constructor
}

TMVA::Types::~Types()
{
   // destructor
   delete fLogger;
}

//_______________________________________________________________________
TMVA::Types& TMVA::Types::Instance()
{
   // the the single instance of "Types" if existin already, or create it  (Signleton)
#if __cplusplus > 199711L
  if(!fgTypesPtr) {
    Types* tmp = new Types();
    Types* expected = 0;
    if(!fgTypesPtr.compare_exchange_strong(expected,tmp)) {
      //Another thread already did it
      delete tmp;
    }
  }
  return *fgTypesPtr;
#else
   return fgTypesPtr ? *fgTypesPtr : *(fgTypesPtr = new Types());
#endif
}
//_______________________________________________________________________
void   TMVA::Types::DestroyInstance()
{
   // "destructor" of the single instance
#if __cplusplus > 199711L
   if (fgTypesPtr != 0) { delete fgTypesPtr.load(); fgTypesPtr = 0; }
#else
   if (fgTypesPtr != 0) { delete fgTypesPtr; fgTypesPtr = 0; }
#endif
}


//_______________________________________________________________________
Bool_t TMVA::Types::AddTypeMapping( Types::EMVA method, const TString& methodname )
{
#if __cplusplus > 199711L
   std::lock_guard<std::mutex> guard(gTypesMutex);
#endif
   std::map<TString, EMVA>::const_iterator it = fStr2type.find( methodname );
   if (it != fStr2type.end()) {
      Log() << kFATAL
            << "Cannot add method " << methodname
            << " to the name->type map because it exists already" << Endl;
      return kFALSE;
   }

   fStr2type[methodname] = method;
   return kTRUE;
}

//_______________________________________________________________________
TMVA::Types::EMVA TMVA::Types::GetMethodType( const TString& method ) const
{
#if __cplusplus > 199711L
   std::lock_guard<std::mutex> guard(gTypesMutex);
#endif
   // returns the method type (enum) for a given method (string)
   std::map<TString, EMVA>::const_iterator it = fStr2type.find( method );
   if (it == fStr2type.end()) {
      Log() << kFATAL << "Unknown method in map: " << method << Endl;
      return kVariable; // Inserted to get rid of GCC warning...
   }
   else return it->second;
}

//_______________________________________________________________________
TString TMVA::Types::GetMethodName( TMVA::Types::EMVA method ) const
{
#if __cplusplus > 199711L
   std::lock_guard<std::mutex> guard(gTypesMutex);
#endif
   std::map<TString, EMVA>::const_iterator it = fStr2type.begin();
   for (; it!=fStr2type.end(); it++) if (it->second == method) return it->first;
   Log() << kFATAL << "Unknown method index in map: " << method << Endl;
   return "";
}
 Types.cxx:1
 Types.cxx:2
 Types.cxx:3
 Types.cxx:4
 Types.cxx:5
 Types.cxx:6
 Types.cxx:7
 Types.cxx:8
 Types.cxx:9
 Types.cxx:10
 Types.cxx:11
 Types.cxx:12
 Types.cxx:13
 Types.cxx:14
 Types.cxx:15
 Types.cxx:16
 Types.cxx:17
 Types.cxx:18
 Types.cxx:19
 Types.cxx:20
 Types.cxx:21
 Types.cxx:22
 Types.cxx:23
 Types.cxx:24
 Types.cxx:25
 Types.cxx:26
 Types.cxx:27
 Types.cxx:28
 Types.cxx:29
 Types.cxx:30
 Types.cxx:31
 Types.cxx:32
 Types.cxx:33
 Types.cxx:34
 Types.cxx:35
 Types.cxx:36
 Types.cxx:37
 Types.cxx:38
 Types.cxx:39
 Types.cxx:40
 Types.cxx:41
 Types.cxx:42
 Types.cxx:43
 Types.cxx:44
 Types.cxx:45
 Types.cxx:46
 Types.cxx:47
 Types.cxx:48
 Types.cxx:49
 Types.cxx:50
 Types.cxx:51
 Types.cxx:52
 Types.cxx:53
 Types.cxx:54
 Types.cxx:55
 Types.cxx:56
 Types.cxx:57
 Types.cxx:58
 Types.cxx:59
 Types.cxx:60
 Types.cxx:61
 Types.cxx:62
 Types.cxx:63
 Types.cxx:64
 Types.cxx:65
 Types.cxx:66
 Types.cxx:67
 Types.cxx:68
 Types.cxx:69
 Types.cxx:70
 Types.cxx:71
 Types.cxx:72
 Types.cxx:73
 Types.cxx:74
 Types.cxx:75
 Types.cxx:76
 Types.cxx:77
 Types.cxx:78
 Types.cxx:79
 Types.cxx:80
 Types.cxx:81
 Types.cxx:82
 Types.cxx:83
 Types.cxx:84
 Types.cxx:85
 Types.cxx:86
 Types.cxx:87
 Types.cxx:88
 Types.cxx:89
 Types.cxx:90
 Types.cxx:91
 Types.cxx:92
 Types.cxx:93
 Types.cxx:94
 Types.cxx:95
 Types.cxx:96
 Types.cxx:97
 Types.cxx:98
 Types.cxx:99
 Types.cxx:100
 Types.cxx:101
 Types.cxx:102
 Types.cxx:103
 Types.cxx:104
 Types.cxx:105
 Types.cxx:106
 Types.cxx:107
 Types.cxx:108
 Types.cxx:109
 Types.cxx:110
 Types.cxx:111
 Types.cxx:112
 Types.cxx:113
 Types.cxx:114
 Types.cxx:115
 Types.cxx:116
 Types.cxx:117
 Types.cxx:118
 Types.cxx:119
 Types.cxx:120
 Types.cxx:121
 Types.cxx:122
 Types.cxx:123
 Types.cxx:124
 Types.cxx:125
 Types.cxx:126
 Types.cxx:127
 Types.cxx:128
 Types.cxx:129
 Types.cxx:130