⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 utils.cpp

📁 C语言库函数的原型,有用的拿去
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// ==++==
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// ==--==
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
// utils.cpp
//
// Utility routines for use in ConcRT.
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

#include "concrtinternal.h"

extern "C" IMAGE_DOS_HEADER __ImageBase;

#if _UMS_ADVANCED_DEBUG

//**************************************************
//
// Global operator overloads for UMS debugging
//
//**************************************************

void ValidateHeapCall()
{
    if (UMS::Initialized())
    {
        UMSThreadProxy *pProxy = UMSThreadProxy::GetCurrent();

        //
        // Once a thread is transmogrified, it behaves as a truly external thread -- all validations are performed as such.
        //
        if (pProxy != NULL && !pProxy->IsTransmogrified())
        {
            CriticalRegionType type = pProxy->GetCriticalRegionType();

            //
            // Rules are more relaxed during shutdown when we're not responsible for scheduling anything.  We need to be in a CR for various
            // reasons, but heap allocations there won't hose us since there's nothing running.
            //
            bool validations = pProxy->IsShutdownValidations();

            if (!validations)
            {
                ContextBase *pContext = SchedulerBase::FastCurrentContext();
                if (pContext != NULL)
                    validations = pContext->IsShutdownValidations();
            }

            CORE_ASSERT(type != InsideHyperCriticalRegion || validations);
        }
    }
}

void *operator new(size_t size)
{
    ValidateHeapCall();
    return malloc(size);
}

void operator delete(void *pObj)
{
    ValidateHeapCall();
    free(pObj);
}

void *operator new[](size_t size)
{
    ValidateHeapCall();
    return malloc(size);
}

void operator delete[](void *pObj)
{
    ValidateHeapCall();
    free(pObj);
}


#endif // _UMS_ADVANCED_DEBUG

namespace Concurrency
{
namespace details
{

    /// <summary>
    ///     Default method for yielding during a spin wait
    /// </summary>
    void __cdecl _UnderlyingYield()
    {
        // Performs a yield appropriate to the scheduler.
        ContextBase *pCurrentContext = SchedulerBase::SafeFastCurrentContext();
        if (pCurrentContext != NULL)
        {
            pCurrentContext->SpinYield();
        }
        else
        {
            SwitchToThread();
        }
    }

    /// <summary>
    ///     Use Sleep(0) to do the yield.
    /// </summary>
    void __cdecl _Sleep0()
    {
        Sleep(0);
    }

    static bool g_TraceInitialized = false;
    static int g_DesiredTraceLevel = 0;
    static FILE* g_DebugOutFilePtr = stderr;
    static int g_CommitFrequency = 50;
    static unsigned __int64 g_TraceCount = 0;

    void _HyperNonReentrantLock::_Acquire()
    {
        ContextBase::StaticEnterHyperCriticalRegion();
        m_lock._Acquire();
    }

    bool _HyperNonReentrantLock::_TryAcquire()
    {
        ContextBase::StaticEnterHyperCriticalRegion();
        bool lockAcquired = m_lock._TryAcquire();
        if (!lockAcquired)
            ContextBase::StaticExitHyperCriticalRegion();
        return lockAcquired;
    }

    void _HyperNonReentrantLock::_Release()
    {
        m_lock._Release();
        ContextBase::StaticExitHyperCriticalRegion();
    }

    void _CriticalNonReentrantLock::_Acquire()
    {
        ContextBase::StaticEnterCriticalRegion();
        m_lock._Acquire();
    }

    bool _CriticalNonReentrantLock::_TryAcquire()
    {
        ContextBase::StaticEnterCriticalRegion();
        bool lockAcquired = m_lock._TryAcquire();
        if (!lockAcquired)
            ContextBase::StaticExitCriticalRegion();
        return lockAcquired;
    }

    void _CriticalNonReentrantLock::_Release()
    {
        m_lock._Release();
        ContextBase::StaticExitCriticalRegion();
    }

#if defined(CONCRT_TRACING)
    static bool
    IsWhitespace(
        wchar_t wch
        )
    {
        wchar_t buf[2];
        buf[0] = wch;
        buf[1] = 0;
        WORD type;
#pragma warning(disable: 25028)  // use of function or parameters passed to function 'GetStringTypeExW' need to be reviewed -- it has been reviewed
        if (!GetStringTypeExW(LOCALE_USER_DEFAULT, CT_CTYPE1, buf, 1, &type)) {
            return false;
        }
#pragma warning(default: 25028)
        return (type & C1_SPACE) != 0;
    }

    static wchar_t *
    SkipWhitespace(
        __out_ecount(count) wchar_t * ptr,
        int count
        )
    {
        int i = 0;
        for (; i < count && ptr[i] != 0 && iswspace(ptr[i]); ++i)
            ;
        return &ptr[i];
    }
#endif

