<commit_before>/* mbed Microcontroller Library
 * Copyright (c) 2006-2012 ARM Limited
 * SPDX-License-Identifier: MIT
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#define __STDC_LIMIT_MACROS
#include "rtos/ThisThread.h"

#include "platform/mbed_toolchain.h"
#include "rtos/Kernel.h"
#include "platform/CriticalSectionLock.h"
#include "platform/mbed_assert.h"
#include "platform/mbed_critical.h"
#include "platform/internal/mbed_os_timer.h"

using std::milli;
using std::chrono::duration;
using rtos::Kernel::Clock;
using rtos::Kernel::wait_for_u32_max;
using rtos::Kernel::wait_for_u32_forever;

#if !MBED_CONF_RTOS_PRESENT
/* If the RTOS is not present, we call mbed_thread.cpp to do the work */
/* If the RTOS is present, mbed_thread.cpp calls us to do the work */
#include "platform/mbed_thread.h"

static uint32_t thread_flags;

/* For the flags to be useful, need a way of setting them, but there's only the main
 * thread, and that has no Thread object, so Thread class is not provided. Implement
 * one CMSIS-RTOS function to provide access.
 */
extern "C"
uint32_t osThreadFlagsSet(osThreadId_t /*thread_id*/, uint32_t flags)
{
    return core_util_atomic_fetch_or_u32(&thread_flags, flags) | flags;
}
#endif

namespace rtos {

uint32_t ThisThread::flags_clear(uint32_t flags)
{
#if MBED_CONF_RTOS_PRESENT
    flags = osThreadFlagsClear(flags);
    MBED_ASSERT(!(flags & osFlagsError));
#else
    flags = core_util_atomic_fetch_and_u32(&thread_flags, ~flags);
#endif
    return flags;
}

uint32_t ThisThread::flags_get()
{
#if MBED_CONF_RTOS_PRESENT
    return osThreadFlagsGet();
#else
    return core_util_atomic_load_u32(&thread_flags);
#endif
}

#if !MBED_CONF_RTOS_PRESENT
namespace internal {
bool non_rtos_check_flags(void *handle)
{
    flags_check_capture *check = static_cast<flags_check_capture *>(handle);
    uint32_t cur_flags = core_util_atomic_load_u32(check->flags);
    uint32_t set_flags;
    do {
        set_flags = cur_flags & check->flags_wanted;
        check->result = set_flags;
        if ((check->options & osFlagsWaitAll) ? set_flags == check->flags_wanted : set_flags != 0) {
            if (check->options & osFlagsNoClear) {
                break;
            }
        } else {
            return false;
        }
    } while (!core_util_atomic_cas_u32(check->flags, &cur_flags, cur_flags & ~set_flags));
    check->match = true;
    return true;
}
}
#endif

static uint32_t flags_wait_for(uint32_t flags, Clock::duration_u32 rel_time, bool clear, uint32_t options)
{
    if (!clear) {
        options |= osFlagsNoClear;
    }
#if MBED_CONF_RTOS_PRESENT
    flags = osThreadFlagsWait(flags, options, rel_time.count());
    if (flags & osFlagsError) {
        MBED_ASSERT((flags == osFlagsErrorTimeout && rel_time != wait_for_u32_forever) ||
                    (flags == osFlagsErrorResource && rel_time == rel_time.zero()));
        flags = ThisThread::flags_get();
    }
#else
    rtos::internal::flags_check_capture check;
    check.flags = &thread_flags;
    check.options = options;
    check.flags_wanted = flags;
    check.result = 0;
    mbed::internal::do_timed_sleep_relative_or_forever(rel_time, rtos::internal::non_rtos_check_flags, &check);
    flags = check.result;
#endif

    return flags;
}

static uint32_t flags_wait(uint32_t flags, bool clear, uint32_t options)
{
#if MBED_CONF_RTOS_PRESENT
    return flags_wait_for(flags, wait_for_u32_forever, clear, options);
#else
    /* Avoids pulling in timer if not used */
    if (!clear) {
        options |= osFlagsNoClear;
    }
    rtos::internal::flags_check_capture check;
    check.flags = &thread_flags;
    check.options = options;
    check.flags_wanted = flags;
    check.result = 0;
    mbed::internal::do_untimed_sleep(rtos::internal::non_rtos_check_flags, &check);
    flags = check.result;

    return flags;
#endif
}

static uint32_t flags_wait_until(uint32_t flags, Clock::time_point abs_time, bool clear, uint32_t options)
{
    Clock::time_point now = Clock::now();

    Clock::duration_u32 rel_time;
    if (now >= abs_time) {
        rel_time = rel_time.zero();
    } else if (abs_time - now > wait_for_u32_max) {
        // Documentation permits early return for big offsets
        rel_time = wait_for_u32_max;
    } else {
        rel_time = abs_time - now;
    }
    return flags_wait_for(flags, rel_time, clear, options);
}

uint32_t ThisThread::flags_wait_all(uint32_t flags, bool clear)
{
    return flags_wait(flags, clear, osFlagsWaitAll);
}

uint32_t ThisThread::flags_wait_all_for(uint32_t flags, uint32_t millisec, bool clear)
{
    return flags_wait_all_for(flags, duration<uint32_t, milli>(millisec), clear);
}

uint32_t ThisThread::flags_wait_all_for(uint32_t flags, Clock::duration_u32 rel_time, bool clear)
{
    return flags_wait_for(flags, rel_time, clear, osFlagsWaitAll);
}

uint32_t ThisThread::flags_wait_all_until(uint32_t flags, uint64_t millisec, bool clear)
{
    return flags_wait_all_until(flags, Clock::time_point(duration<uint64_t, milli>(millisec)), clear);
}

uint32_t ThisThread::flags_wait_all_until(uint32_t flags, Clock::time_point abs_time, bool clear)
{
    return flags_wait_until(flags, abs_time, clear, osFlagsWaitAll);
}

uint32_t ThisThread::flags_wait_any(uint32_t flags, bool clear)
{
    return flags_wait(flags, clear, osFlagsWaitAny);
}

uint32_t ThisThread::flags_wait_any_for(uint32_t flags, uint32_t millisec, bool clear)
{
    return flags_wait_any_for(flags, duration<uint32_t, milli>(millisec), clear);
}

uint32_t ThisThread::flags_wait_any_for(uint32_t flags, Clock::duration_u32 rel_time, bool clear)
{
    return flags_wait_for(flags, rel_time, clear, osFlagsWaitAny);
}

uint32_t ThisThread::flags_wait_any_until(uint32_t flags, uint64_t millisec, bool clear)
{
    return flags_wait_any_until(flags, Clock::time_point(duration<uint64_t, milli>(millisec)), clear);
}

uint32_t ThisThread::flags_wait_any_until(uint32_t flags, Clock::time_point abs_time, bool clear)
{
    return flags_wait_until(flags, abs_time, clear, osFlagsWaitAny);
}

void ThisThread::sleep_for(uint32_t millisec)
{
    ThisThread::sleep_for(duration<uint32_t, std::milli>(millisec));
}

void ThisThread::sleep_for(Clock::duration_u32 rel_time)
{
#if MBED_CONF_RTOS_PRESENT
    osStatus_t status = osDelay(rel_time.count());
    MBED_ASSERT(status == osOK);
    (void) status;
#else
    thread_sleep_for(rel_time.count());
#endif
}

void ThisThread::sleep_until(uint64_t millisec)
{
    ThisThread::sleep_until(Clock::time_point(duration<uint64_t, milli>(millisec)));
}

void ThisThread::sleep_until(Clock::time_point abs_time)
{
#if MBED_CONF_RTOS_PRESENT
    Clock::time_point now;

    while ((now = Clock::now()) < abs_time) {
        if (abs_time - now > wait_for_u32_max) {
            osStatus_t status = osDelay(wait_for_u32_max.count());
            MBED_ASSERT(status == osOK);
            (void) status;
            continue;
        } else {
            osStatus_t status = osDelay((abs_time - now).count());
            MBED_ASSERT(status == osOK);
            (void) status;
            break;
        }
    }
#else
    thread_sleep_until(abs_time.time_since_epoch().count());
#endif
}

void ThisThread::yield()
{
#if MBED_CONF_RTOS_PRESENT
    osThreadYield();
#else
    asm("yield");
#endif
}

osThreadId_t ThisThread::get_id()
{
#if MBED_CONF_RTOS_PRESENT
    return osThreadGetId();
#else
    return (osThreadId_t) 1; // dummy non-0 value
#endif
}

const char *ThisThread::get_name()
{
#if MBED_CONF_RTOS_PRESENT
    osThreadId_t id = osThreadGetId();
    if (id == nullptr) {
        return nullptr;
    }
    return osThreadGetName(id);
#else
    return nullptr;
#endif
}

}
<commit_msg>rtos: fix delay with 0<commit_after>/* mbed Microcontroller Library
 * Copyright (c) 2006-2012 ARM Limited
 * SPDX-License-Identifier: MIT
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#define __STDC_LIMIT_MACROS
#include "rtos/ThisThread.h"

#include "platform/mbed_toolchain.h"
#include "rtos/Kernel.h"
#include "platform/CriticalSectionLock.h"
#include "platform/mbed_assert.h"
#include "platform/mbed_critical.h"
#include "platform/internal/mbed_os_timer.h"

using std::milli;
using std::chrono::duration;
using rtos::Kernel::Clock;
using rtos::Kernel::wait_for_u32_max;
using rtos::Kernel::wait_for_u32_forever;

#if !MBED_CONF_RTOS_PRESENT
/* If the RTOS is not present, we call mbed_thread.cpp to do the work */
/* If the RTOS is present, mbed_thread.cpp calls us to do the work */
#include "platform/mbed_thread.h"

static uint32_t thread_flags;

/* For the flags to be useful, need a way of setting them, but there's only the main
 * thread, and that has no Thread object, so Thread class is not provided. Implement
 * one CMSIS-RTOS function to provide access.
 */
