Table of Contents

include/AK/Tools/Mac/AkPlatformFuncs.h

Go to the documentation of this file.
00001 /*******************************************************************************
00002 The content of this file includes portions of the AUDIOKINETIC Wwise Technology
00003 released in source code form as part of the SDK installer package.
00004 
00005 Commercial License Usage
00006 
00007 Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology
00008 may use this file in accordance with the end user license agreement provided 
00009 with the software or, alternatively, in accordance with the terms contained in a
00010 written agreement between you and Audiokinetic Inc.
00011 
00012 Apache License Usage
00013 
00014 Alternatively, this file may be used under the Apache License, Version 2.0 (the 
00015 "Apache License"); you may not use this file except in compliance with the 
00016 Apache License. You may obtain a copy of the Apache License at 
00017 http://www.apache.org/licenses/LICENSE-2.0.
00018 
00019 Unless required by applicable law or agreed to in writing, software distributed
00020 under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
00021 OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for
00022 the specific language governing permissions and limitations under the License.
00023 
00024   Version: <VERSION>  Build: <BUILDNUMBER>
00025   Copyright (c) <COPYRIGHTYEAR> Audiokinetic Inc.
00026 *******************************************************************************/
00027 
00028 #pragma once
00029 
00030 #include <AK/Tools/Common/AkAssert.h>
00031 #include <AK/SoundEngine/Common/AkTypes.h>
00032 
00033 #include <mach/task.h>
00034 #include <mach/semaphore.h>
00035 #include <CoreFoundation/CFString.h>
00036 #include <libkern/OSAtomic.h>
00037 #include <mach/task.h>
00038 #include <mach/mach_init.h>
00039 #include <mach/mach_time.h>
00040 #include <wchar.h>
00041 
00042 namespace AKPLATFORM
00043 {
00044     extern inline size_t AkUtf16StrLen( const AkUtf16* in_pStr );
00045     // Simple automatic event API
00046     // ------------------------------------------------------------------
00047     
00048     /// Platform Independent Helper
00049     inline void AkClearEvent( AkEvent & out_event )
00050     {
00051         out_event = 0;
00052     }
00053     
00054     /// Platform Independent Helper
00055     inline AKRESULT AkCreateEvent( AkEvent & out_event )
00056     {
00057         kern_return_t ret = semaphore_create(   
00058                             mach_task_self(),
00059                             &out_event,
00060                             SYNC_POLICY_FIFO,
00061                             0 );
00062         
00063         return ( ret == noErr  ) ? AK_Success : AK_Fail;
00064     }
00065 
00066     inline AKRESULT AkCreateSemaphore( AkSemaphore & out_semaphore, AkUInt32 in_initialCount )
00067     {
00068         kern_return_t ret = semaphore_create(   
00069                             mach_task_self(),
00070                             &out_semaphore,
00071                             SYNC_POLICY_FIFO,
00072                             in_initialCount );
00073         
00074         return ( ret == noErr  ) ? AK_Success : AK_Fail;    
00075     }
00076     
00077     /// Platform Independent Helper
00078     inline void AkDestroyEvent( AkEvent & io_event )
00079     {
00080         if( io_event != 0 )
00081         {
00082             AKVERIFY( semaphore_destroy( mach_task_self(), io_event ) == noErr);
00083         }
00084         io_event = 0;
00085     }
00086 
00087     /// Platform Independent Helper
00088     inline void AkDestroySemaphore( AkSemaphore & io_semaphore )
00089     {
00090         if( io_semaphore != 0 )
00091         {
00092             AKVERIFY( semaphore_destroy( mach_task_self(), io_semaphore ) == noErr);
00093         }
00094         io_semaphore = 0;
00095     }   
00096     
00097     /// Platform Independent Helper
00098     inline void AkWaitForEvent( AkEvent & in_event )
00099     {
00100         AKVERIFY( semaphore_wait( in_event ) == noErr );
00101     }
00102     
00103     inline void AkWaitForSemaphore( AkSemaphore & in_semaphore )
00104     {
00105         AKVERIFY( semaphore_wait( in_semaphore ) == noErr );
00106     }
00107 
00108     /// Platform Independent Helper
00109     inline void AkSignalEvent( const AkEvent & in_event )
00110     {
00111         AKVERIFY( semaphore_signal( in_event ) == noErr );
00112     }
00113     
00114     inline void AkReleaseSemaphore( const AkSemaphore & in_event )
00115     {
00116         AKVERIFY( semaphore_signal( in_event ) == noErr );
00117     }
00118     
00119     // Atomic Operations
00120     // ------------------------------------------------------------------
00121 
00122     /// Platform Independent Helper
00123     inline AkInt32 AkInterlockedIncrement(AkAtomic32 * pValue)
00124     {
00125         return __sync_add_and_fetch(pValue,1);
00126     }
00127 
00128     /// Platform Independent Helper
00129     inline AkInt32 AkInterlockedDecrement(AkAtomic32 * pValue)
00130     {
00131         return __sync_sub_and_fetch(pValue,1);
00132     }
00133 
00134     AkForceInline bool AkInterlockedCompareExchange(volatile AkAtomic32* io_pDest, AkInt32 in_newValue, AkInt32 in_expectedOldVal)
00135     {
00136         return __sync_bool_compare_and_swap(io_pDest, in_expectedOldVal, in_newValue);
00137     }
00138 
00139     AkForceInline bool AkInterlockedCompareExchange(volatile AkAtomic64* io_pDest, AkInt64 in_newValue, AkInt64 in_expectedOldVal)
00140     {
00141         return __sync_bool_compare_and_swap(io_pDest, in_expectedOldVal, in_newValue);
00142     }
00143 
00144     AkForceInline bool AkInterlockedCompareExchange(volatile AkAtomicPtr* io_pDest, AkIntPtr in_newValue, AkIntPtr in_expectedOldVal)
00145     {
00146         return __sync_bool_compare_and_swap(io_pDest, in_expectedOldVal, in_newValue);
00147     }
00148 
00149     inline void AkMemoryBarrier()
00150     {
00151         __sync_synchronize();
00152     }
00153     
00154     // Time functions
00155     // ------------------------------------------------------------------
00156 
00157     /// Platform Independent Helper
00158     inline void PerformanceCounter( AkInt64 * out_piLastTime )
00159     {
00160         *out_piLastTime = mach_absolute_time();
00161     }
00162 
00163     /// Platform Independent Helper
00164     inline void PerformanceFrequency( AkInt64 * out_piFreq )
00165     {
00166         static mach_timebase_info_data_t    sTimebaseInfo;
00167         mach_timebase_info(&sTimebaseInfo);
00168         if ( sTimebaseInfo.numer !=0 )
00169         {
00170             *out_piFreq = AkInt64((1E9 * sTimebaseInfo.denom) / sTimebaseInfo.numer );
00171         }
00172         else
00173         {
00174             *out_piFreq = 0;
00175         }
00176     }
00177 
00178 
00179     template<class destType, class srcType>
00180     inline size_t AkMacConvertString( destType* in_pdDest, const srcType* in_pSrc, size_t in_MaxSize, size_t destStrLen(const destType *),  size_t srcStrLen(const srcType *) )
00181     { 
00182         CFStringBuiltInEncodings dstEncoding;       
00183         CFStringBuiltInEncodings srcEncoding;
00184         switch(sizeof(destType))
00185         {
00186             case 1:
00187                 dstEncoding = kCFStringEncodingUTF8;
00188                 break;
00189             case 2:
00190                 dstEncoding = kCFStringEncodingUTF16LE;
00191                 break;
00192             case 4:
00193                 dstEncoding = kCFStringEncodingUTF32LE;
00194                 break;
00195             default:
00196                 AKASSERT(!"Invalid Char size");
00197         }
00198         
00199         switch(sizeof(srcType))
00200         {
00201             case 1:
00202                 srcEncoding = kCFStringEncodingUTF8;
00203                 break;
00204             case 2:
00205                 srcEncoding = kCFStringEncodingUTF16LE;
00206                 break;
00207             case 4:
00208                 srcEncoding = kCFStringEncodingUTF32LE;
00209                 break;
00210             default:
00211                 AKASSERT(!"Invalid Char size");
00212         }
00213         
00214         CFStringRef strRef;
00215         strRef = CFStringCreateWithBytes(   nil, 
00216                                          (UInt8 *) in_pSrc,
00217                                          (srcStrLen( in_pSrc ) + 1) * sizeof(srcType),
00218                                          srcEncoding,
00219                                          false );
00220         CFRange rangeToProcess = CFRangeMake(0, CFStringGetLength(strRef));
00221         CFIndex sizeConverted = CFStringGetBytes(strRef, rangeToProcess, dstEncoding, '?', false, (UInt8 *)in_pdDest , in_MaxSize * sizeof(destType), NULL);
00222         
00223         //WG-28497 Memory leak when converting strings on Mac & iOS
00224         CFRelease(strRef);
00225         
00226         return sizeConverted;
00227     }
00228 
00229     #define CONVERT_UTF16_TO_WCHAR( _astring_, _wcharstring_ ) \
00230         _wcharstring_ = (wchar_t*)AkAlloca( (1 + AKPLATFORM::AkUtf16StrLen((const AkUtf16*)_astring_)) * sizeof(wchar_t) ); \
00231         AK_UTF16_TO_WCHAR(  _wcharstring_, (const AkUtf16*)_astring_, AKPLATFORM::AkUtf16StrLen((const AkUtf16*)_astring_)+1 )
00232     
00233     #define CONVERT_WCHAR_TO_UTF16( _astring_, _utf16string_ ) \
00234         _utf16string_ = (AkUtf16*)AkAlloca( (1 + wcslen(_astring_)) * sizeof(AkUtf16) ); \
00235         AK_WCHAR_TO_UTF16(  _utf16string_, (const wchar_t*)_astring_, wcslen(_astring_)+1 )
00236 
00237     #define CONVERT_OSCHAR_TO_UTF16( _astring_, _utf16string_ ) \
00238         _utf16string_ = (AkUtf16*)AkAlloca( (1 + strlen(_astring_)) * sizeof(AkUtf16) ); \
00239         AK_OSCHAR_TO_UTF16( _utf16string_, (const AkOSChar*)_astring_, strlen(_astring_)+1 )
00240 
00241     #define CONVERT_UTF16_TO_OSCHAR( _astring_, _oscharstring_ ) \
00242         _oscharstring_ = (AkOSChar*)AkAlloca( (1 + AKPLATFORM::AkUtf16StrLen((const AkUtf16*)_astring_)) * sizeof(AkOSChar) ); \
00243         AK_UTF16_TO_OSCHAR( _oscharstring_, (const AkUtf16*)_astring_, AKPLATFORM::AkUtf16StrLen((const AkUtf16*)_astring_)+1 ) 
00244 
00245     #define AK_UTF16_TO_WCHAR(  in_pdDest, in_pSrc, in_MaxSize )    AKPLATFORM::AkMacConvertString<wchar_t, AkUtf16>(   in_pdDest, in_pSrc, in_MaxSize, &wcslen , &AKPLATFORM::AkUtf16StrLen)
00246     #define AK_WCHAR_TO_UTF16(  in_pdDest, in_pSrc, in_MaxSize )    AKPLATFORM::AkMacConvertString<AkUtf16, wchar_t>(   in_pdDest, in_pSrc, in_MaxSize, &AKPLATFORM::AkUtf16StrLen, &wcslen )
00247     #define AK_UTF16_TO_OSCHAR( in_pdDest, in_pSrc, in_MaxSize )    AKPLATFORM::AkMacConvertString<AkOSChar, AkUtf16>(  in_pdDest, in_pSrc, in_MaxSize, strlen, AKPLATFORM::AkUtf16StrLen )
00248     #define AK_UTF16_TO_CHAR(   in_pdDest, in_pSrc, in_MaxSize )    AKPLATFORM::AkMacConvertString<char, AkUtf16>(  in_pdDest, in_pSrc, in_MaxSize, strlen, AKPLATFORM::AkUtf16StrLen )
00249     #define AK_CHAR_TO_UTF16(   in_pdDest, in_pSrc, in_MaxSize )    AKPLATFORM::AkMacConvertString<AkUtf16, char>(  in_pdDest, in_pSrc, in_MaxSize, AKPLATFORM::AkUtf16StrLen, strlen)  
00250     #define AK_OSCHAR_TO_UTF16( in_pdDest, in_pSrc, in_MaxSize )    AKPLATFORM::AkMacConvertString<AkUtf16, AkOSChar>(  in_pdDest, in_pSrc, in_MaxSize, AKPLATFORM::AkUtf16StrLen, strlen)  
00251     
00252     /// Stack allocations.
00253     #define AkAlloca( _size_ ) alloca( _size_ )
00254 
00255 #if __BIGGEST_ALIGNMENT__ < AK_SIMD_ALIGNMENT
00256     #define AkAllocaSIMD( _size_ ) __builtin_alloca_with_align( _size_, AK_SIMD_ALIGNMENT*8 )
00257 #endif
00258 
00259     #define AK_LIBRARY_PREFIX               ("")
00260     #define AK_DYNAMIC_LIBRARY_EXTENSION    (".dylib")
00261 }