    template<typename SignedInt, typename UnsignedInt, UnsignedInt ui_max>
    static const wchar_t *
    StringToInt(
        const wchar_t * ptr,
        SignedInt * pvalue
        )
    {
        ASSERT(*ptr != L'\0');

        bool negative;
        if (*ptr == L'-') {
            negative = true;
            ++ptr;
        }
        else {
            negative = false;
            if (*ptr == L'+') {
                ++ptr;
            }
        }

        if (*ptr < L'0' || *ptr > L'9') {
            // No number present (possibly just a sign)
            return NULL;
        }

        UnsignedInt absval = 0;
        do {
            int digit = *ptr - L'0';
            if (absval > ui_max / 10 ||
                (absval == ui_max / 10 &&
                 digit > ui_max % 10))
            {
                // Unsigned overflow
                return NULL;
            }
            absval = absval * 10 + digit;
            ++ptr;
        } while (*ptr >= L'0' && *ptr <= L'9');

        SignedInt result = static_cast<SignedInt>(absval);
        if (negative) {
            result = -result;
            if (result > 0) {
                // Signed underflow
                return NULL;
            }
        }
        else {
            if (result < 0) {
                // Signed overflow
                return NULL;
            }
        }

        *pvalue = result;
        return ptr;
    }

#if defined(CONCRT_TRACING)
    static wchar_t * ReadEnvVar(const wchar_t * name, __out_ecount(maxlen) wchar_t * buffer, DWORD maxlen)
    {
        DWORD len = GetEnvironmentVariableW(name, buffer, maxlen);

        if (len == 0) {
            return NULL;
        }

        if (len >= MAX_PATH) {
            // name too long, just ignore it
            return NULL;
        }

        wchar_t * ptr = SkipWhitespace(buffer, maxlen);
        if (*ptr == L'\0') {
            return NULL;
        }

        wchar_t * endptr = ptr + lstrlenW(ptr);
        ASSERT(*endptr == L'\0');
        while (IsWhitespace(endptr[-1])) {
            --endptr;
        }
        *endptr = L'\0';

        ASSERT(*ptr != L'\0' && !IsWhitespace(*ptr));

        return ptr;
    }

    static int ProcessTraceValue(const wchar_t * ptr)
    {
        int value;
        ptr = StringToInt<int, unsigned int, UINT_MAX>(ptr, &value);
        if (ptr == NULL || *ptr != L'\0') {
            return 0;
        }
        return value;
    }
#endif

    void InitializeUtilityRoutines()
    {
#if defined(CONCRT_TRACING)
        if (g_TraceInitialized)
        {
            return;
        }
        else
        {
            g_TraceInitialized = true;
        }

        wchar_t buffer[MAX_PATH+1];
        // bits to match TRACE arenas
        const wchar_t * ptr = ReadEnvVar(L"CONCRT_TRACE", buffer, DIM(buffer)); 
        if (ptr != NULL)
            g_DesiredTraceLevel = ProcessTraceValue(buffer);
        // when > 0, fflush every g_CommitFrequency TRACE statements, when <= 0 no flush
        ptr = ReadEnvVar(L"CONCRT_COMMIT_FREQUENCY", buffer, DIM(buffer)); 
        if (ptr != NULL)
            g_CommitFrequency = ProcessTraceValue(buffer);
        else 
            g_CommitFrequency = 1;
        // when not set will go to debug output, else stdout, stderr or filename
        const wchar_t* pwszOutputFile = ReadEnvVar(L"CONCRT_TRACE_OUTPUT", buffer, DIM(buffer)); 
        if (pwszOutputFile != NULL)
        {
            if (wcsncmp(L"stdout", pwszOutputFile, MAX_PATH) == 0)
                g_DebugOutFilePtr = stdout;
            else if (wcsncmp(L"stderr", pwszOutputFile, MAX_PATH) == 0)
            {
                g_DebugOutFilePtr = stderr;
                g_CommitFrequency = 0;
            }
            else 
            {
                buffer[MAX_PATH] = 0;
                errno_t errNo = 0;
                if ((errNo = _wfopen_s(&g_DebugOutFilePtr, pwszOutputFile, L"w+tc")) != 0)
                {
                    if (swprintf_s(buffer, MAX_PATH, L"Cannot open trace output: %S, errno=%d\n", pwszOutputFile, errNo) < 0)
                        // bad state -- try again w/o string
                        fprintf(stderr, "Cannot open trace output: errno=%d\n", errNo);
                    else
                    {
                        OutputDebugStringW(buffer);
                        fprintf(stderr, "Cannot open trace output: %S, errno=%d\n", pwszOutputFile, errNo);
                    }
                    // default to stderr
                    g_DebugOutFilePtr = stderr;
                }
            }
        }
#endif
    }

    void _ConcRT_Assert(const char *value, const char* filename, int lineno)
    {
        const int size = 1024;
        wchar_t buffer[size+1];
        const ContextBase * pContext = SchedulerBase::SafeFastCurrentContext();

        //
        // If we're on the primary we don't want to execute any blocking APIs
        //

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -