text: 
  #include "stdafx.h"
  
  #include "NativeUtils.h"
  
  #include <string>
  #ifndef _MSC_VER
  #include <condition_variable>
  #include <mutex>
  #include <thread>
  #endif
  
  #include <cstdint>
  #include <cstdlib>
  #include <cstring>
  
  #include <stdint.h>
  #include <stdlib.h>
  #include <string.h>
  
  OPENMPT_NAMESPACE_BEGIN
  
  #ifndef _MSC_VER
  
  namespace mpt {
  
  class semaphore {
  private:
  	unsigned int count;
  	unsigned int waiters_count;
  	std::mutex mutex;
  	std::condition_variable count_nonzero;
  public:
  	semaphore( unsigned int initial_count = 0 )
  		: count(initial_count)
  		, waiters_count(0)
  	{
  		return;
  	}
  	~semaphore() {
  		return;
  	}
  	void wait() {
  		std::unique_lock<std::mutex> l(mutex);
  		waiters_count++;
  		while ( count == 0 ) {
  			count_nonzero.wait( l );
  		}
  		waiters_count--;
  		count--;
  	}
  	void post() {
  		std::unique_lock<std::mutex> l(mutex);
  		if ( waiters_count > 0 ) {
  			count_nonzero.notify_one();
  		}
  		count++;
  	}
  	void lock() {
  		wait();
  	}
  	void unlock() {
  		post();
  	}
  };
  
  } // namespace mpt
  
  #endif
  
  OPENMPT_NAMESPACE_END
  
  extern "C" {
  
  OPENMPT_WINESUPPORT_API void * OPENMPT_WINESUPPORT_CALL OpenMPT_Alloc( size_t size ) {
  	return calloc( 1, size );
  }
  
  OPENMPT_WINESUPPORT_API void OPENMPT_WINESUPPORT_CALL OpenMPT_Free( void * mem ) {
  	if ( mem == nullptr ) {
  		return;
  	}
  	free( mem );
  	return;
  }
  
  OPENMPT_WINESUPPORT_API size_t OPENMPT_WINESUPPORT_CALL OpenMPT_String_Length( const char * str ) {
  	size_t len = 0;
  	if ( !str ) {
  		return len;
  	}
  	len = strlen( str );
  	return len;
  }
  
  OPENMPT_WINESUPPORT_API char * OPENMPT_WINESUPPORT_CALL OpenMPT_String_Duplicate( const char * src ) {
  	if ( !src ) {
  		return strdup( "" );
  	}
  	return strdup( src );
  }
  
  OPENMPT_WINESUPPORT_API void OPENMPT_WINESUPPORT_CALL OpenMPT_String_Free( char * str ) {
  	OpenMPT_Free( str );
  }
  
  typedef struct OpenMPT_Semaphore {
  #ifndef _MSC_VER
  	OPENMPT_NAMESPACE::mpt::semaphore * impl;
  #else
  	void * dummy;
  #endif
  } OpenMPT_Semaphore;
  
  OPENMPT_WINESUPPORT_API OpenMPT_Semaphore * OPENMPT_WINESUPPORT_CALL OpenMPT_Semaphore_Construct(void) {
  #ifndef _MSC_VER
  	OpenMPT_Semaphore * sem = (OpenMPT_Semaphore*)OpenMPT_Alloc( sizeof( OpenMPT_Semaphore ) );
  	sem->impl = new OPENMPT_NAMESPACE::mpt::semaphore(0);
  	return sem;
  #else
  	return nullptr;
  #endif
  }
  
  OPENMPT_WINESUPPORT_API void OPENMPT_WINESUPPORT_CALL OpenMPT_Semaphore_Destruct( OpenMPT_Semaphore * sem ) {
  #ifndef _MSC_VER
  	delete sem->impl;
  	sem->impl = nullptr;
  	OpenMPT_Free( sem );
  #else
  	MPT_UNREFERENCED_PARAMETER(sem);
  #endif
  }
  
  OPENMPT_WINESUPPORT_API void OPENMPT_WINESUPPORT_CALL OpenMPT_Semaphore_Wait( OpenMPT_Semaphore * sem ) {
  #ifndef _MSC_VER
  	sem->impl->wait();
  #else
  	MPT_UNREFERENCED_PARAMETER(sem);
  #endif
  }
  
  OPENMPT_WINESUPPORT_API void OPENMPT_WINESUPPORT_CALL OpenMPT_Semaphore_Post( OpenMPT_Semaphore * sem ) {
  #ifndef _MSC_VER
  	sem->impl->post();
  #else
  	MPT_UNREFERENCED_PARAMETER(sem);
  #endif
  }
  
  } // extern "C"
  