extern "C"
uint32_t osThreadFlagsSet(osThreadId_t /*thread_id*/, uint32_t flags)
{
    return core_util_atomic_fetch_or_u32(&thread_flags, flags) | flags;
}
#endif

namespace rtos {

uint32_t ThisThread::flags_clear(uint32_t flags)
{
#if MBED_CONF_RTOS_PRESENT
    flags = osThreadFlagsClear(flags);
    MBED_ASSERT(!(flags & osFlagsError));
#else
    flags = core_util_atomic_fetch_and_u32(&thread_flags, ~flags);
#endif
    return flags;
}

uint32_t ThisThread::flags_get()
{
#if MBED_CONF_RTOS_PRESENT
    return osThreadFlagsGet();
#else
    return core_util_atomic_load_u32(&thread_flags);
#endif
}

#if !MBED_CONF_RTOS_PRESENT
namespace internal {
bool non_rtos_check_flags(void *handle)
{
    flags_check_capture *check = static_cast<flags_check_capture *>(handle);
    uint32_t cur_flags = core_util_atomic_load_u32(check->flags);
    uint32_t set_flags;
    do {
        set_flags = cur_flags & check->flags_wanted;
        check->result = set_flags;
        if ((check->options & osFlagsWaitAll) ? set_flags == check->flags_wanted : set_flags != 0) {
            if (check->options & osFlagsNoClear) {
                break;
            }
        } else {
            return false;
        }
    } while (!core_util_atomic_cas_u32(check->flags, &cur_flags, cur_flags & ~set_flags));
    check->match = true;
    return true;
}
}
#endif

static uint32_t flags_wait_for(uint32_t flags, Clock::duration_u32 rel_time, bool clear, uint32_t options)
{
    if (!clear) {
        options |= osFlagsNoClear;
    }
#if MBED_CONF_RTOS_PRESENT
    flags = osThreadFlagsWait(flags, options, rel_time.count());
    if (flags & osFlagsError) {
        MBED_ASSERT((flags == osFlagsErrorTimeout && rel_time != wait_for_u32_forever) ||
                    (flags == osFlagsErrorResource && rel_time == rel_time.zero()));
        flags = ThisThread::flags_get();
    }
#else
    rtos::internal::flags_check_capture check;
    check.flags = &thread_flags;
    check.options = options;
    check.flags_wanted = flags;
    check.result = 0;
    mbed::internal::do_timed_sleep_relative_or_forever(rel_time, rtos::internal::non_rtos_check_flags, &check);
    flags = check.result;
#endif

    return flags;
}

static uint32_t flags_wait(uint32_t flags, bool clear, uint32_t options)
{
#if MBED_CONF_RTOS_PRESENT
    return flags_wait_for(flags, wait_for_u32_forever, clear, options);
#else
    /* Avoids pulling in timer if not used */
    if (!clear) {
        options |= osFlagsNoClear;
    }
    rtos::internal::flags_check_capture check;
    check.flags = &thread_flags;
    check.options = options;
    check.flags_wanted = flags;
    check.result = 0;
    mbed::internal::do_untimed_sleep(rtos::internal::non_rtos_check_flags, &check);
    flags = check.result;

    return flags;
#endif
}

static uint32_t flags_wait_until(uint32_t flags, Clock::time_point abs_time, bool clear, uint32_t options)
{
    Clock::time_point now = Clock::now();

    Clock::duration_u32 rel_time;
    if (now >= abs_time) {
        rel_time = rel_time.zero();
    } else if (abs_time - now > wait_for_u32_max) {
        // Documentation permits early return for big offsets
        rel_time = wait_for_u32_max;
    } else {
        rel_time = abs_time - now;
    }
    return flags_wait_for(flags, rel_time, clear, options);
}

uint32_t ThisThread::flags_wait_all(uint32_t flags, bool clear)
{
    return flags_wait(flags, clear, osFlagsWaitAll);
}

uint32_t ThisThread::flags_wait_all_for(uint32_t flags, uint32_t millisec, bool clear)
{
    return flags_wait_all_for(flags, duration<uint32_t, milli>(millisec), clear);
}

uint32_t ThisThread::flags_wait_all_for(uint32_t flags, Clock::duration_u32 rel_time, bool clear)
{
    return flags_wait_for(flags, rel_time, clear, osFlagsWaitAll);
}

uint32_t ThisThread::flags_wait_all_until(uint32_t flags, uint64_t millisec, bool clear)
{
    return flags_wait_all_until(flags, Clock::time_point(duration<uint64_t, milli>(millisec)), clear);
}

uint32_t ThisThread::flags_wait_all_until(uint32_t flags, Clock::time_point abs_time, bool clear)
{
    return flags_wait_until(flags, abs_time, clear, osFlagsWaitAll);
}

uint32_t ThisThread::flags_wait_any(uint32_t flags, bool clear)
{
    return flags_wait(flags, clear, osFlagsWaitAny);
}

uint32_t ThisThread::flags_wait_any_for(uint32_t flags, uint32_t millisec, bool clear)
{
    return flags_wait_any_for(flags, duration<uint32_t, milli>(millisec), clear);
}

uint32_t ThisThread::flags_wait_any_for(uint32_t flags, Clock::duration_u32 rel_time, bool clear)
{
    return flags_wait_for(flags, rel_time, clear, osFlagsWaitAny);
}

uint32_t ThisThread::flags_wait_any_until(uint32_t flags, uint64_t millisec, bool clear)
{
    return flags_wait_any_until(flags, Clock::time_point(duration<uint64_t, milli>(millisec)), clear);
}

uint32_t ThisThread::flags_wait_any_until(uint32_t flags, Clock::time_point abs_time, bool clear)
{
    return flags_wait_until(flags, abs_time, clear, osFlagsWaitAny);
}

void ThisThread::sleep_for(uint32_t millisec)
{
    ThisThread::sleep_for(duration<uint32_t, std::milli>(millisec));
}

void ThisThread::sleep_for(Clock::duration_u32 rel_time)
{
#if MBED_CONF_RTOS_PRESENT
    uint32_t delay = rel_time.count();
    if (delay != 0) {
        osStatus_t status = osDelay(delay);
        MBED_ASSERT(status == osOK);
        (void) status;
    }
#else
    thread_sleep_for(rel_time.count());
#endif
}

void ThisThread::sleep_until(uint64_t millisec)
{
    ThisThread::sleep_until(Clock::time_point(duration<uint64_t, milli>(millisec)));
}

void ThisThread::sleep_until(Clock::time_point abs_time)
{
#if MBED_CONF_RTOS_PRESENT
    Clock::time_point now;

    while ((now = Clock::now()) < abs_time) {
        if (abs_time - now > wait_for_u32_max) {
            osStatus_t status = osDelay(wait_for_u32_max.count());
            MBED_ASSERT(status == osOK);
            (void) status;
            continue;
        } else {
            osStatus_t status = osDelay((abs_time - now).count());
            MBED_ASSERT(status == osOK);
            (void) status;
            break;
        }
    }
#else
    thread_sleep_until(abs_time.time_since_epoch().count());
#endif
}

void ThisThread::yield()
{
#if MBED_CONF_RTOS_PRESENT
    osThreadYield();
#else
    asm("yield");
#endif
}

osThreadId_t ThisThread::get_id()
{
#if MBED_CONF_RTOS_PRESENT
    return osThreadGetId();
#else
    return (osThreadId_t) 1; // dummy non-0 value
#endif
}

const char *ThisThread::get_name()
{
#if MBED_CONF_RTOS_PRESENT
    osThreadId_t id = osThreadGetId();
    if (id == nullptr) {
        return nullptr;
    }
    return osThreadGetName(id);
#else
    return nullptr;
#endif
}

}
<|endoftext|>


<commit_before>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
# define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
# define AMD_PLATFORM_BUILD_NUMBER 1713
#endif // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
# define AMD_PLATFORM_REVISION_NUMBER 0
#endif // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
# define AMD_PLATFORM_RELEASE_INFO
#endif // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING XSTR(AMD_PLATFORM_BUILD_NUMBER) \
    "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
# define AMD_PLATFORM_INFO "AMD-APP" AMD_PLATFORM_RELEASE_INFO \
    DEBUG_ONLY("." IF(IS_OPTIMIZED,"opt","dbg")) " (" AMD_BUILD_STRING ")"
#endif // ATI_PLATFORM_INFO

#endif // VERSIONS_HPP_
<commit_msg>P4 to Git Change 1112253 by johtaylo@johtaylo-JTBUILDER03-increment on 2015/01/16 03:00:15<commit_after>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
# define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
# define AMD_PLATFORM_BUILD_NUMBER 1714
#endif // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
# define AMD_PLATFORM_REVISION_NUMBER 0
#endif // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
# define AMD_PLATFORM_RELEASE_INFO
#endif // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING XSTR(AMD_PLATFORM_BUILD_NUMBER) \
    "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
# define AMD_PLATFORM_INFO "AMD-APP" AMD_PLATFORM_RELEASE_INFO \
    DEBUG_ONLY("." IF(IS_OPTIMIZED,"opt","dbg")) " (" AMD_BUILD_STRING ")"
#endif // ATI_PLATFORM_INFO

#endif // VERSIONS_HPP_
<|endoftext|>


<commit_before>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
# define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
# define AMD_PLATFORM_BUILD_NUMBER 1599
#endif // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
# define AMD_PLATFORM_REVISION_NUMBER 0
#endif // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
# define AMD_PLATFORM_RELEASE_INFO
#endif // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING XSTR(AMD_PLATFORM_BUILD_NUMBER) \
    "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
# define AMD_PLATFORM_INFO "AMD-APP" AMD_PLATFORM_RELEASE_INFO \
    DEBUG_ONLY("." IF(IS_OPTIMIZED,"opt","dbg")) " (" AMD_BUILD_STRING ")"
#endif // ATI_PLATFORM_INFO

#endif // VERSIONS_HPP_
<commit_msg>P4 to Git Change 1060846 by johtaylo@johtaylo-JTBUILDER03-increment on 2014/07/30 03:00:11<commit_after>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
# define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
# define AMD_PLATFORM_BUILD_NUMBER 1600
#endif // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
# define AMD_PLATFORM_REVISION_NUMBER 0
#endif // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
# define AMD_PLATFORM_RELEASE_INFO
#endif // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING XSTR(AMD_PLATFORM_BUILD_NUMBER) \
    "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
# define AMD_PLATFORM_INFO "AMD-APP" AMD_PLATFORM_RELEASE_INFO \
    DEBUG_ONLY("." IF(IS_OPTIMIZED,"opt","dbg")) " (" AMD_BUILD_STRING ")"
#endif // ATI_PLATFORM_INFO

#endif // VERSIONS_HPP_
<|endoftext|>


<commit_before>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
# define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
# define AMD_PLATFORM_BUILD_NUMBER 1666
#endif // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
# define AMD_PLATFORM_REVISION_NUMBER 0
#endif // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
# define AMD_PLATFORM_RELEASE_INFO
#endif // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING XSTR(AMD_PLATFORM_BUILD_NUMBER) \
    "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
# define AMD_PLATFORM_INFO "AMD-APP" AMD_PLATFORM_RELEASE_INFO \
    DEBUG_ONLY("." IF(IS_OPTIMIZED,"opt","dbg")) " (" AMD_BUILD_STRING ")"
#endif // ATI_PLATFORM_INFO

#endif // VERSIONS_HPP_
<commit_msg>P4 to Git Change 1090678 by johtaylo@johtaylo-JTBUILDER03-increment on 2014/10/24 03:00:12<commit_after>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
# define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
# define AMD_PLATFORM_BUILD_NUMBER 1667
#endif // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
# define AMD_PLATFORM_REVISION_NUMBER 0
#endif // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
# define AMD_PLATFORM_RELEASE_INFO
#endif // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING XSTR(AMD_PLATFORM_BUILD_NUMBER) \
    "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
# define AMD_PLATFORM_INFO "AMD-APP" AMD_PLATFORM_RELEASE_INFO \
    DEBUG_ONLY("." IF(IS_OPTIMIZED,"opt","dbg")) " (" AMD_BUILD_STRING ")"
#endif // ATI_PLATFORM_INFO

#endif // VERSIONS_HPP_
<|endoftext|>


<commit_before>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
# define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
# define AMD_PLATFORM_BUILD_NUMBER 1601
#endif // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
# define AMD_PLATFORM_REVISION_NUMBER 0
#endif // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
# define AMD_PLATFORM_RELEASE_INFO
#endif // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING XSTR(AMD_PLATFORM_BUILD_NUMBER) \
    "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
# define AMD_PLATFORM_INFO "AMD-APP" AMD_PLATFORM_RELEASE_INFO \
    DEBUG_ONLY("." IF(IS_OPTIMIZED,"opt","dbg")) " (" AMD_BUILD_STRING ")"
#endif // ATI_PLATFORM_INFO

#endif // VERSIONS_HPP_
<commit_msg>P4 to Git Change 1061929 by johtaylo@johtaylo-JTBUILDER03-increment on 2014/08/01 03:00:11<commit_after>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
# define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
# define AMD_PLATFORM_BUILD_NUMBER 1602
#endif // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
# define AMD_PLATFORM_REVISION_NUMBER 0
#endif // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
# define AMD_PLATFORM_RELEASE_INFO
#endif // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING XSTR(AMD_PLATFORM_BUILD_NUMBER) \
    "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
# define AMD_PLATFORM_INFO "AMD-APP" AMD_PLATFORM_RELEASE_INFO \
    DEBUG_ONLY("." IF(IS_OPTIMIZED,"opt","dbg")) " (" AMD_BUILD_STRING ")"
#endif // ATI_PLATFORM_INFO

#endif // VERSIONS_HPP_
<|endoftext|>


<commit_before>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
# define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
# define AMD_PLATFORM_BUILD_NUMBER 2127
#endif // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
# define AMD_PLATFORM_REVISION_NUMBER 0
#endif // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
# define AMD_PLATFORM_RELEASE_INFO
#endif // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING XSTR(AMD_PLATFORM_BUILD_NUMBER) \
    "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
# define AMD_PLATFORM_INFO "AMD-APP" AMD_PLATFORM_RELEASE_INFO \
    DEBUG_ONLY("." IF(IS_OPTIMIZED,"opt","dbg")) " (" AMD_BUILD_STRING ")"
#endif // ATI_PLATFORM_INFO

#endif // VERSIONS_HPP_
<commit_msg>P4 to Git Change 1274130 by johtaylo@johtaylo-JTBUILDER03-increment on 2016/05/28 03:00:09<commit_after>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
# define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
# define AMD_PLATFORM_BUILD_NUMBER 2128
#endif // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
# define AMD_PLATFORM_REVISION_NUMBER 0
#endif // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
# define AMD_PLATFORM_RELEASE_INFO
#endif // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING XSTR(AMD_PLATFORM_BUILD_NUMBER) \
    "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
# define AMD_PLATFORM_INFO "AMD-APP" AMD_PLATFORM_RELEASE_INFO \
    DEBUG_ONLY("." IF(IS_OPTIMIZED,"opt","dbg")) " (" AMD_BUILD_STRING ")"
#endif // ATI_PLATFORM_INFO

#endif // VERSIONS_HPP_
<|endoftext|>


<commit_before>#define WIN32_LEAN_AND_MEAN

#include <iostream>
#include <map>
#include <memory>
#include <sstream>
#include <string>
#include <utility>
#include <uv.h>
#include <vector>
#include <windows.h>

#include "../../helper/windows/helper.h"
#include "../../lock.h"
#include "../../log.h"
#include "../../message.h"
#include "../../message_buffer.h"
#include "../recent_file_cache.h"
#include "../worker_platform.h"
#include "../worker_thread.h"
#include "subscription.h"

using std::default_delete;
using std::endl;
using std::make_pair;
using std::map;
using std::move;
using std::ostream;
using std::ostringstream;
using std::pair;
using std::shared_ptr;
using std::string;
using std::unique_ptr;
using std::vector;
using std::wostringstream;
using std::wstring;

const size_t DEFAULT_CACHE_SIZE = 4096;

const size_t DEFAULT_CACHE_PREPOPULATION = 1024;

void CALLBACK command_perform_helper(__in ULONG_PTR payload);

void CALLBACK event_helper(DWORD error_code, DWORD num_bytes, LPOVERLAPPED overlapped);

class WindowsWorkerPlatform : public WorkerPlatform
{
public:
  WindowsWorkerPlatform(WorkerThread *thread) : WorkerPlatform(thread), thread_handle{0}, cache{DEFAULT_CACHE_SIZE}
  {
    int err;

    err = uv_mutex_init(&thread_handle_mutex);
    if (err) {
      report_uv_error(err);
    }
    freeze();
  };

  ~WindowsWorkerPlatform() override { uv_mutex_destroy(&thread_handle_mutex); }

  Result<> wake() override
  {
    Lock lock(thread_handle_mutex);

    if (!thread_handle) {
      return ok_result();
    }

    BOOL success = QueueUserAPC(command_perform_helper, thread_handle, reinterpret_cast<ULONG_PTR>(this));
    if (!success) {
      return windows_error_result<>("Unable to queue APC");
    }

    return ok_result();
  }

  Result<> listen() override
  {
    {
      Lock lock(thread_handle_mutex);

      HANDLE pseudo_handle = GetCurrentThread();
      BOOL success = DuplicateHandle(GetCurrentProcess(),  // Source process
        pseudo_handle,  // Source handle
        GetCurrentProcess(),  // Destination process
        &thread_handle,  // Destination handle
        0,  // Desired access
        FALSE,  // Inheritable by new processes
        DUPLICATE_SAME_ACCESS  // options
      );
      if (!success) {
        return windows_error_result<>("Unable to duplicate thread handle");
      }
    }

    while (true) {
      SleepEx(INFINITE, true);
    }

    return error_result("listen loop ended unexpectedly");
  }

  Result<bool> handle_add_command(CommandID command,
    ChannelID channel,
    const string &root_path,
    bool recursive) override
  {
    // Convert the path to a wide-character string
    Result<wstring> convr = to_wchar(root_path);
    if (convr.is_error()) return convr.propagate<bool>();
    wstring &root_path_w = convr.get_value();

    // Open a directory handle
    HANDLE root = CreateFileW(root_path_w.c_str(),  // null-terminated wchar file name
      FILE_LIST_DIRECTORY,  // desired access
      FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,  // share mode
      NULL,  // security attributes
      OPEN_EXISTING,  // creation disposition
      FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,  // flags and attributes
      NULL  // template file
    );
    if (root == INVALID_HANDLE_VALUE) {
      return windows_error_result<bool>("Unable to open directory handle");
    }

    // Allocate and persist the subscription
    Subscription *sub = new Subscription(channel, root, root_path_w, recursive, this);
    auto insert_result = subscriptions.insert(make_pair(channel, sub));
    if (!insert_result.second) {
      delete sub;

      ostringstream msg("Channel collision: ");
      msg << channel;
      return Result<bool>::make_error(msg.str());
    }

    ostream &logline = LOGGER << "Added directory root " << root_path;
    if (!recursive) logline << " (non-recursive)";
    logline << " at channel " << channel << "." << endl;

    Result<bool> schedr = sub->schedule(&event_helper);
    if (schedr.is_error()) return schedr.propagate<bool>();
    if (!schedr.get_value()) {
      LOGGER << "Falling back to polling for watch root " << root_path << "." << endl;

      return emit(Message(CommandPayloadBuilder::add(channel, string(root_path), recursive, 1).build()))
        .propagate(false);
    }

    cache.prepopulate(root_path, DEFAULT_CACHE_PREPOPULATION);

    return ok_result(true);
  }

  Result<bool> handle_remove_command(CommandID command, ChannelID channel) override
  {
    auto it = subscriptions.find(channel);
    if (it == subscriptions.end()) {
      LOGGER << "Channel " << channel << " was already removed." << endl;
      return ok_result(true);
    }

    Result<> r = it->second->stop(command);
    if (r.is_error()) return r.propagate<bool>();

    LOGGER << "Subscription for channel " << channel << " stopped." << endl;
    return ok_result(false);
  }

  Result<> handle_fs_event(DWORD error_code, DWORD num_bytes, Subscription *sub)
  {
    // Ensure that the subscription is valid.
    ChannelID channel = sub->get_channel();
    auto it = subscriptions.find(channel);
    if (it == subscriptions.end() || it->second != sub) {
      return ok_result();
    }

    // Subscription termination.
    bool terminate = false;
    if (error_code == ERROR_OPERATION_ABORTED) {
      LOGGER << "Completing termination of channel " << channel << "." << endl;
      terminate = true;
    } else if (sub->is_terminating()) {
      LOGGER << "Filesystem event encountered on terminating channel " << channel << "." << endl;
      terminate = true;
    }
    if (terminate) return remove(sub);

    // Handle errors.
    if (error_code == ERROR_INVALID_PARAMETER) {
      LOGGER << "Attempting to revert to a network-friendly buffer size." << endl;

      Result<> resize = sub->use_network_size();
      if (resize.is_error()) return emit_fatal_error(sub, move(resize));

      return reschedule(sub);
    }

    if (error_code == ERROR_NOTIFY_ENUM_DIR) {
      LOGGER << "Change buffer overflow. Some events may have been lost." << endl;
      return reschedule(sub);
    }

    if (error_code != ERROR_SUCCESS) {
      return emit_fatal_error(sub, windows_error_result<>("Completion callback error", error_code));
    }

    // Schedule the next completion callback.
    BYTE *base = sub->get_written(num_bytes);
    Result<> next = reschedule(sub);

    // Process received events.
    MessageBuffer buffer;
    ChannelMessageBuffer messages(buffer, channel);
    size_t num_events = 0;
    bool old_path_seen = false;
    string old_path;

    while (true) {
      PFILE_NOTIFY_INFORMATION info = reinterpret_cast<PFILE_NOTIFY_INFORMATION>(base);
      num_events++;

      Result<> pr = process_event_payload(info, sub, messages, old_path_seen, old_path);
      if (pr.is_error()) {
        LOGGER << "Skipping entry " << pr << "." << endl;
      }

      if (info->NextEntryOffset == 0) {
        break;
      }
      base += info->NextEntryOffset;
    }

    cache.apply();
    cache.prune();

    if (!messages.empty()) {
      Result<> er = emit_all(messages.begin(), messages.end());
      if (er.is_error()) {
        LOGGER << "Unable to emit messages: " << er << "." << endl;
      } else {
        LOGGER << "Filesystem event batch of size " << num_events << " completed. "
               << plural(messages.size(), "message") << " produced." << endl;
      }
    }

    return next.propagate_as_void();
  }

private:
  Result<> reschedule(Subscription *sub)
  {
    Result<bool> sch = sub->schedule(&event_helper);
    if (sch.is_error()) return emit_fatal_error(sub, sch.propagate_as_void());

    if (!sch.get_value()) {
      Result<string> root = sub->get_root_path();
      if (root.is_error()) return emit_fatal_error(sub, root.propagate_as_void());

      LOGGER << "Falling back to polling for path " << root.get_value() << " at channel " << sub->get_channel() << "."
             << endl;

      Result<> rem = remove(sub);
      rem &= emit(Message(
        CommandPayloadBuilder::add(sub->get_channel(), move(root.get_value()), sub->is_recursive(), 1).build()));
      return rem;
    }

    return ok_result();
  }

  Result<> remove(Subscription *sub)
  {
    Message response(AckPayload(sub->get_command_id(), sub->get_channel(), true, ""));

    // Ensure that the subscription is valid.
    ChannelID channel = sub->get_channel();
    auto it = subscriptions.find(channel);
    if (it == subscriptions.end() || it->second != sub) {
      return ok_result();
    }

    subscriptions.erase(it);
    delete sub;

    if (sub->get_command_id() != NULL_COMMAND_ID) {
      return emit(move(response));
    } else {
      return ok_result();
    }
  }

  Result<> emit_fatal_error(Subscription *sub, Result<> &&r)
  {
    assert(r.is_error());

    Result<> out = emit(Message(ErrorPayload(sub->get_channel(), string(r.get_error()), true)));
    out &= remove(sub);
    return out;
  }

  Result<> process_event_payload(PFILE_NOTIFY_INFORMATION info,
    Subscription *sub,
    ChannelMessageBuffer &messages,
    bool &old_path_seen,
    string &old_path)
  {
    ChannelID channel = sub->get_channel();
    wstring relpathw{info->FileName, info->FileNameLength / sizeof(WCHAR)};
    wstring pathw = sub->make_absolute(move(relpathw));

    Result<string> u8r = to_utf8(pathw);
    if (u8r.is_error()) {
      LOGGER << "Unable to convert path to utf-8: " << u8r << "." << endl;
      return ok_result();
    }
    string &path = u8r.get_value();

    shared_ptr<StatResult> stat;
    if (info->Action == FILE_ACTION_REMOVED || info->Action == FILE_ACTION_RENAMED_OLD_NAME) {
      stat = cache.former_at_path(path, false, false);
    } else {
      stat = cache.current_at_path(path, false, false);
      if (stat->is_absent()) {
        stat = cache.former_at_path(path, false, false);
      }
    }
    EntryKind kind = stat->get_entry_kind();

    switch (info->Action) {
      case FILE_ACTION_ADDED: messages.created(move(path), kind); break;
      case FILE_ACTION_MODIFIED: messages.modified(move(path), kind); break;
      case FILE_ACTION_REMOVED: messages.deleted(move(path), kind); break;
      case FILE_ACTION_RENAMED_OLD_NAME:
        old_path_seen = true;
        old_path = move(path);
        break;
      case FILE_ACTION_RENAMED_NEW_NAME:
        if (old_path_seen) {
          // Old name received first
          messages.renamed(move(old_path), move(path), kind);
          old_path_seen = false;
        } else {
          // No old name. Treat it as a creation
          messages.created(move(path), kind);
        }
        break;
      default:
        ostringstream out;
        out << "Unexpected action " << info->Action << " reported by ReadDirectoryChangesW for " << path;
        return error_result(out.str());
        break;
    }

    return ok_result();
  }

  uv_mutex_t thread_handle_mutex;
  HANDLE thread_handle;

  map<ChannelID, Subscription *> subscriptions;

  RecentFileCache cache;
};

unique_ptr<WorkerPlatform> WorkerPlatform::for_worker(WorkerThread *thread)
{
  return unique_ptr<WorkerPlatform>(new WindowsWorkerPlatform(thread));
}

void CALLBACK command_perform_helper(__in ULONG_PTR payload)
{
  WindowsWorkerPlatform *platform = reinterpret_cast<WindowsWorkerPlatform *>(payload);
  platform->handle_commands();
}

static void CALLBACK event_helper(DWORD error_code, DWORD num_bytes, LPOVERLAPPED overlapped)
{
  Subscription *sub = static_cast<Subscription *>(overlapped->hEvent);
  Result<> r = sub->get_platform()->handle_fs_event(error_code, num_bytes, sub);
  if (r.is_error()) {
    LOGGER << "Unable to handle filesystem events: " << r << "." << endl;
  }
}
<commit_msg>Configure the cache size on Windows<commit_after>#define WIN32_LEAN_AND_MEAN

#include <iostream>
#include <map>
#include <memory>
#include <sstream>
#include <string>
#include <utility>
#include <uv.h>
#include <vector>
#include <windows.h>

#include "../../helper/windows/helper.h"
#include "../../lock.h"
#include "../../log.h"
#include "../../message.h"
#include "../../message_buffer.h"
#include "../recent_file_cache.h"
#include "../worker_platform.h"
#include "../worker_thread.h"
#include "subscription.h"

using std::default_delete;
using std::endl;
using std::make_pair;
using std::map;
using std::move;
using std::ostream;
using std::ostringstream;
using std::pair;
using std::shared_ptr;
using std::string;
using std::unique_ptr;
using std::vector;
using std::wostringstream;
using std::wstring;

const size_t DEFAULT_CACHE_SIZE = 4096;

const size_t DEFAULT_CACHE_PREPOPULATION = 1024;

void CALLBACK command_perform_helper(__in ULONG_PTR payload);

void CALLBACK event_helper(DWORD error_code, DWORD num_bytes, LPOVERLAPPED overlapped);

class WindowsWorkerPlatform : public WorkerPlatform
{
public:
  WindowsWorkerPlatform(WorkerThread *thread) : WorkerPlatform(thread), thread_handle{0}, cache{DEFAULT_CACHE_SIZE}
  {
    int err;

    err = uv_mutex_init(&thread_handle_mutex);
    if (err) {
      report_uv_error(err);
    }
    freeze();
  };

  ~WindowsWorkerPlatform() override { uv_mutex_destroy(&thread_handle_mutex); }

  Result<> wake() override
  {
    Lock lock(thread_handle_mutex);

    if (!thread_handle) {
      return ok_result();
    }

    BOOL success = QueueUserAPC(command_perform_helper, thread_handle, reinterpret_cast<ULONG_PTR>(this));
    if (!success) {
      return windows_error_result<>("Unable to queue APC");
    }

    return ok_result();
  }

  Result<> listen() override
  {
    {
      Lock lock(thread_handle_mutex);

      HANDLE pseudo_handle = GetCurrentThread();
      BOOL success = DuplicateHandle(GetCurrentProcess(),  // Source process
        pseudo_handle,  // Source handle
        GetCurrentProcess(),  // Destination process
        &thread_handle,  // Destination handle
        0,  // Desired access
        FALSE,  // Inheritable by new processes
        DUPLICATE_SAME_ACCESS  // options
      );
      if (!success) {
        return windows_error_result<>("Unable to duplicate thread handle");
      }
    }

    while (true) {
      SleepEx(INFINITE, true);
    }

    return error_result("listen loop ended unexpectedly");
  }

