/*!
  \file
  File containing method definitions the the CUDAmaniple class.
*/

#include <cuda_runtime.h>


#include "anytask.hpp"
#include "cudatask.hpp"
#include "cudamaniple.hpp"

#include "cudacheck.hpp"

namespace SciGPU {

  namespace Legion {

    // -------------------------------------------------------
    
    void CUDAmaniple::Initialise( void ) {
      // Set the device
      CUDA_SAFE_CALL( cudaSetDevice( this->gpuID ) );
      
      // Allocate memory to acquire context
      int *tmp;
      
      CUDA_SAFE_CALL( cudaMalloc( (void**)&tmp, 1 ) );
      CUDA_SAFE_CALL( cudaFree( tmp ) );
	
      // Write out name
      cudaDeviceProp devProp;
      
      CUDA_SAFE_CALL( cudaGetDeviceProperties( &devProp, this->gpuID ) );
      this->LogMessage( devProp.name );
    }
    

    // -------------------------------------------------------

    void CUDAmaniple::Finalise( void ) {
      CUDA_SAFE_CALL( cudaThreadExit() );
    }

    
    // -------------------------------------------------------

    bool CUDAmaniple::ApproveType( const Task& theTask ) {
      /*!
	This method for \ref CUDAmaniple CUDAmaniples
	approves tasks of type CUDAtask and AnyTask
      */

      bool res = false;

      res = ( res || this->CheckTaskType<AnyTask>( theTask ) );
      res = ( res || this->CheckTaskType<CUDAtask>( theTask ) );

      return( res );
    }
 
    // -------------------------------------------------------

    bool CUDAmaniple::ApproveTask( const Task& theTask ) {
      
      const boost::thread::id noThread;

      bool res = true;

      if( this->CheckTaskType<CUDAtask>( theTask ) ) {
	const CUDAtask& tsk = dynamic_cast<const CUDAtask&>(theTask);

	// Check for matching ID
	res = ( boost::this_thread::get_id() == tsk.tid );
	// Check for not-a-thread, which means any CUDAmaniple
	res = ( res || ( tsk.tid == noThread ) );
      }

      return( res );
    }

  }
}