  Result<bool> handle_add_command(CommandID command,
    ChannelID channel,
    const string &root_path,
    bool recursive) override
  {
    // Convert the path to a wide-character string
    Result<wstring> convr = to_wchar(root_path);
    if (convr.is_error()) return convr.propagate<bool>();
    wstring &root_path_w = convr.get_value();

    // Open a directory handle
    HANDLE root = CreateFileW(root_path_w.c_str(),  // null-terminated wchar file name
      FILE_LIST_DIRECTORY,  // desired access
      FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,  // share mode
      NULL,  // security attributes
      OPEN_EXISTING,  // creation disposition
      FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,  // flags and attributes
      NULL  // template file
    );
    if (root == INVALID_HANDLE_VALUE) {
      return windows_error_result<bool>("Unable to open directory handle");
    }

    // Allocate and persist the subscription
    Subscription *sub = new Subscription(channel, root, root_path_w, recursive, this);
    auto insert_result = subscriptions.insert(make_pair(channel, sub));
    if (!insert_result.second) {
      delete sub;

      ostringstream msg("Channel collision: ");
      msg << channel;
      return Result<bool>::make_error(msg.str());
    }

    ostream &logline = LOGGER << "Added directory root " << root_path;
    if (!recursive) logline << " (non-recursive)";
    logline << " at channel " << channel << "." << endl;

    Result<bool> schedr = sub->schedule(&event_helper);
    if (schedr.is_error()) return schedr.propagate<bool>();
    if (!schedr.get_value()) {
      LOGGER << "Falling back to polling for watch root " << root_path << "." << endl;

      return emit(Message(CommandPayloadBuilder::add(channel, string(root_path), recursive, 1).build()))
        .propagate(false);
    }

    cache.prepopulate(root_path, DEFAULT_CACHE_PREPOPULATION);

    return ok_result(true);
  }

  Result<bool> handle_remove_command(CommandID command, ChannelID channel) override
  {
    auto it = subscriptions.find(channel);
    if (it == subscriptions.end()) {
      LOGGER << "Channel " << channel << " was already removed." << endl;
      return ok_result(true);
    }

    Result<> r = it->second->stop(command);
    if (r.is_error()) return r.propagate<bool>();

    LOGGER << "Subscription for channel " << channel << " stopped." << endl;
    return ok_result(false);
  }

  void handle_cache_size_command(size_t cache_size) override
  {
    LOGGER << "Changing cache size to " << cache_size << "." << endl;
    cache.resize(cache_size);
  }

  Result<> handle_fs_event(DWORD error_code, DWORD num_bytes, Subscription *sub)
  {
    // Ensure that the subscription is valid.
    ChannelID channel = sub->get_channel();
    auto it = subscriptions.find(channel);
    if (it == subscriptions.end() || it->second != sub) {
      return ok_result();
    }

    // Subscription termination.
    bool terminate = false;
    if (error_code == ERROR_OPERATION_ABORTED) {
      LOGGER << "Completing termination of channel " << channel << "." << endl;
      terminate = true;
    } else if (sub->is_terminating()) {
      LOGGER << "Filesystem event encountered on terminating channel " << channel << "." << endl;
      terminate = true;
    }
    if (terminate) return remove(sub);

    // Handle errors.
    if (error_code == ERROR_INVALID_PARAMETER) {
      LOGGER << "Attempting to revert to a network-friendly buffer size." << endl;

      Result<> resize = sub->use_network_size();
      if (resize.is_error()) return emit_fatal_error(sub, move(resize));

      return reschedule(sub);
    }

    if (error_code == ERROR_NOTIFY_ENUM_DIR) {
      LOGGER << "Change buffer overflow. Some events may have been lost." << endl;
      return reschedule(sub);
    }

    if (error_code != ERROR_SUCCESS) {
      return emit_fatal_error(sub, windows_error_result<>("Completion callback error", error_code));
    }

    // Schedule the next completion callback.
    BYTE *base = sub->get_written(num_bytes);
    Result<> next = reschedule(sub);

    // Process received events.
    MessageBuffer buffer;
    ChannelMessageBuffer messages(buffer, channel);
    size_t num_events = 0;
    bool old_path_seen = false;
    string old_path;

    while (true) {
      PFILE_NOTIFY_INFORMATION info = reinterpret_cast<PFILE_NOTIFY_INFORMATION>(base);
      num_events++;

      Result<> pr = process_event_payload(info, sub, messages, old_path_seen, old_path);
      if (pr.is_error()) {
        LOGGER << "Skipping entry " << pr << "." << endl;
      }

      if (info->NextEntryOffset == 0) {
        break;
      }
      base += info->NextEntryOffset;
    }

    cache.apply();
    cache.prune();

    if (!messages.empty()) {
      Result<> er = emit_all(messages.begin(), messages.end());
      if (er.is_error()) {
        LOGGER << "Unable to emit messages: " << er << "." << endl;
      } else {
        LOGGER << "Filesystem event batch of size " << num_events << " completed. "
               << plural(messages.size(), "message") << " produced." << endl;
      }
    }

    return next.propagate_as_void();
  }

private:
  Result<> reschedule(Subscription *sub)
  {
    Result<bool> sch = sub->schedule(&event_helper);
    if (sch.is_error()) return emit_fatal_error(sub, sch.propagate_as_void());

    if (!sch.get_value()) {
      Result<string> root = sub->get_root_path();
      if (root.is_error()) return emit_fatal_error(sub, root.propagate_as_void());

      LOGGER << "Falling back to polling for path " << root.get_value() << " at channel " << sub->get_channel() << "."
             << endl;

      Result<> rem = remove(sub);
      rem &= emit(Message(
        CommandPayloadBuilder::add(sub->get_channel(), move(root.get_value()), sub->is_recursive(), 1).build()));
      return rem;
    }

    return ok_result();
  }

  Result<> remove(Subscription *sub)
  {
    Message response(AckPayload(sub->get_command_id(), sub->get_channel(), true, ""));

    // Ensure that the subscription is valid.
    ChannelID channel = sub->get_channel();
    auto it = subscriptions.find(channel);
    if (it == subscriptions.end() || it->second != sub) {
      return ok_result();
    }

    subscriptions.erase(it);
    delete sub;

    if (sub->get_command_id() != NULL_COMMAND_ID) {
      return emit(move(response));
    } else {
      return ok_result();
    }
  }

  Result<> emit_fatal_error(Subscription *sub, Result<> &&r)
  {
    assert(r.is_error());

    Result<> out = emit(Message(ErrorPayload(sub->get_channel(), string(r.get_error()), true)));
    out &= remove(sub);
    return out;
  }

  Result<> process_event_payload(PFILE_NOTIFY_INFORMATION info,
    Subscription *sub,
    ChannelMessageBuffer &messages,
    bool &old_path_seen,
    string &old_path)
  {
    ChannelID channel = sub->get_channel();
    wstring relpathw{info->FileName, info->FileNameLength / sizeof(WCHAR)};
    wstring pathw = sub->make_absolute(move(relpathw));

    Result<string> u8r = to_utf8(pathw);
    if (u8r.is_error()) {
      LOGGER << "Unable to convert path to utf-8: " << u8r << "." << endl;
      return ok_result();
    }
    string &path = u8r.get_value();

    shared_ptr<StatResult> stat;
    if (info->Action == FILE_ACTION_REMOVED || info->Action == FILE_ACTION_RENAMED_OLD_NAME) {
      stat = cache.former_at_path(path, false, false);
    } else {
      stat = cache.current_at_path(path, false, false);
      if (stat->is_absent()) {
        stat = cache.former_at_path(path, false, false);
      }
    }
    EntryKind kind = stat->get_entry_kind();

    switch (info->Action) {
      case FILE_ACTION_ADDED: messages.created(move(path), kind); break;
      case FILE_ACTION_MODIFIED: messages.modified(move(path), kind); break;
      case FILE_ACTION_REMOVED: messages.deleted(move(path), kind); break;
      case FILE_ACTION_RENAMED_OLD_NAME:
        old_path_seen = true;
        old_path = move(path);
        break;
      case FILE_ACTION_RENAMED_NEW_NAME:
        if (old_path_seen) {
          // Old name received first
          messages.renamed(move(old_path), move(path), kind);
          old_path_seen = false;
        } else {
          // No old name. Treat it as a creation
          messages.created(move(path), kind);
        }
        break;
      default:
        ostringstream out;
        out << "Unexpected action " << info->Action << " reported by ReadDirectoryChangesW for " << path;
        return error_result(out.str());
        break;
    }

    return ok_result();
  }

  uv_mutex_t thread_handle_mutex;
  HANDLE thread_handle;

  map<ChannelID, Subscription *> subscriptions;

  RecentFileCache cache;
};

unique_ptr<WorkerPlatform> WorkerPlatform::for_worker(WorkerThread *thread)
{
  return unique_ptr<WorkerPlatform>(new WindowsWorkerPlatform(thread));
}

void CALLBACK command_perform_helper(__in ULONG_PTR payload)
{
  WindowsWorkerPlatform *platform = reinterpret_cast<WindowsWorkerPlatform *>(payload);
  platform->handle_commands();
}

static void CALLBACK event_helper(DWORD error_code, DWORD num_bytes, LPOVERLAPPED overlapped)
{
  Subscription *sub = static_cast<Subscription *>(overlapped->hEvent);
  Result<> r = sub->get_platform()->handle_fs_event(error_code, num_bytes, sub);
  if (r.is_error()) {
    LOGGER << "Unable to handle filesystem events: " << r << "." << endl;
  }
}
<|endoftext|>


<commit_before>/*
 * Copyright 1999-2004 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#if !defined(STRINGTOKENIZER_HEADER_GUARD_1357924680)
#define STRINGTOKENIZER_HEADER_GUARD_1357924680

// Base include file.  Must be first.
#include <xalanc/PlatformSupport/PlatformSupportDefinitions.hpp>

#include <xalanc/XalanDOM/XalanDOMString.hpp>

#include <xalanc/PlatformSupport/DOMStringHelper.hpp>

XALAN_CPP_NAMESPACE_BEGIN

class XALAN_PLATFORMSUPPORT_EXPORT StringTokenizer
{
public:

	static const XalanDOMChar	s_defaultTokens[];

	typedef size_t	size_type;

	/**
	 * Constructs a tokenizer for the target string.  No copies of any input
	 * strings are made.
	 *
	 * @param theString     string to tokenize
	 * @param theTokens     string of delimiters used to parse target, default
	 *                      is " \t\n\r"
	 * @param fReturnTokens if true, delimiter characters are also returned
	 *                      as tokens, default is false
	 */
	StringTokenizer(const XalanDOMString&	theString,
					const XalanDOMString&	theTokens,
					bool					fReturnTokens = false);

	/**
	 * Constructs a tokenizer for the target string.  No copies of any input
	 * strings are made.
	 *
	 * @param theString     string to tokenize
	 * @param theTokens     string of delimiters used to parse target, default
	 *                      is " \t\n\r"
	 * @param fReturnTokens if true, delimiter characters are also returned
	 *                      as tokens, default is false
	 */
	StringTokenizer(const XalanDOMString&	theString,
					const XalanDOMChar*		theTokens = s_defaultTokens,
					bool					fReturnTokens = false);

	/**
	 * Constructs a tokenizer for the target string.  No copies of any input
	 * strings are made.
	 *
	 * @param theString     string to tokenize
	 * @param theTokens     string of delimiters used to parse target.
	 * @param fReturnTokens if true, delimiter characters are also returned
	 *                      as tokens, default is false
	 */
	StringTokenizer(const XalanDOMChar*		theString,
					const XalanDOMChar*		theTokens = s_defaultTokens,
					bool					fReturnTokens = false);

	/**
	 * Constructs a tokenizer for the target string.  No copies of any input
	 * strings are made.
	 *
	 * @param theString     string to tokenize
	 * @param theTokens     string of delimiters used to parse target.
	 * @param fReturnTokens if true, delimiter characters are also returned
	 *                      as tokens, default is false
	 */
	StringTokenizer(const XalanDOMChar*		theString,
					const XalanDOMString&	theTokens,
					bool					fReturnTokens = false);

	~StringTokenizer();

	/**
	 * Determine if there are tokens remaining
	 *
	 * @return true if there are more tokens
	 */
	bool
	hasMoreTokens() const;

	/**
	 * Retrieve the next token to be parsed; behavior is undefined if there are
	 * no more tokens
	 *
	 * @param theToken next token string
	 */
	void
	nextToken(XalanDOMString&	theToken);

	/**
	 * Count the number of tokens yet to be parsed
	 *
	 * @return number of remaining tokens
	 */
	size_type
	countTokens() const;

	void
	reset()
	{
		m_currentIndex = 0;
	}

protected:

	XalanDOMString::size_type
	FindNextDelimiterIndex(XalanDOMString::size_type	theStartIndex) const;

private:

	const XalanDOMChar* const			m_string;

	const XalanDOMChar*	const			m_tokens;

	const bool							m_returnTokens;

	XalanDOMString::size_type			m_currentIndex;

	const XalanDOMString::size_type		m_stringLength;

	const XalanDOMString::size_type		m_tokensLength;
};

XALAN_CPP_NAMESPACE_END

#endif	// STRINGTOKENIZER_HEADER_GUARD_1357924680
<commit_msg>Added private copy constructor and operators to silence warnings.<commit_after>/*
 * Copyright 1999-2004 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#if !defined(STRINGTOKENIZER_HEADER_GUARD_1357924680)
#define STRINGTOKENIZER_HEADER_GUARD_1357924680

// Base include file.  Must be first.
#include <xalanc/PlatformSupport/PlatformSupportDefinitions.hpp>

#include <xalanc/XalanDOM/XalanDOMString.hpp>

#include <xalanc/PlatformSupport/DOMStringHelper.hpp>

XALAN_CPP_NAMESPACE_BEGIN

class XALAN_PLATFORMSUPPORT_EXPORT StringTokenizer
{
public:

	static const XalanDOMChar	s_defaultTokens[];

	typedef size_t	size_type;

	/**
	 * Constructs a tokenizer for the target string.  No copies of any input
	 * strings are made.
	 *
	 * @param theString     string to tokenize
	 * @param theTokens     string of delimiters used to parse target, default
	 *                      is " \t\n\r"
	 * @param fReturnTokens if true, delimiter characters are also returned
	 *                      as tokens, default is false
	 */
	StringTokenizer(const XalanDOMString&	theString,
					const XalanDOMString&	theTokens,
					bool					fReturnTokens = false);

	/**
	 * Constructs a tokenizer for the target string.  No copies of any input
	 * strings are made.
	 *
	 * @param theString     string to tokenize
	 * @param theTokens     string of delimiters used to parse target, default
	 *                      is " \t\n\r"
	 * @param fReturnTokens if true, delimiter characters are also returned
	 *                      as tokens, default is false
	 */
	StringTokenizer(const XalanDOMString&	theString,
					const XalanDOMChar*		theTokens = s_defaultTokens,
					bool					fReturnTokens = false);

	/**
	 * Constructs a tokenizer for the target string.  No copies of any input
	 * strings are made.
	 *
	 * @param theString     string to tokenize
	 * @param theTokens     string of delimiters used to parse target.
	 * @param fReturnTokens if true, delimiter characters are also returned
	 *                      as tokens, default is false
	 */
	StringTokenizer(const XalanDOMChar*		theString,
					const XalanDOMChar*		theTokens = s_defaultTokens,
					bool					fReturnTokens = false);

	/**
	 * Constructs a tokenizer for the target string.  No copies of any input
	 * strings are made.
	 *
	 * @param theString     string to tokenize
	 * @param theTokens     string of delimiters used to parse target.
	 * @param fReturnTokens if true, delimiter characters are also returned
	 *                      as tokens, default is false
	 */
	StringTokenizer(const XalanDOMChar*		theString,
					const XalanDOMString&	theTokens,
					bool					fReturnTokens = false);

	~StringTokenizer();

	/**
	 * Determine if there are tokens remaining
	 *
	 * @return true if there are more tokens
	 */
	bool
	hasMoreTokens() const;

	/**
	 * Retrieve the next token to be parsed; behavior is undefined if there are
	 * no more tokens
	 *
	 * @param theToken next token string
	 */
	void
	nextToken(XalanDOMString&	theToken);

	/**
	 * Count the number of tokens yet to be parsed
	 *
	 * @return number of remaining tokens
	 */
	size_type
	countTokens() const;

	void
	reset()
	{
		m_currentIndex = 0;
	}

protected:

	XalanDOMString::size_type
	FindNextDelimiterIndex(XalanDOMString::size_type	theStartIndex) const;

private:

    // These are not implemented...
    StringTokenizer(const StringTokenizer&);

    StringTokenizer&
    operator=(const StringTokenizer&);

    bool
    operator==(const StringTokenizer&) const;

    // Data members...
    const XalanDOMChar* const			m_string;

	const XalanDOMChar*	const			m_tokens;

	const bool							m_returnTokens;

	XalanDOMString::size_type			m_currentIndex;

	const XalanDOMString::size_type		m_stringLength;

	const XalanDOMString::size_type		m_tokensLength;
};

XALAN_CPP_NAMESPACE_END

#endif	// STRINGTOKENIZER_HEADER_GUARD_1357924680
<|endoftext|>


<commit_before>#ifndef STAN_MATH_PRIM_SCAL_FUN_GRAD_REG_INC_GAMMA_HPP
#define STAN_MATH_PRIM_SCAL_FUN_GRAD_REG_INC_GAMMA_HPP

#include <stan/math/prim/scal/meta/return_type.hpp>
#include <stan/math/prim/scal/err/domain_error.hpp>
#include <stan/math/prim/scal/fun/gamma_p.hpp>
#include <stan/math/prim/scal/fun/gamma_q.hpp>
#include <stan/math/prim/scal/fun/is_inf.hpp>
#include <stan/math/prim/scal/fun/is_nan.hpp>
#include <stan/math/prim/scal/fun/square.hpp>
#include <cmath>
#include <limits>

namespace stan {
namespace math {

/**
 * Gradient of the regularized incomplete gamma functions igamma(a, z)
 *
 * For small z, the gradient is computed via the series expansion;
 * for large z, the series is numerically inaccurate due to cancellation
 * and the asymptotic expansion is used.
 *
 * @param a   shape parameter, a > 0
 * @param z   location z >= 0
 * @param g   boost::math::tgamma(a) (precomputed value)
 * @param dig boost::math::digamma(a) (precomputed value)
 * @param precision required precision; applies to series expansion only
 * @param max_steps number of steps to take.
 * @throw throws std::domain_error if not converged after max_steps
 *   or increment overflows to inf.
 *
 * For the asymptotic expansion, the gradient is given by:
   \f[
   \begin{array}{rcl}
   \Gamma(a, z) & = & z^{a-1}e^{-z} \sum_{k=0}^N \frac{(a-1)_k}{z^k} \qquad , z
 \gg a\\
   Q(a, z) & = & \frac{z^{a-1}e^{-z}}{\Gamma(a)} \sum_{k=0}^N
 \frac{(a-1)_k}{z^k}\\
   (a)_k & = & (a)_{k-1}(a-k)\\
   \frac{d}{da} (a)_k & = & (a)_{k-1} + (a-k)\frac{d}{da} (a)_{k-1}\\
   \frac{d}{da}Q(a, z) & = & (log(z) - \psi(a)) Q(a, z)\\
   && + \frac{z^{a-1}e^{-z}}{\Gamma(a)} \sum_{k=0}^N \left(\frac{d}{da}
 (a-1)_k\right) \frac{1}{z^k} \end{array} \f]
 */
template <typename T1, typename T2>
typename return_type<T1, T2>::type grad_reg_inc_gamma(
    T1 a, T2 z, T1 g, T1 dig, double precision = 1e-6, int max_steps = 1e5) {
  using std::exp;
  using std::fabs;
  using std::log;
  typedef typename return_type<T1, T2>::type TP;

  if (is_nan(a) || is_nan(z) || is_nan(g) || is_nan(dig))
    return std::numeric_limits<TP>::quiet_NaN();

  T2 l = log(z);
  if (z >= a && z >= 8) {
    // asymptotic expansion http://dlmf.nist.gov/8.11#E2
    TP S = 0;
    T1 a_minus_one_minus_k = a - 1;
    T1 fac = a_minus_one_minus_k;  // falling_factorial(a-1, k)
    T1 dfac = 1;                   // d/da[falling_factorial(a-1, k)]
    T2 zpow = z;                   // z ** k
    TP delta = dfac / zpow;

    for (int k = 1; k < 10; ++k) {
      a_minus_one_minus_k -= 1;

      S += delta;

      zpow *= z;
      dfac = a_minus_one_minus_k * dfac + fac;
      fac *= a_minus_one_minus_k;
      delta = dfac / zpow;

      if (is_inf(delta))
        domain_error("grad_reg_inc_gamma", "is not converging", "", "");
    }

    return gamma_q(a, z) * (l - dig) + exp(-z + (a - 1) * l) * S / g;
  } else {
    // gradient of series expansion http://dlmf.nist.gov/8.7#E3
    TP S = 0;
    TP log_s = 0.0;
    double s_sign = 1.0;
    T2 log_z = log(z);
    TP log_delta = log_s - 2 * log(a);
    for (int k = 1; k <= max_steps; ++k) {
      S += s_sign >= 0.0 ? exp(log_delta) : -exp(log_delta);
      log_s += log_z - log(k);
      s_sign = -s_sign;
      log_delta = log_s - 2 * log(k + a);
      if (is_inf(log_delta))
        domain_error("grad_reg_inc_gamma", "is not converging", "", "");
      if (log_delta <= log(precision))
        return gamma_p(a, z) * (dig - l) + exp(a * l) * S / g;
    }
    domain_error("grad_reg_inc_gamma", "k (internal counter)",
                 max_steps, "exceeded ",
                 " iterations, gamma function gradient did not converge.");
    return std::numeric_limits<TP>::infinity();
  }
}

}  // namespace math
}  // namespace stan
#endif
<commit_msg>[Jenkins] auto-formatting by clang-format version 6.0.0 (tags/google/stable/2017-11-14)<commit_after>#ifndef STAN_MATH_PRIM_SCAL_FUN_GRAD_REG_INC_GAMMA_HPP
#define STAN_MATH_PRIM_SCAL_FUN_GRAD_REG_INC_GAMMA_HPP

#include <stan/math/prim/scal/meta/return_type.hpp>
#include <stan/math/prim/scal/err/domain_error.hpp>
#include <stan/math/prim/scal/fun/gamma_p.hpp>
#include <stan/math/prim/scal/fun/gamma_q.hpp>
#include <stan/math/prim/scal/fun/is_inf.hpp>
#include <stan/math/prim/scal/fun/is_nan.hpp>
#include <stan/math/prim/scal/fun/square.hpp>
#include <cmath>
#include <limits>

namespace stan {
namespace math {

/**
 * Gradient of the regularized incomplete gamma functions igamma(a, z)
 *
 * For small z, the gradient is computed via the series expansion;
 * for large z, the series is numerically inaccurate due to cancellation
 * and the asymptotic expansion is used.
 *
 * @param a   shape parameter, a > 0
 * @param z   location z >= 0
 * @param g   boost::math::tgamma(a) (precomputed value)
 * @param dig boost::math::digamma(a) (precomputed value)
 * @param precision required precision; applies to series expansion only
 * @param max_steps number of steps to take.
 * @throw throws std::domain_error if not converged after max_steps
 *   or increment overflows to inf.
 *
 * For the asymptotic expansion, the gradient is given by:
   \f[
   \begin{array}{rcl}
   \Gamma(a, z) & = & z^{a-1}e^{-z} \sum_{k=0}^N \frac{(a-1)_k}{z^k} \qquad , z
 \gg a\\
   Q(a, z) & = & \frac{z^{a-1}e^{-z}}{\Gamma(a)} \sum_{k=0}^N
 \frac{(a-1)_k}{z^k}\\
   (a)_k & = & (a)_{k-1}(a-k)\\
   \frac{d}{da} (a)_k & = & (a)_{k-1} + (a-k)\frac{d}{da} (a)_{k-1}\\
   \frac{d}{da}Q(a, z) & = & (log(z) - \psi(a)) Q(a, z)\\
   && + \frac{z^{a-1}e^{-z}}{\Gamma(a)} \sum_{k=0}^N \left(\frac{d}{da}
 (a-1)_k\right) \frac{1}{z^k} \end{array} \f]
 */
template <typename T1, typename T2>
typename return_type<T1, T2>::type grad_reg_inc_gamma(T1 a, T2 z, T1 g, T1 dig,
                                                      double precision = 1e-6,
                                                      int max_steps = 1e5) {
  using std::exp;
  using std::fabs;
  using std::log;
  typedef typename return_type<T1, T2>::type TP;

  if (is_nan(a) || is_nan(z) || is_nan(g) || is_nan(dig))
    return std::numeric_limits<TP>::quiet_NaN();

  T2 l = log(z);
  if (z >= a && z >= 8) {
    // asymptotic expansion http://dlmf.nist.gov/8.11#E2
    TP S = 0;
    T1 a_minus_one_minus_k = a - 1;
    T1 fac = a_minus_one_minus_k;  // falling_factorial(a-1, k)
    T1 dfac = 1;                   // d/da[falling_factorial(a-1, k)]
    T2 zpow = z;                   // z ** k
    TP delta = dfac / zpow;

    for (int k = 1; k < 10; ++k) {
      a_minus_one_minus_k -= 1;

      S += delta;

      zpow *= z;
      dfac = a_minus_one_minus_k * dfac + fac;
      fac *= a_minus_one_minus_k;
      delta = dfac / zpow;

      if (is_inf(delta))
        domain_error("grad_reg_inc_gamma", "is not converging", "", "");
    }

    return gamma_q(a, z) * (l - dig) + exp(-z + (a - 1) * l) * S / g;
  } else {
    // gradient of series expansion http://dlmf.nist.gov/8.7#E3
    TP S = 0;
    TP log_s = 0.0;
    double s_sign = 1.0;
    T2 log_z = log(z);
    TP log_delta = log_s - 2 * log(a);
    for (int k = 1; k <= max_steps; ++k) {
      S += s_sign >= 0.0 ? exp(log_delta) : -exp(log_delta);
      log_s += log_z - log(k);
      s_sign = -s_sign;
      log_delta = log_s - 2 * log(k + a);
      if (is_inf(log_delta))
        domain_error("grad_reg_inc_gamma", "is not converging", "", "");
      if (log_delta <= log(precision))
        return gamma_p(a, z) * (dig - l) + exp(a * l) * S / g;
    }
    domain_error("grad_reg_inc_gamma", "k (internal counter)", max_steps,
                 "exceeded ",
                 " iterations, gamma function gradient did not converge.");
    return std::numeric_limits<TP>::infinity();
  }
}

}  // namespace math
}  // namespace stan
#endif
<|endoftext|>


<commit_before>/* -*-  mode: c++; c-default-style: "google"; indent-tabs-mode: nil -*- */

/* -------------------------------------------------------------------------
   ATS

   License: see $ATS_DIR/COPYRIGHT
   Author: Ethan Coon

   Default base with default implementations of methods for a physical PK.
   ------------------------------------------------------------------------- */
#include "pk_physical_base.hh"

namespace Amanzi {

PKPhysicalBase::PKPhysicalBase(const Teuchos::RCP<Teuchos::ParameterList>& plist,
        Teuchos::ParameterList& FElist,
        const Teuchos::RCP<TreeVector>& solution) :
    PKDefaultBase(plist,FElist,solution) {
  // process the PList
  // domain
  if (domain_ == std::string("")) {
    domain_ = plist_->get<std::string>("domain name", std::string("domain"));
  }
  if (key_ == std::string("")) {
    key_ = plist_->get<std::string>("primary variable");
  }

  // derive the prefix
  if (domain_ == std::string("domain")) {
    domain_prefix_ = std::string("");
  } else {
    domain_prefix_ = domain_ + std::string("_");
  }

  // set up the primary variable solution, and its evaluator
  Teuchos::ParameterList& pv_sublist = FElist.sublist(key_);
  pv_sublist.set("evaluator name", key_);
  pv_sublist.set("field evaluator type", "primary variable");
}

// -----------------------------------------------------------------------------
// Construction of data.
// -----------------------------------------------------------------------------
void PKPhysicalBase::setup(const Teuchos::Ptr<State>& S) {
  PKDefaultBase::setup(S);

  // get the mesh
  mesh_ = S->GetMesh(domain_);

  // set up the debugger
  db_ = Teuchos::rcp(new Debugger(mesh_, name_, *plist_));

  // require primary variable evaluator
  S->RequireFieldEvaluator(key_);
  Teuchos::RCP<FieldEvaluator> fm = S->GetFieldEvaluator(key_);
#if ENABLE_DBC
  solution_evaluator_ = Teuchos::rcp_dynamic_cast<PrimaryVariableFieldEvaluator>(fm);
  ASSERT(solution_evaluator_ != Teuchos::null);
#else
  solution_evaluator_ = Teuchos::rcp_static_cast<PrimaryVariableFieldEvaluator>(fm);
#endif
};

// -----------------------------------------------------------------------------
// Transfer operators -- ONLY COPIES POINTERS
// -----------------------------------------------------------------------------
void PKPhysicalBase::state_to_solution(const Teuchos::RCP<State>& S,
        const Teuchos::RCP<TreeVector>& solution) {
  solution->SetData(S->GetFieldData(key_, name_));
};

// -----------------------------------------------------------------------------
// Transfer operators -- ONLY COPIES POINTERS
// -----------------------------------------------------------------------------
void PKPhysicalBase::solution_to_state(const Teuchos::RCP<TreeVector>& solution,
        const Teuchos::RCP<State>& S) {
  ASSERT(solution->Data() == S->GetFieldData(key_));
  //  S->SetData(key_, name_, solution->Data());
  //  solution_evaluator_->SetFieldAsChanged();
};

// -----------------------------------------------------------------------------
// Experimental approach -- we must pull out S_next_'s solution_evaluator_ to
// stay current for changed_solution()
// -----------------------------------------------------------------------------
void PKPhysicalBase::set_states(const Teuchos::RCP<const State>& S,
        const Teuchos::RCP<State>& S_inter,
        const Teuchos::RCP<State>& S_next) {
  PKDefaultBase::set_states(S, S_inter, S_next);

  // Get the FE and mark it as changed.
  // Note that this is necessary because we need this to point at the
  // FE in S_next_, not the one which we created in S_.
  Teuchos::RCP<FieldEvaluator> fm = S_next->GetFieldEvaluator(key_);
#if ENABLE_DBC
  solution_evaluator_ = Teuchos::rcp_dynamic_cast<PrimaryVariableFieldEvaluator>(fm);
  ASSERT(solution_evaluator_ != Teuchos::null);
#else
  solution_evaluator_ = Teuchos::rcp_static_cast<PrimaryVariableFieldEvaluator>(fm);
#endif

  solution_evaluator_->SetFieldAsChanged(S_next_.ptr());
};

// -----------------------------------------------------------------------------
// Initialization of the PK data.
// -----------------------------------------------------------------------------
void PKPhysicalBase::initialize(const Teuchos::Ptr<State>& S) {
  Teuchos::RCP<Field> field = S->GetField(key_, name_);

  if (!field->initialized()) {
    // initial conditions
    // -- Get the IC function plist.
    if (!plist_->isSublist("initial condition")) {
      std::stringstream messagestream;
      messagestream << name_ << " has no initial condition parameter list.";
      Errors::Message message(messagestream.str());
      Exceptions::amanzi_throw(message);
    }

    // -- Calculate the IC.
    Teuchos::ParameterList ic_plist = plist_->sublist("initial condition");
    field->Initialize(ic_plist);

    // -- Update faces from cells if needed.
    if (ic_plist.get<bool>("initialize faces from cells", false)) {
      DeriveFaceValuesFromCellValues_(field->GetFieldData().ptr());
    }

    // communicate just to make sure values are initialized for valgrind's sake
    field->GetFieldData()->ScatterMasterToGhosted();
    solution_evaluator_->SetFieldAsChanged(S);
  }

  // -- Push the data into the solution.
  solution_->SetData(field->GetFieldData());
};

// -----------------------------------------------------------------------------
// Interpolate pressure ICs on cells to ICs for lambda (faces).
// -----------------------------------------------------------------------------
void PKPhysicalBase::DeriveFaceValuesFromCellValues_(const Teuchos::Ptr<CompositeVector>& cv) {
  cv->ScatterMasterToGhosted("cell");
  Teuchos::Ptr<const CompositeVector> cv_const(cv);
  const Epetra_MultiVector& cv_c = *cv_const->ViewComponent("cell",true);
  Epetra_MultiVector& cv_f = *cv->ViewComponent("face",false);

  int f_owned = cv_f.MyLength();
  for (int f=0; f!=f_owned; ++f) {
    AmanziMesh::Entity_ID_List cells;
    cv->Mesh()->face_get_cells(f, AmanziMesh::USED, &cells);
    int ncells = cells.size();

    double face_value = 0.0;
    for (int n=0; n!=ncells; ++n) {
      face_value += cv_c[0][cells[n]];
    }
    cv_f[0][f] = face_value / ncells;
  }
};

} // namespace
<commit_msg>remove deriving face values from cell values as that should now be handled by Amanzi Field_CV<commit_after>/* -*-  mode: c++; c-default-style: "google"; indent-tabs-mode: nil -*- */

/* -------------------------------------------------------------------------
   ATS

   License: see $ATS_DIR/COPYRIGHT
   Author: Ethan Coon

   Default base with default implementations of methods for a physical PK.
   ------------------------------------------------------------------------- */
#include "pk_physical_base.hh"

namespace Amanzi {

PKPhysicalBase::PKPhysicalBase(const Teuchos::RCP<Teuchos::ParameterList>& plist,
        Teuchos::ParameterList& FElist,
        const Teuchos::RCP<TreeVector>& solution) :
    PKDefaultBase(plist,FElist,solution) {
  // process the PList
  // domain
  if (domain_ == std::string("")) {
    domain_ = plist_->get<std::string>("domain name", std::string("domain"));
  }
  if (key_ == std::string("")) {
    key_ = plist_->get<std::string>("primary variable");
  }

  // derive the prefix
  if (domain_ == std::string("domain")) {
    domain_prefix_ = std::string("");
  } else {
    domain_prefix_ = domain_ + std::string("_");
  }

  // set up the primary variable solution, and its evaluator
  Teuchos::ParameterList& pv_sublist = FElist.sublist(key_);
  pv_sublist.set("evaluator name", key_);
  pv_sublist.set("field evaluator type", "primary variable");
}

// -----------------------------------------------------------------------------
// Construction of data.
// -----------------------------------------------------------------------------
void PKPhysicalBase::setup(const Teuchos::Ptr<State>& S) {
  PKDefaultBase::setup(S);

  // get the mesh
  mesh_ = S->GetMesh(domain_);

  // set up the debugger
  db_ = Teuchos::rcp(new Debugger(mesh_, name_, *plist_));

  // require primary variable evaluator
  S->RequireFieldEvaluator(key_);
  Teuchos::RCP<FieldEvaluator> fm = S->GetFieldEvaluator(key_);
#if ENABLE_DBC
  solution_evaluator_ = Teuchos::rcp_dynamic_cast<PrimaryVariableFieldEvaluator>(fm);
  ASSERT(solution_evaluator_ != Teuchos::null);
#else
  solution_evaluator_ = Teuchos::rcp_static_cast<PrimaryVariableFieldEvaluator>(fm);
#endif
};

// -----------------------------------------------------------------------------
// Transfer operators -- ONLY COPIES POINTERS
// -----------------------------------------------------------------------------
void PKPhysicalBase::state_to_solution(const Teuchos::RCP<State>& S,
        const Teuchos::RCP<TreeVector>& solution) {
  solution->SetData(S->GetFieldData(key_, name_));
};

// -----------------------------------------------------------------------------
// Transfer operators -- ONLY COPIES POINTERS
// -----------------------------------------------------------------------------
void PKPhysicalBase::solution_to_state(const Teuchos::RCP<TreeVector>& solution,
        const Teuchos::RCP<State>& S) {
  ASSERT(solution->Data() == S->GetFieldData(key_));
  //  S->SetData(key_, name_, solution->Data());
  //  solution_evaluator_->SetFieldAsChanged();
};

// -----------------------------------------------------------------------------
// Experimental approach -- we must pull out S_next_'s solution_evaluator_ to
// stay current for changed_solution()
// -----------------------------------------------------------------------------
void PKPhysicalBase::set_states(const Teuchos::RCP<const State>& S,
        const Teuchos::RCP<State>& S_inter,
        const Teuchos::RCP<State>& S_next) {
  PKDefaultBase::set_states(S, S_inter, S_next);

  // Get the FE and mark it as changed.
  // Note that this is necessary because we need this to point at the
  // FE in S_next_, not the one which we created in S_.
  Teuchos::RCP<FieldEvaluator> fm = S_next->GetFieldEvaluator(key_);
#if ENABLE_DBC
  solution_evaluator_ = Teuchos::rcp_dynamic_cast<PrimaryVariableFieldEvaluator>(fm);
  ASSERT(solution_evaluator_ != Teuchos::null);
#else
  solution_evaluator_ = Teuchos::rcp_static_cast<PrimaryVariableFieldEvaluator>(fm);
#endif

  solution_evaluator_->SetFieldAsChanged(S_next_.ptr());
};

// -----------------------------------------------------------------------------
// Initialization of the PK data.
// -----------------------------------------------------------------------------
void PKPhysicalBase::initialize(const Teuchos::Ptr<State>& S) {
  Teuchos::RCP<Field> field = S->GetField(key_, name_);

  if (!field->initialized()) {
    // initial conditions
    // -- Get the IC function plist.
    if (!plist_->isSublist("initial condition")) {
      std::stringstream messagestream;
      messagestream << name_ << " has no initial condition parameter list.";
      Errors::Message message(messagestream.str());
      Exceptions::amanzi_throw(message);
    }

    // -- Calculate the IC.
    Teuchos::ParameterList ic_plist = plist_->sublist("initial condition");
    field->Initialize(ic_plist);

    // -- Update faces from cells if needed.
    // if (ic_plist.get<bool>("initialize faces from cells", false)) {
    //   DeriveFaceValuesFromCellValues_(field->GetFieldData().ptr());
    // }

    // communicate just to make sure values are initialized for valgrind's sake
    field->GetFieldData()->ScatterMasterToGhosted();
    solution_evaluator_->SetFieldAsChanged(S);
  }

  // -- Push the data into the solution.
  solution_->SetData(field->GetFieldData());
};

// -----------------------------------------------------------------------------
// Interpolate pressure ICs on cells to ICs for lambda (faces).
// -----------------------------------------------------------------------------
void PKPhysicalBase::DeriveFaceValuesFromCellValues_(const Teuchos::Ptr<CompositeVector>& cv) {
  cv->ScatterMasterToGhosted("cell");
  Teuchos::Ptr<const CompositeVector> cv_const(cv);
  const Epetra_MultiVector& cv_c = *cv_const->ViewComponent("cell",true);
  Epetra_MultiVector& cv_f = *cv->ViewComponent("face",false);

  int f_owned = cv_f.MyLength();
  for (int f=0; f!=f_owned; ++f) {
    AmanziMesh::Entity_ID_List cells;
    cv->Mesh()->face_get_cells(f, AmanziMesh::USED, &cells);
    int ncells = cells.size();

    double face_value = 0.0;
    for (int n=0; n!=ncells; ++n) {
      face_value += cv_c[0][cells[n]];
    }
    cv_f[0][f] = face_value / ncells;
  }
};

} // namespace
<|endoftext|>