<commit_before>/*
 *    Copyright (c) 2017, The OpenThread Authors.
 *    All rights reserved.
 *
 *    Redistribution and use in source and binary forms, with or without
 *    modification, are permitted provided that the following conditions are met:
 *    1. Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *    2. Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *    3. Neither the name of the copyright holder nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 *    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 *    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 *    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *    POSSIBILITY OF SUCH DAMAGE.
 */

#include <openthread-br/config.h>

#include <fstream>
#include <mutex>
#include <sstream>
#include <thread>

#include <errno.h>
#include <getopt.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <assert.h>
#include <openthread/logging.h>
#include <openthread/platform/radio.h>

#include "agent/agent_instance.hpp"
#include "common/code_utils.hpp"
#include "common/logging.hpp"
#include "common/mainloop.hpp"
#include "common/types.hpp"
#include "ncp/ncp_openthread.hpp"
#if OTBR_ENABLE_REST_SERVER
#include "rest/rest_web_server.hpp"
using otbr::rest::RestWebServer;
#endif
#if OTBR_ENABLE_DBUS_SERVER
#include "dbus/server/dbus_agent.hpp"
using otbr::DBus::DBusAgent;
#endif
using otbr::Ncp::ControllerOpenThread;

#if OTBR_ENABLE_OPENWRT
extern void       UbusUpdateFdSet(fd_set &aReadFdSet, int &aMaxFd);
extern void       UbusProcess(const fd_set &aReadFdSet);
extern void       UbusServerRun(void);
extern void       UbusServerInit(otbr::Ncp::ControllerOpenThread *aController, std::mutex *aNcpThreadMutex);
static std::mutex sThreadMutex;
#endif

static const char kSyslogIdent[]          = "otbr-agent";
static const char kDefaultInterfaceName[] = "wpan0";

enum
{
    OTBR_OPT_BACKBONE_INTERFACE_NAME = 'B',
    OTBR_OPT_DEBUG_LEVEL             = 'd',
    OTBR_OPT_HELP                    = 'h',
    OTBR_OPT_INTERFACE_NAME          = 'I',
    OTBR_OPT_VERBOSE                 = 'v',
    OTBR_OPT_VERSION                 = 'V',
    OTBR_OPT_SHORTMAX                = 128,
    OTBR_OPT_RADIO_VERSION,
};

static jmp_buf sResetJump;
static bool    sShouldTerminate = false;

void __gcov_flush();

// Default poll timeout.
static const struct timeval kPollTimeout = {10, 0};
static const struct option  kOptions[]   = {
    {"backbone-ifname", required_argument, nullptr, OTBR_OPT_BACKBONE_INTERFACE_NAME},
    {"debug-level", required_argument, nullptr, OTBR_OPT_DEBUG_LEVEL},
    {"help", no_argument, nullptr, OTBR_OPT_HELP},
    {"thread-ifname", required_argument, nullptr, OTBR_OPT_INTERFACE_NAME},
    {"verbose", no_argument, nullptr, OTBR_OPT_VERBOSE},
    {"version", no_argument, nullptr, OTBR_OPT_VERSION},
    {"radio-version", no_argument, nullptr, OTBR_OPT_RADIO_VERSION},
    {0, 0, 0, 0}};

static void HandleSignal(int aSignal)
{
    sShouldTerminate = true;
    signal(aSignal, SIG_DFL);
}

static int Mainloop(otbr::AgentInstance &aInstance, const char *aInterfaceName)
{
    int                   error         = EXIT_SUCCESS;
    ControllerOpenThread &ncpOpenThread = static_cast<ControllerOpenThread &>(aInstance.GetNcp());

    OT_UNUSED_VARIABLE(ncpOpenThread);

#if OTBR_ENABLE_DBUS_SERVER
    std::unique_ptr<DBusAgent> dbusAgent = std::unique_ptr<DBusAgent>(new DBusAgent(aInterfaceName, &ncpOpenThread));
    dbusAgent->Init();
#else
    OTBR_UNUSED_VARIABLE(aInterfaceName);
#endif
#if OTBR_ENABLE_REST_SERVER
    RestWebServer *restServer = RestWebServer::GetRestWebServer(&ncpOpenThread);
    restServer->Init();
#endif
    otbrLogInfo("Border router agent started.");
    // allow quitting elegantly
    signal(SIGTERM, HandleSignal);

    while (!sShouldTerminate)
    {
        otbr::MainloopContext mainloop;
        int                   rval;

        mainloop.mMaxFd   = -1;
        mainloop.mTimeout = kPollTimeout;

        FD_ZERO(&mainloop.mReadFdSet);
        FD_ZERO(&mainloop.mWriteFdSet);
        FD_ZERO(&mainloop.mErrorFdSet);

        aInstance.Update(mainloop);

#if OTBR_ENABLE_DBUS_SERVER
        dbusAgent->Update(mainloop);
#endif

#if OTBR_ENABLE_REST_SERVER
        restServer->Update(mainloop);
#endif

#if OTBR_ENABLE_OPENWRT
        UbusUpdateFdSet(mainloop.mReadFdSet, mainloop.mMaxFd);
        sThreadMutex.unlock();
#endif

        rval = select(mainloop.mMaxFd + 1, &mainloop.mReadFdSet, &mainloop.mWriteFdSet, &mainloop.mErrorFdSet,
                      &mainloop.mTimeout);

        if (rval >= 0)
        {
#if OTBR_ENABLE_OPENWRT
            sThreadMutex.lock();
            UbusProcess(mainloop.mReadFdSet);
#endif

#if OTBR_ENABLE_REST_SERVER
            restServer->Process(mainloop);
#endif

            aInstance.Process(mainloop);

#if OTBR_ENABLE_DBUS_SERVER
            dbusAgent->Process(mainloop);
#endif
        }
        else if (errno != EINTR)
        {
#if OTBR_ENABLE_OPENWRT
            sThreadMutex.lock();
#endif
            error = OTBR_ERROR_ERRNO;
            otbrLogErr("select() failed: %s", strerror(errno));
            break;
        }
    }

    return error;
}

static void PrintHelp(const char *aProgramName)
{
    fprintf(stderr, "Usage: %s [-I interfaceName] [-B backboneIfName] [-d DEBUG_LEVEL] [-v] RADIO_URL [RADIO_URL]\n",
            aProgramName);
    fprintf(stderr, "%s", otSysGetRadioUrlHelpString());
}

static void PrintVersion(void)
{
    printf("%s\n", OTBR_PACKAGE_VERSION);
}

static void PrintRadioVersion(otInstance *aInstance)
{
    printf("%s\n", otPlatRadioGetVersionString(aInstance));
}

static void OnAllocateFailed(void)
{
    otbrLogCrit("Allocate failure, exiting...");
    exit(1);
}

static int realmain(int argc, char *argv[])
{
    otbrLogLevel              logLevel = OTBR_LOG_INFO;
    int                       opt;
    int                       ret                   = EXIT_SUCCESS;
    const char *              interfaceName         = kDefaultInterfaceName;
    const char *              backboneInterfaceName = "";
    bool                      verbose               = false;
    bool                      printRadioVersion     = false;
    std::vector<const char *> radioUrls;

    std::set_new_handler(OnAllocateFailed);

    while ((opt = getopt_long(argc, argv, "B:d:hI:Vv", kOptions, nullptr)) != -1)
    {
        switch (opt)
        {
        case OTBR_OPT_BACKBONE_INTERFACE_NAME:
            backboneInterfaceName = optarg;
            break;

        case OTBR_OPT_DEBUG_LEVEL:
            logLevel = static_cast<otbrLogLevel>(atoi(optarg));
            VerifyOrExit(logLevel >= OTBR_LOG_EMERG && logLevel <= OTBR_LOG_DEBUG, ret = EXIT_FAILURE);
            break;

        case OTBR_OPT_INTERFACE_NAME:
            interfaceName = optarg;
            break;

        case OTBR_OPT_VERBOSE:
            verbose = true;
            break;

        case OTBR_OPT_VERSION:
            PrintVersion();
            ExitNow();
            break;

        case OTBR_OPT_HELP:
            PrintHelp(argv[0]);
            ExitNow(ret = EXIT_SUCCESS);
            break;

        case OTBR_OPT_RADIO_VERSION:
            printRadioVersion = true;
            break;

        default:
            PrintHelp(argv[0]);
            ExitNow(ret = EXIT_FAILURE);
            break;
        }
    }

    otbrLogInit(kSyslogIdent, logLevel, verbose);
    otbrLogInfo("Running %s", OTBR_PACKAGE_VERSION);
    otbrLogInfo("Thread version: %s", otbr::Ncp::ControllerOpenThread::GetThreadVersion());
    otbrLogInfo("Thread interface: %s", interfaceName);
    otbrLogInfo("Backbone interface: %s", backboneInterfaceName);

    for (int i = optind; i < argc; i++)
    {
        otbrLogInfo("Radio URL: %s", argv[i]);
        radioUrls.push_back(argv[i]);
    }

    {
        otbr::Ncp::ControllerOpenThread ncpOpenThread{interfaceName, radioUrls, backboneInterfaceName};
        otbr::AgentInstance             instance(ncpOpenThread);

        otbr::InstanceParams::Get().SetThreadIfName(interfaceName);
        otbr::InstanceParams::Get().SetBackboneIfName(backboneInterfaceName);

        SuccessOrExit(ret = instance.Init());

        if (printRadioVersion)
        {
            PrintRadioVersion(ncpOpenThread.GetInstance());
            ExitNow(ret = EXIT_SUCCESS);
        }

#if OTBR_ENABLE_OPENWRT
        UbusServerInit(&ncpOpenThread, &sThreadMutex);
        std::thread(UbusServerRun).detach();
#endif
        SuccessOrExit(ret = Mainloop(instance, interfaceName));
    }

    otbrLogDeinit();

exit:
    return ret;
}

void otPlatReset(otInstance *aInstance)
{
    OT_UNUSED_VARIABLE(aInstance);

    gPlatResetReason = OT_PLAT_RESET_REASON_SOFTWARE;

    otSysDeinit();

    longjmp(sResetJump, 1);
    assert(false);
}

int main(int argc, char *argv[])
{
    if (setjmp(sResetJump))
    {
        alarm(0);
#if OPENTHREAD_ENABLE_COVERAGE
        __gcov_flush();
#endif
        execvp(argv[0], argv);
    }

    return realmain(argc, argv);
}
<commit_msg>[android] set the default log level based on the properity ro.build.type (#1048)<commit_after>/*
 *    Copyright (c) 2017, The OpenThread Authors.
 *    All rights reserved.
 *
 *    Redistribution and use in source and binary forms, with or without
 *    modification, are permitted provided that the following conditions are met:
 *    1. Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *    2. Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *    3. Neither the name of the copyright holder nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 *    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 *    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 *    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *    POSSIBILITY OF SUCH DAMAGE.
 */

#include <openthread-br/config.h>

#include <fstream>
#include <mutex>
#include <sstream>
#include <thread>

#include <errno.h>
#include <getopt.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <assert.h>
#include <openthread/logging.h>
#include <openthread/platform/radio.h>

#if __ANDROID__ && OPENTHREAD_ENABLE_ANDROID_PROPERTY
#include <cutils/properties.h>
#endif

#include "agent/agent_instance.hpp"
#include "common/code_utils.hpp"
#include "common/logging.hpp"
#include "common/mainloop.hpp"
#include "common/types.hpp"
#include "ncp/ncp_openthread.hpp"
#if OTBR_ENABLE_REST_SERVER
#include "rest/rest_web_server.hpp"
using otbr::rest::RestWebServer;
#endif
#if OTBR_ENABLE_DBUS_SERVER
#include "dbus/server/dbus_agent.hpp"
using otbr::DBus::DBusAgent;
#endif
using otbr::Ncp::ControllerOpenThread;

#if OTBR_ENABLE_OPENWRT
extern void       UbusUpdateFdSet(fd_set &aReadFdSet, int &aMaxFd);
extern void       UbusProcess(const fd_set &aReadFdSet);
extern void       UbusServerRun(void);
extern void       UbusServerInit(otbr::Ncp::ControllerOpenThread *aController, std::mutex *aNcpThreadMutex);
static std::mutex sThreadMutex;
#endif

static const char kSyslogIdent[]          = "otbr-agent";
static const char kDefaultInterfaceName[] = "wpan0";

enum
{
    OTBR_OPT_BACKBONE_INTERFACE_NAME = 'B',
    OTBR_OPT_DEBUG_LEVEL             = 'd',
    OTBR_OPT_HELP                    = 'h',
    OTBR_OPT_INTERFACE_NAME          = 'I',
    OTBR_OPT_VERBOSE                 = 'v',
    OTBR_OPT_VERSION                 = 'V',
    OTBR_OPT_SHORTMAX                = 128,
    OTBR_OPT_RADIO_VERSION,
};

static jmp_buf sResetJump;
static bool    sShouldTerminate = false;

void __gcov_flush();

// Default poll timeout.
static const struct timeval kPollTimeout = {10, 0};
static const struct option  kOptions[]   = {
    {"backbone-ifname", required_argument, nullptr, OTBR_OPT_BACKBONE_INTERFACE_NAME},
    {"debug-level", required_argument, nullptr, OTBR_OPT_DEBUG_LEVEL},
    {"help", no_argument, nullptr, OTBR_OPT_HELP},
    {"thread-ifname", required_argument, nullptr, OTBR_OPT_INTERFACE_NAME},
    {"verbose", no_argument, nullptr, OTBR_OPT_VERBOSE},
    {"version", no_argument, nullptr, OTBR_OPT_VERSION},
    {"radio-version", no_argument, nullptr, OTBR_OPT_RADIO_VERSION},
    {0, 0, 0, 0}};

static void HandleSignal(int aSignal)
{
    sShouldTerminate = true;
    signal(aSignal, SIG_DFL);
}

static int Mainloop(otbr::AgentInstance &aInstance, const char *aInterfaceName)
{
    int                   error         = EXIT_SUCCESS;
    ControllerOpenThread &ncpOpenThread = static_cast<ControllerOpenThread &>(aInstance.GetNcp());

    OT_UNUSED_VARIABLE(ncpOpenThread);

#if OTBR_ENABLE_DBUS_SERVER
    std::unique_ptr<DBusAgent> dbusAgent = std::unique_ptr<DBusAgent>(new DBusAgent(aInterfaceName, &ncpOpenThread));
    dbusAgent->Init();
#else
    OTBR_UNUSED_VARIABLE(aInterfaceName);
#endif
#if OTBR_ENABLE_REST_SERVER
    RestWebServer *restServer = RestWebServer::GetRestWebServer(&ncpOpenThread);
    restServer->Init();
#endif
    otbrLogInfo("Border router agent started.");
    // allow quitting elegantly
    signal(SIGTERM, HandleSignal);

    while (!sShouldTerminate)
    {
        otbr::MainloopContext mainloop;
        int                   rval;

        mainloop.mMaxFd   = -1;
        mainloop.mTimeout = kPollTimeout;

        FD_ZERO(&mainloop.mReadFdSet);
        FD_ZERO(&mainloop.mWriteFdSet);
        FD_ZERO(&mainloop.mErrorFdSet);

        aInstance.Update(mainloop);

#if OTBR_ENABLE_DBUS_SERVER
        dbusAgent->Update(mainloop);
#endif

#if OTBR_ENABLE_REST_SERVER
        restServer->Update(mainloop);
#endif

#if OTBR_ENABLE_OPENWRT
        UbusUpdateFdSet(mainloop.mReadFdSet, mainloop.mMaxFd);
        sThreadMutex.unlock();
#endif

        rval = select(mainloop.mMaxFd + 1, &mainloop.mReadFdSet, &mainloop.mWriteFdSet, &mainloop.mErrorFdSet,
                      &mainloop.mTimeout);

        if (rval >= 0)
        {
#if OTBR_ENABLE_OPENWRT
            sThreadMutex.lock();
            UbusProcess(mainloop.mReadFdSet);
#endif

#if OTBR_ENABLE_REST_SERVER
            restServer->Process(mainloop);
#endif

            aInstance.Process(mainloop);

#if OTBR_ENABLE_DBUS_SERVER
            dbusAgent->Process(mainloop);
#endif
        }
        else if (errno != EINTR)
        {
#if OTBR_ENABLE_OPENWRT
            sThreadMutex.lock();
#endif
            error = OTBR_ERROR_ERRNO;
            otbrLogErr("select() failed: %s", strerror(errno));
            break;
        }
    }

    return error;
}

static void PrintHelp(const char *aProgramName)
{
    fprintf(stderr, "Usage: %s [-I interfaceName] [-B backboneIfName] [-d DEBUG_LEVEL] [-v] RADIO_URL [RADIO_URL]\n",
            aProgramName);
    fprintf(stderr, "%s", otSysGetRadioUrlHelpString());
}

static void PrintVersion(void)
{
    printf("%s\n", OTBR_PACKAGE_VERSION);
}

static void PrintRadioVersion(otInstance *aInstance)
{
    printf("%s\n", otPlatRadioGetVersionString(aInstance));
}

static void OnAllocateFailed(void)
{
    otbrLogCrit("Allocate failure, exiting...");
    exit(1);
}

static otbrLogLevel GetDefaultLogLevel(void)
{
    otbrLogLevel level = OTBR_LOG_INFO;

#if __ANDROID__ && OPENTHREAD_ENABLE_ANDROID_PROPERTY
    char value[PROPERTY_VALUE_MAX];

    property_get("ro.build.type", value, "user");
    if (!strcmp(value, "user"))
    {
        level = OTBR_LOG_WARNING;
    }
#endif

    return level;
}

static int realmain(int argc, char *argv[])
{
    otbrLogLevel              logLevel = GetDefaultLogLevel();
    int                       opt;
    int                       ret                   = EXIT_SUCCESS;
    const char *              interfaceName         = kDefaultInterfaceName;
    const char *              backboneInterfaceName = "";
    bool                      verbose               = false;
    bool                      printRadioVersion     = false;
    std::vector<const char *> radioUrls;

    std::set_new_handler(OnAllocateFailed);

    while ((opt = getopt_long(argc, argv, "B:d:hI:Vv", kOptions, nullptr)) != -1)
    {
        switch (opt)
        {
        case OTBR_OPT_BACKBONE_INTERFACE_NAME:
            backboneInterfaceName = optarg;
            break;

        case OTBR_OPT_DEBUG_LEVEL:
            logLevel = static_cast<otbrLogLevel>(atoi(optarg));
            VerifyOrExit(logLevel >= OTBR_LOG_EMERG && logLevel <= OTBR_LOG_DEBUG, ret = EXIT_FAILURE);
            break;

        case OTBR_OPT_INTERFACE_NAME:
            interfaceName = optarg;
            break;

        case OTBR_OPT_VERBOSE:
            verbose = true;
            break;

        case OTBR_OPT_VERSION:
            PrintVersion();
            ExitNow();
            break;

        case OTBR_OPT_HELP:
            PrintHelp(argv[0]);
            ExitNow(ret = EXIT_SUCCESS);
            break;

        case OTBR_OPT_RADIO_VERSION:
            printRadioVersion = true;
            break;

        default:
            PrintHelp(argv[0]);
            ExitNow(ret = EXIT_FAILURE);
            break;
        }
    }

    otbrLogInit(kSyslogIdent, logLevel, verbose);
    otbrLogInfo("Running %s", OTBR_PACKAGE_VERSION);
    otbrLogInfo("Thread version: %s", otbr::Ncp::ControllerOpenThread::GetThreadVersion());
    otbrLogInfo("Thread interface: %s", interfaceName);
    otbrLogInfo("Backbone interface: %s", backboneInterfaceName);

    for (int i = optind; i < argc; i++)
    {
        otbrLogInfo("Radio URL: %s", argv[i]);
        radioUrls.push_back(argv[i]);
    }

    {
        otbr::Ncp::ControllerOpenThread ncpOpenThread{interfaceName, radioUrls, backboneInterfaceName};
        otbr::AgentInstance             instance(ncpOpenThread);

        otbr::InstanceParams::Get().SetThreadIfName(interfaceName);
        otbr::InstanceParams::Get().SetBackboneIfName(backboneInterfaceName);

        SuccessOrExit(ret = instance.Init());

        if (printRadioVersion)
        {
            PrintRadioVersion(ncpOpenThread.GetInstance());
            ExitNow(ret = EXIT_SUCCESS);
        }

#if OTBR_ENABLE_OPENWRT
        UbusServerInit(&ncpOpenThread, &sThreadMutex);
        std::thread(UbusServerRun).detach();
#endif
        SuccessOrExit(ret = Mainloop(instance, interfaceName));
    }

    otbrLogDeinit();

exit:
    return ret;
}

void otPlatReset(otInstance *aInstance)
{
    OT_UNUSED_VARIABLE(aInstance);

    gPlatResetReason = OT_PLAT_RESET_REASON_SOFTWARE;

    otSysDeinit();

    longjmp(sResetJump, 1);
    assert(false);
}

int main(int argc, char *argv[])
{
    if (setjmp(sResetJump))
    {
        alarm(0);
#if OPENTHREAD_ENABLE_COVERAGE
        __gcov_flush();
#endif
        execvp(argv[0], argv);
    }

    return realmain(argc, argv);
}
<|endoftext|>


<commit_before>//===-- Intercept.cpp - System function interception routines -------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// If a function call occurs to an external function, the JIT is designed to use
// the dynamic loader interface to find a function to call.  This is useful for
// calling system calls and library functions that are not available in LLVM.
// Some system calls, however, need to be handled specially.  For this reason,
// we intercept some of them here and use our own stubs to handle them.
//
//===----------------------------------------------------------------------===//

#include "JIT.h"
#include "llvm/System/DynamicLibrary.h"
#include "llvm/Config/config.h"
using namespace llvm;

// AtExitHandlers - List of functions to call when the program exits,
// registered with the atexit() library function.
static std::vector<void (*)()> AtExitHandlers;

/// runAtExitHandlers - Run any functions registered by the program's
/// calls to atexit(3), which we intercept and store in
/// AtExitHandlers.
///
static void runAtExitHandlers() {
  while (!AtExitHandlers.empty()) {
    void (*Fn)() = AtExitHandlers.back();
    AtExitHandlers.pop_back();
    Fn();
  }
}

//===----------------------------------------------------------------------===//
// Function stubs that are invoked instead of certain library calls
//===----------------------------------------------------------------------===//

// Force the following functions to be linked in to anything that uses the
// JIT. This is a hack designed to work around the all-too-clever Glibc
// strategy of making these functions work differently when inlined vs. when
// not inlined, and hiding their real definitions in a separate archive file
// that the dynamic linker can't see. For more info, search for
// 'libc_nonshared.a' on Google, or read http://llvm.org/PR274.
#if defined(__linux__)
#if defined(HAVE_SYS_STAT_H)
#include <sys/stat.h>
#endif
void *FunctionPointers[] = {
  (void *)(intptr_t) stat,
  (void *)(intptr_t) fstat,
  (void *)(intptr_t) lstat,
  (void *)(intptr_t) stat64,
  (void *)(intptr_t) fstat64,
  (void *)(intptr_t) lstat64,
  (void *)(intptr_t) atexit,
  (void *)(intptr_t) mknod
};
#endif // __linux__

// jit_exit - Used to intercept the "exit" library call.
static void jit_exit(int Status) {
  runAtExitHandlers();   // Run atexit handlers...
  exit(Status);
}

// jit_atexit - Used to intercept the "atexit" library call.
static int jit_atexit(void (*Fn)(void)) {
  AtExitHandlers.push_back(Fn);    // Take note of atexit handler...
  return 0;  // Always successful
}

//===----------------------------------------------------------------------===//
//
/// getPointerToNamedFunction - This method returns the address of the specified
/// function by using the dynamic loader interface.  As such it is only useful
/// for resolving library symbols, not code generated symbols.
///
void *JIT::getPointerToNamedFunction(const std::string &Name) {
  // Check to see if this is one of the functions we want to intercept.  Note,
  // we cast to intptr_t here to silence a -pedantic warning that complains
  // about casting a function pointer to a normal pointer.
  if (Name == "exit") return (void*)(intptr_t)&jit_exit;
  if (Name == "atexit") return (void*)(intptr_t)&jit_atexit;

  const char *NameStr = Name.c_str();
  // If this is an asm specifier, skip the sentinal.
  if (NameStr[0] == 1) ++NameStr;

  // If it's an external function, look it up in the process image...
  void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr);
  if (Ptr) return Ptr;

  // If it wasn't found and if it starts with an underscore ('_') character, and
  // has an asm specifier, try again without the underscore.
  if (Name[0] == 1 && NameStr[0] == '_') {
    Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr+1);
    if (Ptr) return Ptr;
  }

  /// If a LazyFunctionCreator is installed, use it to get/create the function.
  if (LazyFunctionCreator)
    if (void *RP = LazyFunctionCreator(Name))
      return RP;

  cerr << "ERROR: Program used external function '" << Name
       << "' which could not be resolved!\n";
  abort();
  return 0;
}
<commit_msg>Unbreak all of the darwin/ppc32 JIT failures having to do  with not being able to find printf.<commit_after>//===-- Intercept.cpp - System function interception routines -------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// If a function call occurs to an external function, the JIT is designed to use
// the dynamic loader interface to find a function to call.  This is useful for
// calling system calls and library functions that are not available in LLVM.
// Some system calls, however, need to be handled specially.  For this reason,
// we intercept some of them here and use our own stubs to handle them.
//
//===----------------------------------------------------------------------===//

#include "JIT.h"
#include "llvm/System/DynamicLibrary.h"
#include "llvm/Config/config.h"
using namespace llvm;

// AtExitHandlers - List of functions to call when the program exits,
// registered with the atexit() library function.
static std::vector<void (*)()> AtExitHandlers;

/// runAtExitHandlers - Run any functions registered by the program's
/// calls to atexit(3), which we intercept and store in
/// AtExitHandlers.
///
static void runAtExitHandlers() {
  while (!AtExitHandlers.empty()) {
    void (*Fn)() = AtExitHandlers.back();
    AtExitHandlers.pop_back();
    Fn();
  }
}

//===----------------------------------------------------------------------===//
// Function stubs that are invoked instead of certain library calls
//===----------------------------------------------------------------------===//

// Force the following functions to be linked in to anything that uses the
// JIT. This is a hack designed to work around the all-too-clever Glibc
// strategy of making these functions work differently when inlined vs. when
// not inlined, and hiding their real definitions in a separate archive file
// that the dynamic linker can't see. For more info, search for
// 'libc_nonshared.a' on Google, or read http://llvm.org/PR274.
#if defined(__linux__)
#if defined(HAVE_SYS_STAT_H)
#include <sys/stat.h>
#endif
void *FunctionPointers[] = {
  (void *)(intptr_t) stat,
  (void *)(intptr_t) fstat,
  (void *)(intptr_t) lstat,
  (void *)(intptr_t) stat64,
  (void *)(intptr_t) fstat64,
  (void *)(intptr_t) lstat64,
  (void *)(intptr_t) atexit,
  (void *)(intptr_t) mknod
};
#endif // __linux__

// jit_exit - Used to intercept the "exit" library call.
static void jit_exit(int Status) {
  runAtExitHandlers();   // Run atexit handlers...
  exit(Status);
}

// jit_atexit - Used to intercept the "atexit" library call.
static int jit_atexit(void (*Fn)(void)) {
  AtExitHandlers.push_back(Fn);    // Take note of atexit handler...
  return 0;  // Always successful
}

//===----------------------------------------------------------------------===//
//
/// getPointerToNamedFunction - This method returns the address of the specified
/// function by using the dynamic loader interface.  As such it is only useful
/// for resolving library symbols, not code generated symbols.
///
void *JIT::getPointerToNamedFunction(const std::string &Name) {
  // Check to see if this is one of the functions we want to intercept.  Note,
  // we cast to intptr_t here to silence a -pedantic warning that complains
  // about casting a function pointer to a normal pointer.
  if (Name == "exit") return (void*)(intptr_t)&jit_exit;
  if (Name == "atexit") return (void*)(intptr_t)&jit_atexit;

  const char *NameStr = Name.c_str();
  // If this is an asm specifier, skip the sentinal.
  if (NameStr[0] == 1) ++NameStr;

  // If it's an external function, look it up in the process image...
  void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr);
  if (Ptr) return Ptr;

  // If it wasn't found and if it starts with an underscore ('_') character, and
  // has an asm specifier, try again without the underscore.
  if (Name[0] == 1 && NameStr[0] == '_') {
    Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr+1);
    if (Ptr) return Ptr;
  }

  // darwin/ppc adds $LDBLStub suffixes to various symbols like printf.  These
  // are references to hidden visibility symbols that dlsym cannot resolve.  If
  // we have one of these, strip off $LDBLStub and try again.
#if defined(__APPLE__) && defined(__ppc__)
  if (Name.size() > 9 && Name[Name.size()-9] == '$' &&
      memcmp(&Name[Name.size()-8], "LDBLStub", 8) == 0)
    return getPointerToNamedFunction(std::string(Name.begin(),
                                                 Name.end()-9));
#endif

  /// If a LazyFunctionCreator is installed, use it to get/create the function.
  if (LazyFunctionCreator)
    if (void *RP = LazyFunctionCreator(Name))
      return RP;

  cerr << "ERROR: Program used external function '" << Name
       << "' which could not be resolved!\n";
  abort();
  return 0;
}
<|endoftext|>


<commit_before><commit_msg>(MPU9250): fix setting gyro FSR<commit_after><|endoftext|>


<commit_before>#include "Mirror.h"

Mirror::Mirror(float ma, float mi, bool z, glm::vec3 o) : Entity()
{
  this->LoadObject("Assets/untitled.obj", false);
  this->setColor(glm::vec3(0,0,1));
  this->reflective = true;
  isZ = true;
  max = ma;
  min = mi;
  isZ = z;
  if (isZ) {
    cur = this->position.z;
    this->scale  = glm::vec3(2.5f,7.5,10);
  } else {
    cur = this->position.x;
    this->scale  = glm::vec3(10,7.5,2.5f);
  }
  origin = o;
}

Mirror::~Mirror()
{

}

bool Mirror::checkZ()
{
  return isZ;
}

void Mirror::update(float deltaTime) {
  if (input()->isDown(GLFW_KEY_S) && cur < max && !isZ || input()->isDown(GLFW_KEY_A) && cur < max && isZ) {
    cur += 10.0f * deltaTime;
  } else if (input()->isDown(GLFW_KEY_W) && cur > min && !isZ || input()->isDown(GLFW_KEY_D) && cur > min && isZ) {
    cur -= 10.0f * deltaTime;
  }
  if (isZ) {
    this->position.z = origin.z + cur;
  } else {
    this->position.x = origin.x + cur;
  }
}
<commit_msg>Update documentation<commit_after>#include "Mirror.h"

Mirror::Mirror(float ma, float mi, bool z, glm::vec3 o) : Entity()
{
  // Load an OBJ file
  this->LoadObject("Assets/untitled.obj", false);
  // Set the color
  this->setColor(glm::vec3(0,0,1));
  // Make the object reflective
  this->reflective = true;
  // set these vars
  max = ma;
  min = mi;
  isZ = z;
  if (isZ) {
    // Object is vertical (Z axis)
    cur = this->position.z;
    this->scale  = glm::vec3(2.5f,7.5,10);
  } else {
    // Object is horizontal (X axis)
    cur = this->position.x;
    this->scale  = glm::vec3(10,7.5,2.5f);
  }
  // Set the origin so we can move the mirror according to this
  origin = o;
}

Mirror::~Mirror()
{

}

bool Mirror::checkZ()
{
  // Check if the mirror is horizontal or vertical
  return isZ;
}

void Mirror::update(float deltaTime) {
  if (input()->isDown(GLFW_KEY_S) && cur < max && !isZ || input()->isDown(GLFW_KEY_A) && cur < max && isZ) {
    // Move the mirror according to it's state (horizontal | vertical)
    cur += 10.0f * deltaTime;
  } else if (input()->isDown(GLFW_KEY_W) && cur > min && !isZ || input()->isDown(GLFW_KEY_D) && cur > min && isZ) {
    // Move the mirror according to it's state (horizontal | vertical)
    cur -= 10.0f * deltaTime;
  }
  if (isZ) {
    // Move the mirror according to it's state (horizontal | vertical)
    this->position.z = origin.z + cur;
  } else {
    // Move the mirror according to it's state (horizontal | vertical)
    this->position.x = origin.x + cur;
  }
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: DAVRequestEnvironment.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 16:06:42 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _DAVREQUESTENVIRONMENT_HXX_
#define _DAVREQUESTENVIRONMENT_HXX_

#ifndef _RTL_REF_HXX_
#include <rtl/ref.hxx>
#endif

#ifndef _DAVAUTHLISTENER_HXX_
#include "DAVAuthListener.hxx"
#endif

namespace webdav_ucp
{

struct DAVRequestEnvironment
{
    rtl::OUString m_aRequestURI;
    rtl::Reference< DAVAuthListener >     m_xAuthListener;
//    rtl::Reference< DAVStatusListener >   m_xStatusListener;
//    rtl::Reference< DAVProgressListener > m_xStatusListener;

    DAVRequestEnvironment( const rtl::OUString & rRequestURI,
                           const rtl::Reference< DAVAuthListener > & xListener )
    : m_aRequestURI( rRequestURI ), m_xAuthListener( xListener ) {}

    DAVRequestEnvironment() {}
};

}; // namespace webdav_ucp

#endif // _DAVREQUESTENVIRONMENT_HXX_
<commit_msg>INTEGRATION: CWS warnings01 (1.5.10); FILE MERGED 2005/11/10 18:10:17 pl 1.5.10.1: #i55991# removed warnings<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: DAVRequestEnvironment.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-20 05:33:41 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _DAVREQUESTENVIRONMENT_HXX_
#define _DAVREQUESTENVIRONMENT_HXX_

#ifndef _RTL_REF_HXX_
#include <rtl/ref.hxx>
#endif

#ifndef _DAVAUTHLISTENER_HXX_
#include "DAVAuthListener.hxx"
#endif

namespace webdav_ucp
{

struct DAVRequestEnvironment
{
    rtl::OUString m_aRequestURI;
    rtl::Reference< DAVAuthListener >     m_xAuthListener;
//    rtl::Reference< DAVStatusListener >   m_xStatusListener;
//    rtl::Reference< DAVProgressListener > m_xStatusListener;

    DAVRequestEnvironment( const rtl::OUString & rRequestURI,
                           const rtl::Reference< DAVAuthListener > & xListener )
    : m_aRequestURI( rRequestURI ), m_xAuthListener( xListener ) {}

    DAVRequestEnvironment() {}
};

} // namespace webdav_ucp

#endif // _DAVREQUESTENVIRONMENT_HXX_
<|endoftext|>


<commit_before>// $Id: forceFieldComponent.C,v 1.7 2000/07/25 21:14:22 oliver Exp $

#include <BALL/MOLMEC/COMMON/forceFieldComponent.h>

using namespace std;

namespace BALL
{

	// default constructor
	ForceFieldComponent::ForceFieldComponent()
	{
		name_ = "GenericForceFieldComponent";
		force_field_ = 0;
		energy_ = 0;
	}

	// constructor
	ForceFieldComponent::ForceFieldComponent(ForceField& force_field)
	{
		force_field_ = &force_field;
		name_ = "GenericForceFieldComponent";
		energy_ = 0;
	}

	// copy constructor
	ForceFieldComponent::ForceFieldComponent(const ForceFieldComponent& force_field_component, bool /* clone_deep */)
	{
		name_ = force_field_component.name_;
		force_field_ = force_field_component.force_field_;
		energy_ = force_field_component.energy_;
	}

	// destructor
	ForceFieldComponent::~ForceFieldComponent()
	{
	}

	// setup
	bool ForceFieldComponent::setup()
	{
		return true;
	}

	// update pair lists - empty!
	void update()
	{
	}

	// Set the name of the component
	void ForceFieldComponent::setName(const String& name)
	{
		name_ = name;
	}

	// Return the name of the component
	String ForceFieldComponent::getName( ) const
	{
		return name_;
	}

	// Return a pointer to the force field
	ForceField* ForceFieldComponent::getForceField() const
	{
		return force_field_;
	}

	// Set the force field to force_field
	void ForceFieldComponent::setForceField(ForceField& force_field)
	{
		force_field_ = &force_field;
	}

	double ForceFieldComponent::getEnergy() const
	{
		return energy_;
	}

	double ForceFieldComponent::updateEnergy()
	{
		return 0.0;
	}

	void ForceFieldComponent::updateForces()
	{
	}

} // namespace BALL
<commit_msg>fixed: missing implementation of update() method<commit_after>// $Id: forceFieldComponent.C,v 1.8 2000/07/26 08:25:50 oliver Exp $

#include <BALL/MOLMEC/COMMON/forceFieldComponent.h>

using namespace std;

namespace BALL
{

	// default constructor
	ForceFieldComponent::ForceFieldComponent()
	{
		name_ = "GenericForceFieldComponent";
		force_field_ = 0;
		energy_ = 0;
	}

	// constructor
	ForceFieldComponent::ForceFieldComponent(ForceField& force_field)
	{
		force_field_ = &force_field;
		name_ = "GenericForceFieldComponent";
		energy_ = 0;
	}

	// copy constructor
	ForceFieldComponent::ForceFieldComponent(const ForceFieldComponent& force_field_component, bool /* clone_deep */)
	{
		name_ = force_field_component.name_;
		force_field_ = force_field_component.force_field_;
		energy_ = force_field_component.energy_;
	}

	// destructor
	ForceFieldComponent::~ForceFieldComponent()
	{
	}

	// setup
	bool ForceFieldComponent::setup()
	{
		return true;
	}

	// update pair lists - empty!
	void update()
	{
	}

	// Set the name of the component
	void ForceFieldComponent::setName(const String& name)
	{
		name_ = name;
	}

	// Return the name of the component
	String ForceFieldComponent::getName( ) const
	{
		return name_;
	}

	// Return a pointer to the force field
	ForceField* ForceFieldComponent::getForceField() const
	{
		return force_field_;
	}

	// Set the force field to force_field
	void ForceFieldComponent::setForceField(ForceField& force_field)
	{
		force_field_ = &force_field;
	}

	double ForceFieldComponent::getEnergy() const
	{
		return energy_;
	}

	double ForceFieldComponent::updateEnergy()
	{
		return 0.0;
	}

	void ForceFieldComponent::updateForces()
	{
	}

	void ForceFieldComponent::update()
	{
	}

} // namespace BALL
<|endoftext|>


<commit_before>#include "LaserManager.h"
#include <mining-manager/MiningManager.h>
#include <glog/logging.h>
using namespace sf1r::laser;
namespace sf1r
{
    LaserManager::LaserManager(const boost::shared_ptr<AdSearchService>& adSearchService)
        : adSearchService_(adSearchService)
    {
        rpcServer_ = RpcServer::getInstance();
        rpcServer_->start("0.0.0.0",
            28611,
            2,
            MiningManager::system_working_path_ + "/laser_clustering/",
            MiningManager::system_working_path_ + "/laser_leveldb",
            MiningManager::system_resource_path_ + "/dict/title_pca/");

        recommend_.reset(new LaserRecommend());
    }

    LaserManager::~LaserManager()
    {
    }

    bool LaserManager::recommend(const LaserRecommendParam& param,
        RawTextResultFromMIA& itemList) const
    {
        std::vector<std::string> docIdList;
        std::vector<float> itemScoreList;
        if (!recommend_->recommend(param.uuid_, docIdList, itemScoreList, param.topN_))
            return false;
        //TODO
        //miningManager_.GetAdSearchService()->getDocument(docIdList, itemList);
        return true;
    }
}
<commit_msg>add getDocumentsByIds<commit_after>#include "LaserManager.h"
#include <mining-manager/MiningManager.h>
#include <query-manager/ActionItem.h>
#include <ad-manager/AdSearchService.h>
#include <glog/logging.h>
using namespace sf1r::laser;
namespace sf1r
{
    LaserManager::LaserManager(const boost::shared_ptr<AdSearchService>& adSearchService)
        : adSearchService_(adSearchService)
    {
        rpcServer_ = RpcServer::getInstance();
        rpcServer_->start("0.0.0.0",
            28611,
            2,
            MiningManager::system_working_path_ + "/laser_clustering/",
            MiningManager::system_working_path_ + "/laser_leveldb",
            MiningManager::system_resource_path_ + "/dict/title_pca/");

        recommend_.reset(new LaserRecommend());
    }

    LaserManager::~LaserManager()
    {
    }

    bool LaserManager::recommend(const LaserRecommendParam& param,
        RawTextResultFromMIA& res) const
    {
        std::vector<std::string> docIdList;
        std::vector<float> itemScoreList;
        if (!recommend_->recommend(param.uuid_, docIdList, itemScoreList, param.topN_))
            return false;
        GetDocumentsByIdsActionItem actionItem;
        for (std::size_t i = 0; i < docIdList.size(); ++i)
        {
            actionItem.docIdList_.push_back(docIdList[i]);
        }
        adSearchService_->getDocumentsByIds(actionItem, res);
        return true;
    }
}
<|endoftext|>


<commit_before>/**
 * \file
 * \brief SpiMaster class implementation
 *
 * \author Copyright (C) 2016-2018 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "distortos/devices/communication/SpiMaster.hpp"

#include "distortos/devices/communication/SpiDevice.hpp"
#include "distortos/devices/communication/SpiDeviceProxy.hpp"
#include "distortos/devices/communication/SpiMasterLowLevel.hpp"
#include "distortos/devices/communication/SpiMasterOperation.hpp"
#include "distortos/devices/communication/SpiMasterProxy.hpp"

#include "distortos/devices/io/OutputPin.hpp"

#include "distortos/internal/CHECK_FUNCTION_CONTEXT.hpp"

#include "distortos/assert.h"
#include "distortos/Semaphore.hpp"

#include "estd/ScopeGuard.hpp"

#include <mutex>

#include <cerrno>

namespace distortos
{

namespace devices
{

/*---------------------------------------------------------------------------------------------------------------------+
| public functions
+---------------------------------------------------------------------------------------------------------------------*/

SpiMaster::~SpiMaster()
{
	CHECK_FUNCTION_CONTEXT();

	if (openCount_ == 0)
		return;

	const std::lock_guard<distortos::Mutex> lockGuard {mutex_};

	spiMaster_.stop();
}

int SpiMaster::close()
{
	const std::lock_guard<distortos::Mutex> lockGuard {mutex_};

	if (openCount_ == 0)	// device is not open anymore?
		return EBADF;

	if (openCount_ == 1)	// last close?
	{
		const auto ret = spiMaster_.stop();
		if (ret != 0)
			return ret;
	}

	--openCount_;
	return 0;
}

std::pair<int, size_t> SpiMaster::executeTransaction(SpiDevice& device, const SpiMasterOperationsRange operationsRange)
{
	CHECK_FUNCTION_CONTEXT();

	if (operationsRange.size() == 0)
		return {EINVAL, {}};

	const SpiDevice::Proxy spiDeviceProxy {device};
	Proxy proxy {spiDeviceProxy};

	{
		const auto ret = proxy.configure(device.getMode(), device.getMaxClockFrequency(), device.getWordLength(),
				device.getLsbFirst());
		if (ret.first != 0)
			return {ret.first, {}};
	}

	device.getSlaveSelectPin().set(false);
	const auto cleanupScopeGuard = estd::makeScopeGuard(
			[&device]()
			{
				device.getSlaveSelectPin().set(true);
			});

	return proxy.executeTransaction(operationsRange);
}

int SpiMaster::open()
{
	const std::lock_guard<distortos::Mutex> lockGuard {mutex_};

	if (openCount_ == std::numeric_limits<decltype(openCount_)>::max())	// device is already opened too many times?
		return EMFILE;

	if (openCount_ == 0)	// first open?
	{
		const auto ret = spiMaster_.start(*this);
		if (ret != 0)
			return ret;
	}

	++openCount_;
	return 0;
}

/*---------------------------------------------------------------------------------------------------------------------+
| private functions
+---------------------------------------------------------------------------------------------------------------------*/

void SpiMaster::notifyWaiter(const int ret)
{
	ret_ = ret;
	const auto semaphore = semaphore_;
	assert(semaphore != nullptr);
	semaphore->post();
}

void SpiMaster::transferCompleteEvent(SpiMasterErrorSet errorSet, size_t bytesTransfered)
{
	assert(operationsRange_.size() != 0 && "Invalid range of operations!");

	{
		const auto previousTransfer = operationsRange_.begin()->getTransfer();
		assert(previousTransfer != nullptr && "Invalid type of previous operation!");
		previousTransfer->finalize(errorSet, bytesTransfered);
	}

	const auto error = errorSet.any();
	if (error == false)	// handling of last operation successful?
		operationsRange_ = {operationsRange_.begin() + 1, operationsRange_.end()};

	if (operationsRange_.size() == 0 || error == true)	// all operations are done or handling of last one failed?
	{
		notifyWaiter(error == false ? 0 : EIO);
		return;
	}

	{
		const auto nextTransfer = operationsRange_.begin()->getTransfer();
		assert(nextTransfer != nullptr && "Invalid type of next operation!");
		const auto ret = spiMaster_.startTransfer(nextTransfer->getWriteBuffer(), nextTransfer->getReadBuffer(),
				nextTransfer->getSize());
		if (ret != 0)
			notifyWaiter(ret);
	}
}

}	// namespace devices

}	// namespace distortos
<commit_msg>Use SpiDeviceSelectGuard in SpiMaster<commit_after>/**
 * \file
 * \brief SpiMaster class implementation
 *
 * \author Copyright (C) 2016-2018 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "distortos/devices/communication/SpiMaster.hpp"

#include "distortos/devices/communication/SpiDevice.hpp"
#include "distortos/devices/communication/SpiDeviceProxy.hpp"
#include "distortos/devices/communication/SpiDeviceSelectGuard.hpp"
#include "distortos/devices/communication/SpiMasterLowLevel.hpp"
#include "distortos/devices/communication/SpiMasterOperation.hpp"
#include "distortos/devices/communication/SpiMasterProxy.hpp"

#include "distortos/internal/CHECK_FUNCTION_CONTEXT.hpp"

#include "distortos/assert.h"
#include "distortos/Semaphore.hpp"

#include <mutex>

#include <cerrno>

namespace distortos
{

namespace devices
{

/*---------------------------------------------------------------------------------------------------------------------+
| public functions
+---------------------------------------------------------------------------------------------------------------------*/

SpiMaster::~SpiMaster()
{
	CHECK_FUNCTION_CONTEXT();

	if (openCount_ == 0)
		return;

	const std::lock_guard<distortos::Mutex> lockGuard {mutex_};

	spiMaster_.stop();
}

int SpiMaster::close()
{
	const std::lock_guard<distortos::Mutex> lockGuard {mutex_};

	if (openCount_ == 0)	// device is not open anymore?
		return EBADF;

	if (openCount_ == 1)	// last close?
	{
		const auto ret = spiMaster_.stop();
		if (ret != 0)
			return ret;
	}

	--openCount_;
	return 0;
}

std::pair<int, size_t> SpiMaster::executeTransaction(SpiDevice& device, const SpiMasterOperationsRange operationsRange)
{
	CHECK_FUNCTION_CONTEXT();

	if (operationsRange.size() == 0)
		return {EINVAL, {}};

	const SpiDevice::Proxy spiDeviceProxy {device};
	Proxy proxy {spiDeviceProxy};

	{
		const auto ret = proxy.configure(device.getMode(), device.getMaxClockFrequency(), device.getWordLength(),
				device.getLsbFirst());
		if (ret.first != 0)
			return {ret.first, {}};
	}

	const SpiDeviceSelectGuard spiDeviceSelectGuard {proxy};

	return proxy.executeTransaction(operationsRange);
}

int SpiMaster::open()
{
	const std::lock_guard<distortos::Mutex> lockGuard {mutex_};

	if (openCount_ == std::numeric_limits<decltype(openCount_)>::max())	// device is already opened too many times?
		return EMFILE;

	if (openCount_ == 0)	// first open?
	{
		const auto ret = spiMaster_.start(*this);
		if (ret != 0)
			return ret;
	}

	++openCount_;
	return 0;
}

/*---------------------------------------------------------------------------------------------------------------------+
| private functions
+---------------------------------------------------------------------------------------------------------------------*/

void SpiMaster::notifyWaiter(const int ret)
{
	ret_ = ret;
	const auto semaphore = semaphore_;
	assert(semaphore != nullptr);
	semaphore->post();
}

void SpiMaster::transferCompleteEvent(SpiMasterErrorSet errorSet, size_t bytesTransfered)
{
	assert(operationsRange_.size() != 0 && "Invalid range of operations!");

	{
		const auto previousTransfer = operationsRange_.begin()->getTransfer();
		assert(previousTransfer != nullptr && "Invalid type of previous operation!");
		previousTransfer->finalize(errorSet, bytesTransfered);
	}

	const auto error = errorSet.any();
	if (error == false)	// handling of last operation successful?
		operationsRange_ = {operationsRange_.begin() + 1, operationsRange_.end()};

	if (operationsRange_.size() == 0 || error == true)	// all operations are done or handling of last one failed?
	{
		notifyWaiter(error == false ? 0 : EIO);
		return;
	}

	{
		const auto nextTransfer = operationsRange_.begin()->getTransfer();
		assert(nextTransfer != nullptr && "Invalid type of next operation!");
		const auto ret = spiMaster_.startTransfer(nextTransfer->getWriteBuffer(), nextTransfer->getReadBuffer(),
				nextTransfer->getSize());
		if (ret != 0)
			notifyWaiter(ret);
	}
}

}	// namespace devices

}	// namespace distortos
<|endoftext|>


<commit_before>/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */

/*  Fluent Bit - Output data to Treasure Data
 *  =========================================
 *  Copyright (C) 2015 Treasure Data Inc.
 *
 *  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.
 */

#include <unistd.h>
#include <fluent-bit.h>

int main(int argc, char **argv)
{
    int i;
    int n;
    int ret;
    char tmp[256];
    struct flb_config *config;

    if (argc < 2) {
        fprintf(stderr, "Usage: td /path/to/configuration.file\n");
        exit(EXIT_FAILURE);
    }

    /* Create configuration context */
    config = flb_config_init();
    if (!config) {
        exit(EXIT_FAILURE);
    }

    /* Enable verbose messages */
    flb_config_verbose(FLB_TRUE);

    /* Load a configuration file (required by TD output plugin) */
    ret = flb_lib_config_file(config, argv[1]);

    /* Initialize library */
    ret = flb_lib_init(config, (char *) "td");
    if (ret != 0) {
        exit(EXIT_FAILURE);
    }

    /* Start the background worker */
    flb_lib_start(config);

    /* Push some data */
    for (i = 0; i < 100; i++) {
        n = snprintf(tmp, sizeof(tmp) - 1,
                     "{\"time\": 1442875576, \"key\": \"val %i\"}", i);
        flb_lib_push(config, tmp, n);
    }

    flb_lib_stop(config);

    return 0;
}
<commit_msg>Example: Treasure Data: make sample more friendly<commit_after>/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */

/*  Fluent Bit - Output data to Treasure Data
 *  =========================================
 *  Copyright (C) 2015 Treasure Data Inc.
 *
 *  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.
 */

#include <unistd.h>
#include <fluent-bit.h>

int main(int argc, char **argv)
{
    int i;
    int n;
    int ret;
    int time_field;
    char tmp[256];
    struct flb_config *config;

    if (argc < 2) {
        fprintf(stderr, "Usage: td /path/to/configuration.file\n");
        exit(EXIT_FAILURE);
    }

    /* Create configuration context */
    config = flb_config_init();
    if (!config) {
        exit(EXIT_FAILURE);
    }

    /* Enable verbose messages */
    flb_config_verbose(FLB_TRUE);

    /* Load a configuration file (required by TD output plugin) */
    ret = flb_lib_config_file(config, argv[1]);

    /* Initialize library */
    ret = flb_lib_init(config, (char *) "td");
    if (ret != 0) {
        exit(EXIT_FAILURE);
    }

    /* Start the background worker */
    flb_lib_start(config);

    /* Push some data */
    time_field = time(NULL) - 100;
    for (i = 0; i < 100; i++) {
        n = snprintf(tmp, sizeof(tmp) - 1,
                     "{\"time\": %i, \"key\": \"val %i\"}", time_field, i);
        flb_lib_push(config, tmp, n);
        time_field++;
    }

    flb_lib_stop(config);

    return 0;
}
<|endoftext|>


<commit_before>#include <xzero/executor/NativeScheduler.h>
#include <xzero/RuntimeError.h>
#include <xzero/WallClock.h>
#include <xzero/sysconfig.h>
#include <algorithm>
#include <vector>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/select.h>
#include <unistd.h>
#include <fcntl.h>

namespace xzero {

#define PIPE_READ_END  0
#define PIPE_WRITE_END 1

/**
 * XXX
 * - registering a key should be *ONESHOT* and *Edge Triggered*
 * - remove SelectionKey::change()
 * - add SelectionKey::cancel()
 * - do we need Selectable then (just use EndPoinit or `int fd`?)
 *   - endpoint: operator int() { return handle(); }
 * - maybe inherit from Executor
 * - add a way to add timed callbacks that can be cancelled
 * - actual implementations inheriting from: Selector < Scheduler < Executor
 * - select: SelectEventLoop (currently: NativeScheduler)
 * - epoll: LinuxEventLoop
 *
 */

NativeScheduler::NativeScheduler(
    std::function<void(const std::exception&)> errorLogger,
    WallClock* clock,
    std::function<void()> preInvoke,
    std::function<void()> postInvoke)
    : Scheduler(std::move(errorLogger)),
      clock_(clock ? clock : WallClock::system()),
      lock_(),
      wakeupPipe_(),
      onPreInvokePending_(preInvoke),
      onPostInvokePending_(postInvoke) {
  if (pipe(wakeupPipe_) < 0) {
    throw SYSTEM_ERROR(errno);
  }
  fcntl(wakeupPipe_[0], F_SETFL, O_NONBLOCK);
  fcntl(wakeupPipe_[1], F_SETFL, O_NONBLOCK);
}

NativeScheduler::NativeScheduler(
    std::function<void(const std::exception&)> errorLogger,
    WallClock* clock)
    : NativeScheduler(errorLogger, clock, nullptr, nullptr) {
}

NativeScheduler::NativeScheduler()
    : NativeScheduler(nullptr, nullptr, nullptr, nullptr) {
}

NativeScheduler::~NativeScheduler() {
  ::close(wakeupPipe_[PIPE_READ_END]);
  ::close(wakeupPipe_[PIPE_WRITE_END]);
}

void NativeScheduler::execute(Task&& task) {
  {
    std::lock_guard<std::mutex> lk(lock_);
    tasks_.push_back(task);
  }
  breakLoop();
}

std::string NativeScheduler::toString() const {
  return "NativeScheduler";
}

Scheduler::HandleRef NativeScheduler::executeAfter(TimeSpan delay, Task task) {
  auto onCancel = [this](Handle* handle) {
    removeFromTimersList(handle);
  };

  return insertIntoTimersList(clock_->get() + delay,
                              std::make_shared<Handle>(task, onCancel));
}

Scheduler::HandleRef NativeScheduler::executeAt(DateTime when, Task task) {
  return insertIntoTimersList(
      when,
      std::make_shared<Handle>(task,
                               std::bind(&NativeScheduler::removeFromTimersList,
                                         this,
                                         std::placeholders::_1)));
}

Scheduler::HandleRef NativeScheduler::insertIntoTimersList(DateTime dt,
                                                           HandleRef handle) {
  Timer t = { dt, handle };

  std::lock_guard<std::mutex> lk(lock_);

  auto i = timers_.end();
  auto e = timers_.begin();

  while (i != e) {
    i--;
    const Timer& current = *i;
    if (current.when >= t.when) {
      timers_.insert(i, t);
      return handle;
    }
  }

  timers_.push_front(t);
  return handle;
}

void NativeScheduler::removeFromTimersList(Handle* handle) {
  std::lock_guard<std::mutex> lk(lock_);

  for (auto i = timers_.begin(), e = timers_.end(); i != e; ++i) {
    if (i->handle.get() == handle) {
      timers_.erase(i);
      break;
    }
  }
}

void NativeScheduler::collectTimeouts() {
  const DateTime now = clock_->get();

  std::lock_guard<std::mutex> lk(lock_);

  for (;;) {
    if (timers_.empty())
      break;

    const Timer& job = timers_.front();

    if (job.when > now)
      break;

    tasks_.push_back(job.handle->getAction());
    timers_.pop_front();
  }
}

inline Scheduler::HandleRef registerInterest(
    std::mutex* registryLock,
    std::list<std::pair<int, Scheduler::HandleRef>>* registry,
    int fd,
    Executor::Task task) {

  auto onCancel = [=](Scheduler::Handle* h) {
    std::lock_guard<std::mutex> lk(*registryLock);
    for (auto i: *registry) {
      if (i.second.get() == h) {
        return registry->remove(i);
      }
    }
  };

  std::lock_guard<std::mutex> lk(*registryLock);
  auto handle = std::make_shared<Scheduler::Handle>(task, onCancel);
  registry->push_back(std::make_pair(fd, handle));

  return handle;
}

Scheduler::HandleRef NativeScheduler::executeOnReadable(int fd, Task task) {
  return registerInterest(&lock_, &readers_, fd, task);
}

Scheduler::HandleRef NativeScheduler::executeOnWritable(int fd, Task task) {
  return registerInterest(&lock_, &writers_, fd, task);
}

inline void collectActiveHandles(
    std::list<std::pair<int, Scheduler::HandleRef>>* interests,
    fd_set* fdset,
    std::vector<Scheduler::HandleRef>* result) {

  auto i = interests->begin();
  auto e = interests->end();

  while (i != e) {
    if (FD_ISSET(i->first, fdset)) {
      result->push_back(i->second);
      auto k = i;
      ++i;
      interests->erase(k);
    } else {
      i++;
    }
  }
}

size_t NativeScheduler::timerCount() {
  std::lock_guard<std::mutex> lk(lock_);
  return timers_.size();
}

size_t NativeScheduler::readerCount() {
  std::lock_guard<std::mutex> lk(lock_);
  return readers_.size();
}

size_t NativeScheduler::writerCount() {
  std::lock_guard<std::mutex> lk(lock_);
  return writers_.size();
}

void NativeScheduler::runLoopOnce() {
  fd_set input, output, error;
  FD_ZERO(&input);
  FD_ZERO(&output);
  FD_ZERO(&error);

  int wmark = 0;
  timeval tv;

  {
    std::lock_guard<std::mutex> lk(lock_);

    for (auto i: readers_) {
      FD_SET(i.first, &input);
      if (i.first > wmark) {
        wmark = i.first;
      }
    }

    for (auto i: writers_) {
      FD_SET(i.first, &output);
      if (i.first > wmark) {
        wmark = i.first;
      }
    }

    const TimeSpan nextTimeout = !tasks_.empty()
                               ? TimeSpan::Zero
                               : !timers_.empty()
                                 ? timers_.front().when - clock_->get()
                                 : TimeSpan::fromSeconds(4);

    tv.tv_sec = static_cast<time_t>(nextTimeout.totalSeconds()),
    tv.tv_usec = nextTimeout.microseconds();
  }

  FD_SET(wakeupPipe_[PIPE_READ_END], &input);

  int rv = ::select(wmark + 1, &input, &output, &error, &tv);
  if (rv < 0 && errno != EINTR)
    throw SYSTEM_ERROR(errno);

  if (FD_ISSET(wakeupPipe_[PIPE_READ_END], &input)) {
    bool consumeMore = true;
    while (consumeMore) {
      char buf[sizeof(int) * 128];
      consumeMore = ::read(wakeupPipe_[PIPE_READ_END], buf, sizeof(buf)) > 0;
    }
  }

  collectTimeouts();

  std::vector<HandleRef> activeHandles;
  activeHandles.reserve(rv);

  std::deque<Task> activeTasks;
  {
    std::lock_guard<std::mutex> lk(lock_);

    collectActiveHandles(&readers_, &input, &activeHandles);
    collectActiveHandles(&writers_, &output, &activeHandles);
    activeTasks = std::move(tasks_);
  }

  safeCall(onPreInvokePending_);
  safeCallEach(activeHandles);
  safeCallEach(activeTasks);
  safeCall(onPostInvokePending_);
}

void NativeScheduler::breakLoop() {
  int dummy = 42;
  ::write(wakeupPipe_[PIPE_WRITE_END], &dummy, sizeof(dummy));
}

} // namespace xzero
<commit_msg>notes<commit_after>#include <xzero/executor/NativeScheduler.h>
#include <xzero/RuntimeError.h>
#include <xzero/WallClock.h>
#include <xzero/sysconfig.h>
#include <algorithm>
#include <vector>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/select.h>
#include <unistd.h>
#include <fcntl.h>

namespace xzero {

#define PIPE_READ_END  0
#define PIPE_WRITE_END 1

/**
 * XXX
 * - registering a key should be *ONESHOT* and *Edge Triggered*
 * - rename NativeScheduler to SimpleScheduler
 *
 * XXX LinuxScheduler
 * - epoll fuer i/o notification
 * - eventfd for wakeup implementation
 * - timerfd_* for timer impl
 */

NativeScheduler::NativeScheduler(
    std::function<void(const std::exception&)> errorLogger,
    WallClock* clock,
    std::function<void()> preInvoke,
    std::function<void()> postInvoke)
    : Scheduler(std::move(errorLogger)),
      clock_(clock ? clock : WallClock::system()),
      lock_(),
      wakeupPipe_(),
      onPreInvokePending_(preInvoke),
      onPostInvokePending_(postInvoke) {
  if (pipe(wakeupPipe_) < 0) {
    throw SYSTEM_ERROR(errno);
  }
  fcntl(wakeupPipe_[0], F_SETFL, O_NONBLOCK);
  fcntl(wakeupPipe_[1], F_SETFL, O_NONBLOCK);
}

NativeScheduler::NativeScheduler(
    std::function<void(const std::exception&)> errorLogger,
    WallClock* clock)
    : NativeScheduler(errorLogger, clock, nullptr, nullptr) {
}

NativeScheduler::NativeScheduler()
    : NativeScheduler(nullptr, nullptr, nullptr, nullptr) {
}

NativeScheduler::~NativeScheduler() {
  ::close(wakeupPipe_[PIPE_READ_END]);
  ::close(wakeupPipe_[PIPE_WRITE_END]);
}

void NativeScheduler::execute(Task&& task) {
  {
    std::lock_guard<std::mutex> lk(lock_);
    tasks_.push_back(task);
  }
  breakLoop();
}

std::string NativeScheduler::toString() const {
  return "NativeScheduler";
}

Scheduler::HandleRef NativeScheduler::executeAfter(TimeSpan delay, Task task) {
  auto onCancel = [this](Handle* handle) {
    removeFromTimersList(handle);
  };

  return insertIntoTimersList(clock_->get() + delay,
                              std::make_shared<Handle>(task, onCancel));
}

Scheduler::HandleRef NativeScheduler::executeAt(DateTime when, Task task) {
  return insertIntoTimersList(
      when,
      std::make_shared<Handle>(task,
                               std::bind(&NativeScheduler::removeFromTimersList,
                                         this,
                                         std::placeholders::_1)));
}

Scheduler::HandleRef NativeScheduler::insertIntoTimersList(DateTime dt,
                                                           HandleRef handle) {
  Timer t = { dt, handle };

  std::lock_guard<std::mutex> lk(lock_);

  auto i = timers_.end();
  auto e = timers_.begin();

  while (i != e) {
    i--;
    const Timer& current = *i;
    if (current.when >= t.when) {
      timers_.insert(i, t);
      return handle;
    }
  }

  timers_.push_front(t);
  return handle;
}

void NativeScheduler::removeFromTimersList(Handle* handle) {
  std::lock_guard<std::mutex> lk(lock_);

  for (auto i = timers_.begin(), e = timers_.end(); i != e; ++i) {
    if (i->handle.get() == handle) {
      timers_.erase(i);
      break;
    }
  }
}

void NativeScheduler::collectTimeouts() {
  const DateTime now = clock_->get();

  std::lock_guard<std::mutex> lk(lock_);

  for (;;) {
    if (timers_.empty())
      break;

    const Timer& job = timers_.front();

    if (job.when > now)
      break;

    tasks_.push_back(job.handle->getAction());
    timers_.pop_front();
  }
}

inline Scheduler::HandleRef registerInterest(
    std::mutex* registryLock,
    std::list<std::pair<int, Scheduler::HandleRef>>* registry,
    int fd,
    Executor::Task task) {

  auto onCancel = [=](Scheduler::Handle* h) {
    std::lock_guard<std::mutex> lk(*registryLock);
    for (auto i: *registry) {
      if (i.second.get() == h) {
        return registry->remove(i);
      }
    }
  };

  std::lock_guard<std::mutex> lk(*registryLock);
  auto handle = std::make_shared<Scheduler::Handle>(task, onCancel);
  registry->push_back(std::make_pair(fd, handle));

  return handle;
}

Scheduler::HandleRef NativeScheduler::executeOnReadable(int fd, Task task) {
  return registerInterest(&lock_, &readers_, fd, task);
}

Scheduler::HandleRef NativeScheduler::executeOnWritable(int fd, Task task) {
  return registerInterest(&lock_, &writers_, fd, task);
}

inline void collectActiveHandles(
    std::list<std::pair<int, Scheduler::HandleRef>>* interests,
    fd_set* fdset,
    std::vector<Scheduler::HandleRef>* result) {

  auto i = interests->begin();
  auto e = interests->end();

  while (i != e) {
    if (FD_ISSET(i->first, fdset)) {
      result->push_back(i->second);
      auto k = i;
      ++i;
      interests->erase(k);
    } else {
      i++;
    }
  }
}

size_t NativeScheduler::timerCount() {
  std::lock_guard<std::mutex> lk(lock_);
  return timers_.size();
}

size_t NativeScheduler::readerCount() {
  std::lock_guard<std::mutex> lk(lock_);
  return readers_.size();
}

size_t NativeScheduler::writerCount() {
  std::lock_guard<std::mutex> lk(lock_);
  return writers_.size();
}

void NativeScheduler::runLoopOnce() {
  fd_set input, output, error;
  FD_ZERO(&input);
  FD_ZERO(&output);
  FD_ZERO(&error);

  int wmark = 0;
  timeval tv;

  {
    std::lock_guard<std::mutex> lk(lock_);

    for (auto i: readers_) {
      FD_SET(i.first, &input);
      if (i.first > wmark) {
        wmark = i.first;
      }
    }

    for (auto i: writers_) {
      FD_SET(i.first, &output);
      if (i.first > wmark) {
        wmark = i.first;
      }
    }

    const TimeSpan nextTimeout = !tasks_.empty()
                               ? TimeSpan::Zero
                               : !timers_.empty()
                                 ? timers_.front().when - clock_->get()
                                 : TimeSpan::fromSeconds(4);

    tv.tv_sec = static_cast<time_t>(nextTimeout.totalSeconds()),
    tv.tv_usec = nextTimeout.microseconds();
  }

  FD_SET(wakeupPipe_[PIPE_READ_END], &input);

  int rv = ::select(wmark + 1, &input, &output, &error, &tv);
  if (rv < 0 && errno != EINTR)
    throw SYSTEM_ERROR(errno);

  if (FD_ISSET(wakeupPipe_[PIPE_READ_END], &input)) {
    bool consumeMore = true;
    while (consumeMore) {
      char buf[sizeof(int) * 128];
      consumeMore = ::read(wakeupPipe_[PIPE_READ_END], buf, sizeof(buf)) > 0;
    }
  }

  collectTimeouts();

  std::vector<HandleRef> activeHandles;
  activeHandles.reserve(rv);

  std::deque<Task> activeTasks;
  {
    std::lock_guard<std::mutex> lk(lock_);

    collectActiveHandles(&readers_, &input, &activeHandles);
    collectActiveHandles(&writers_, &output, &activeHandles);
    activeTasks = std::move(tasks_);
  }

  safeCall(onPreInvokePending_);
  safeCallEach(activeHandles);
  safeCallEach(activeTasks);
  safeCall(onPostInvokePending_);
}

void NativeScheduler::breakLoop() {
  int dummy = 42;
  ::write(wakeupPipe_[PIPE_WRITE_END], &dummy, sizeof(dummy));
}

} // namespace xzero
<|endoftext|>


<commit_before>#include "robot.hpp"

using namespace smartqq;

class CommonChat : public RobotPlugin {
public:
    CommonChat(smartqq::Robot& robot) : RobotPlugin(robot) {}
    void onMessage(const Message& message) {
        //Deal with new friend
        if (GetFriendMap().find(message.uid) == GetFriendMap().end()) {
            UpdateFriendList();
        }
        std::string name = GetFriendMap().at(message.uid).markname;
        if(name == "") name = GetFriendMap().at(message.uid).nickname;
        cout << "Message from " << name << ": "
            << message.content << endl;
    }

    void onGroupMessage(const GroupMessage& message) {
        std::string groupname;
        std::string username = std::to_string(message.uid);
        for (auto i : GetGroups()) {
            if (i.id == message.gid) {
                groupname = i.name;
                for (auto j : i.ginfo.users) {
                    if (j.uin == message.uid) {
                        username = j.card.empty()?j.card:j.nick;
                    }
                }
                break;
            }
        }
        if (groupname.empty()) {
            UpdateGroupList();

            for (auto i : GetGroups()) {
                if (i.id == message.gid) {
                    groupname = i.name;
                    for (auto j : i.ginfo.users) {
                        if (j.uin == message.uid) {
                            username = j.card.empty()?j.card:j.nick;
                        }
                    }
                    break;
                }
            }
        }
        if (groupname.empty()) groupname = "NOTFOUND";
        cout << "Group message from user " << username
            << " in group " << groupname
            << ": " << message.content << endl;
    }

    void onDiscussMessage(const smartqq::DiscussMessage& message) {
        std::string discussname;
        std::string username = std::to_string(message.uid);
        for (auto i : GetDiscusses()) {
            if (i.id == message.did) {
                discussname = i.name;
                for (auto j : i.dinfo.users) {
                    if(j.uin == message.uid) {
                        username = j.nick;
                    }
                }
                break;
            }
        }
        if (discussname.empty()) {
            UpdateDiscussList();

            for (auto i : GetDiscusses()) {
                if (i.id == message.did) {
                    discussname = i.name;
                    for (auto j : i.dinfo.users) {
                        if(j.uin == message.uid) {
                            username = j.nick;
                        }
                    }
                    break;
                }
            }
        }
        if (discussname.empty()) discussname = "NOTFOUND";
        cout << "Discuss message from user " << username
            << "in discuss " << discussname
            << ": " << message.content << endl;
    }
};

void SuperCallback::onMessage(const Message &message)
{
    for (auto p : plugins_) {
        p->onMessage(message);
    }
}

void SuperCallback::onGroupMessage(const GroupMessage &message)
{
    for (auto p : plugins_) {
        p->onGroupMessage(message);
    }
}

void SuperCallback::onDiscussMessage(const DiscussMessage &message)
{
    for (auto p : plugins_) {
        p->onDiscussMessage(message) ;
    }
}

Robot::Robot(SmartQQClient& client) : client_(client),
    callback_(plugins)
{
    AddPlugin(std::shared_ptr<RobotPlugin>(new CommonChat(*this)));
}

void Robot::AddPlugin(std::shared_ptr<RobotPlugin> plugin)
{
    plugins.push_back(plugin);
}

void Robot::AddPlugin(const std::list<std::shared_ptr<RobotPlugin>>& plugin_list)
{
    for (auto i : plugin_list) {
        plugins.push_back(i);
    }
}

void Robot::Run()
{
    client_.login();

    categories_ = client_.getFriendListWithCategory(friendMap_);
    groups_ = client_.getGroupList();

    for (auto& i : groups_) {
        i.ginfo = client_.getGroupInfo(i.code);
    }

    discusses_ = client_.getDiscussList();

    for (auto& i : discusses_) {
        i.dinfo = client_.getDiscussInfo(i.id);
    }

    client_.startPolling(callback_);
}

<commit_msg>[FIX] Add blank.<commit_after>#include "robot.hpp"

using namespace smartqq;

class CommonChat : public RobotPlugin {
public:
    CommonChat(smartqq::Robot& robot) : RobotPlugin(robot) {}
    void onMessage(const Message& message) {
        //Deal with new friend
        if (GetFriendMap().find(message.uid) == GetFriendMap().end()) {
            UpdateFriendList();
        }
        std::string name = GetFriendMap().at(message.uid).markname;
        if(name == "") name = GetFriendMap().at(message.uid).nickname;
        cout << "Message from " << name << ": "
            << message.content << endl;
    }

    void onGroupMessage(const GroupMessage& message) {
        std::string groupname;
        std::string username = std::to_string(message.uid);
        for (auto i : GetGroups()) {
            if (i.id == message.gid) {
                groupname = i.name;
                for (auto j : i.ginfo.users) {
                    if (j.uin == message.uid) {
                        username = j.card.empty()?j.card:j.nick;
                    }
                }
                break;
            }
        }
        if (groupname.empty()) {
            UpdateGroupList();

            for (auto i : GetGroups()) {
                if (i.id == message.gid) {
                    groupname = i.name;
                    for (auto j : i.ginfo.users) {
                        if (j.uin == message.uid) {
                            username = j.card.empty()?j.card:j.nick;
                        }
                    }
                    break;
                }
            }
        }
        if (groupname.empty()) groupname = "NOTFOUND";
        cout << "Group message from user " << username
            << " in group " << groupname
            << ": " << message.content << endl;
    }

    void onDiscussMessage(const smartqq::DiscussMessage& message) {
        std::string discussname;
        std::string username = std::to_string(message.uid);
        for (auto i : GetDiscusses()) {
            if (i.id == message.did) {
                discussname = i.name;
                for (auto j : i.dinfo.users) {
                    if(j.uin == message.uid) {
                        username = j.nick;
                    }
                }
                break;
            }
        }
        if (discussname.empty()) {
            UpdateDiscussList();

            for (auto i : GetDiscusses()) {
                if (i.id == message.did) {
                    discussname = i.name;
                    for (auto j : i.dinfo.users) {
                        if(j.uin == message.uid) {
                            username = j.nick;
                        }
                    }
                    break;
                }
            }
        }
        if (discussname.empty()) discussname = "NOTFOUND";
        cout << "Discuss message from user " << username
            << " in discuss " << discussname
            << ": " << message.content << endl;
    }
};

void SuperCallback::onMessage(const Message &message)
{
    for (auto p : plugins_) {
        p->onMessage(message);
    }
}

void SuperCallback::onGroupMessage(const GroupMessage &message)
{
    for (auto p : plugins_) {
        p->onGroupMessage(message);
    }
}

void SuperCallback::onDiscussMessage(const DiscussMessage &message)
{
    for (auto p : plugins_) {
        p->onDiscussMessage(message) ;
    }
}

Robot::Robot(SmartQQClient& client) : client_(client),
    callback_(plugins)
{
    AddPlugin(std::shared_ptr<RobotPlugin>(new CommonChat(*this)));
}

void Robot::AddPlugin(std::shared_ptr<RobotPlugin> plugin)
{
    plugins.push_back(plugin);
}

void Robot::AddPlugin(const std::list<std::shared_ptr<RobotPlugin>>& plugin_list)
{
    for (auto i : plugin_list) {
        plugins.push_back(i);
    }
}

void Robot::Run()
{
    client_.login();

    categories_ = client_.getFriendListWithCategory(friendMap_);
    groups_ = client_.getGroupList();

    for (auto& i : groups_) {
        i.ginfo = client_.getGroupInfo(i.code);
    }

    discusses_ = client_.getDiscussList();

    for (auto& i : discusses_) {
        i.dinfo = client_.getDiscussInfo(i.id);
    }

    client_.startPolling(callback_);
}

<|endoftext|>


<commit_before>//===-- MSP430Subtarget.cpp - MSP430 Subtarget Information ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the MSP430 specific subclass of TargetSubtargetInfo.
//
//===----------------------------------------------------------------------===//

#include "MSP430Subtarget.h"
#include "MSP430.h"
#include "llvm/Support/TargetRegistry.h"

using namespace llvm;

#define DEBUG_TYPE "msp430-subtarget"

#define GET_SUBTARGETINFO_TARGET_DESC
#define GET_SUBTARGETINFO_CTOR
#include "MSP430GenSubtargetInfo.inc"

void MSP430Subtarget::anchor() { }

MSP430Subtarget &MSP430Subtarget::initializeSubtargetDependencies(StringRef CPU, StringRef FS) {
  ParseSubtargetFeatures("generic", FS);
  return *this;
}

MSP430Subtarget::MSP430Subtarget(const std::string &TT, const std::string &CPU,
                                 const std::string &FS, const TargetMachine &TM)
    : MSP430GenSubtargetInfo(TT, CPU, FS), FrameLowering(),
      InstrInfo(initializeSubtargetDependencies(CPU, FS)), TLInfo(TM, *this),
      TSInfo(*TM.getDataLayout()) {}
<commit_msg>80-column fixup.<commit_after>//===-- MSP430Subtarget.cpp - MSP430 Subtarget Information ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the MSP430 specific subclass of TargetSubtargetInfo.
//
//===----------------------------------------------------------------------===//

#include "MSP430Subtarget.h"
#include "MSP430.h"
#include "llvm/Support/TargetRegistry.h"

using namespace llvm;

#define DEBUG_TYPE "msp430-subtarget"

#define GET_SUBTARGETINFO_TARGET_DESC
#define GET_SUBTARGETINFO_CTOR
#include "MSP430GenSubtargetInfo.inc"

void MSP430Subtarget::anchor() { }

MSP430Subtarget &
MSP430Subtarget::initializeSubtargetDependencies(StringRef CPU, StringRef FS) {
  ParseSubtargetFeatures("generic", FS);
  return *this;
}

MSP430Subtarget::MSP430Subtarget(const std::string &TT, const std::string &CPU,
                                 const std::string &FS, const TargetMachine &TM)
    : MSP430GenSubtargetInfo(TT, CPU, FS), FrameLowering(),
      InstrInfo(initializeSubtargetDependencies(CPU, FS)), TLInfo(TM, *this),
      TSInfo(*TM.getDataLayout()) {}
<|endoftext|>


<commit_before>/* The Halfling Project - A Graphics Engine and Projects
 *
 * The Halfling Project is the legal property of Adrian Astley
 * Copyright Adrian Astley 2013 - 2014
 */

#include "obj_loader_demo/obj_loader_demo.h"

namespace ObjLoaderDemo {

LRESULT ObjLoaderDemo::MsgProc(HWND hwnd, uint msg, WPARAM wParam, LPARAM lParam) {
	// Send event message to AntTweakBar
	if (TwEventWin(hwnd, msg, wParam, lParam)) {
		return 0;    // Event has been handled by AntTweakBar
	}

	// Let the base engine handle any events that we don't handle
	return Halfling::HalflingEngine::MsgProc(hwnd, msg, wParam, lParam);
}

ObjLoaderDemo::ObjLoaderDemo(HINSTANCE hinstance)
	: Halfling::HalflingEngine(hinstance),
	  m_nearClip(0.1f),
	  m_farClip(5000.0f),
	  m_globalWorldTransform(DirectX::XMMatrixIdentity()),
	  m_camera(0.5f * DirectX::XM_PI, 0.45f * DirectX::XM_PI, 100.0f),
	  m_showConsole(false),
	  m_instanceBuffer(nullptr),
	  m_sceneLoaded(false),
	  m_sceneIsSetup(false),
	  m_sceneScaleFactor(0.0f),
	  m_modelInstanceThreshold(100u),
	  m_pointLightBufferNeedsRebuild(false),
	  m_spotLightBufferNeedsRebuild(false),
	  m_vsync(false),
	  m_wireframe(false),
	  m_animateLights(true),
	  m_shadingType(ShadingType::NoCullDeferred),
	  m_gbufferSelector(GBufferSelector::None),
	  m_showLightLocations(false),
	  m_showGBuffers(false),
	  m_numPointLightsToDraw(100),
	  m_numSpotLightsToDraw(100),
	  m_renderTargetView(nullptr),
	  m_depthStencilBuffer(nullptr),
	  m_defaultInputLayout(nullptr),
	  m_debugObjectInputLayout(nullptr),
	  m_pointLightBuffer(nullptr),
	  m_spotLightBuffer(nullptr),
	  m_gbufferVertexShader(nullptr),
	  m_gbufferPixelShader(nullptr),
	  m_fullscreenTriangleVertexShader(nullptr),
	  m_noCullFinalGatherPixelShader(nullptr),
	  m_debugObjectVertexShader(nullptr),
	  m_debugObjectPixelShader(nullptr),
	  m_transformedFullscreenTriangleVertexShader(nullptr),
	  m_renderGbuffersPixelShader(nullptr) {
}

void ObjLoaderDemo::Shutdown() {
	// Release in the opposite order we initialized in
	delete m_pointLightBuffer;
	delete m_spotLightBuffer;
	delete m_instanceBuffer;
	delete m_frameMaterialListBuffer;
	delete(m_forwardVertexShader);
	delete(m_forwardPixelShader);
	delete(m_gbufferVertexShader);
	delete(m_gbufferPixelShader);
	delete(m_fullscreenTriangleVertexShader);
	delete(m_noCullFinalGatherPixelShader);
	delete(m_debugObjectVertexShader);
	delete(m_debugObjectPixelShader);
	delete(m_transformedFullscreenTriangleVertexShader);
	delete(m_renderGbuffersPixelShader);
	ReleaseCOM(m_defaultInputLayout);
	ReleaseCOM(m_debugObjectInputLayout);

	for (auto iter = m_pointLightAnimators.begin(); iter != m_pointLightAnimators.end(); ++iter) {
		delete *iter;
	}
	for (auto iter = m_spotLightAnimators.begin(); iter != m_spotLightAnimators.end(); ++iter) {
		delete *iter;
	}
	for (auto iter = m_gBuffers.begin(); iter != m_gBuffers.end(); ++iter) {
		delete *iter;
	}

	delete m_depthStencilBuffer;
	ReleaseCOM(m_renderTargetView);

	if (m_sceneLoaderThread.joinable()) {
		m_sceneLoaderThread.detach();
	}

	TwTerminate();

	Halfling::HalflingEngine::Shutdown();
}

void ObjLoaderDemo::OnResize() {
	if (!m_d3dInitialized) {
		return;
	}

	// Update the projection matrix
	// We swap near and far clip because we are using 1 - depth in our depth buffer
	m_camera.UpdateProjectionMatrix((float)m_clientWidth, (float)m_clientHeight, m_farClip, m_nearClip);

	// Release the gBuffers
	for (auto gbuffer : m_gBuffers) {
		delete gbuffer;
	}
	m_gBuffers.clear();
	m_gBufferRTVs.clear();
	m_gBufferSRVs.clear();

	// Release the old views and the old depth/stencil buffer.
	ReleaseCOM(m_renderTargetView);
	delete m_depthStencilBuffer;
	m_depthStencilBuffer = nullptr;

	// Resize the swap chain and recreate the render target view.
	HR(m_swapChain->ResizeBuffers(2, m_clientWidth, m_clientHeight, DXGI_FORMAT_R8G8B8A8_UNORM, 0));

	// Recreate the render target view.
	ID3D11Texture2D *backBuffer;
	HR(m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void **>(&backBuffer)));
	HR(m_device->CreateRenderTargetView(backBuffer, 0, &m_renderTargetView));
	ReleaseCOM(backBuffer);

	// Create the depth/stencil buffer and view.
	DXGI_SAMPLE_DESC sampleDesc;

	// Use MSAA?
	if (m_msaaCount > 1) {
		uint msaaQuality;
		HR(m_device->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM, m_msaaCount, &msaaQuality));
		assert(msaaQuality > 0);

		sampleDesc.Count = m_msaaCount;
		sampleDesc.Quality = msaaQuality - 1;
	} else {
		sampleDesc.Count = 1;
		sampleDesc.Quality = 0;
	}

	m_depthStencilBuffer = new Common::Depth2D(m_device, m_clientWidth, m_clientHeight,
											   D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE,
											   sampleDesc, m_stencil);

	// Create the gBuffers
	// Diffuse Albedo
	m_gBuffers.push_back(new Common::Texture2D(m_device, m_clientWidth, m_clientHeight,
		DXGI_FORMAT_R11G11B10_FLOAT,
		D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE,
		sampleDesc));

	// Specular Albedo and Spec Power
	m_gBuffers.push_back(new Common::Texture2D(m_device, m_clientWidth, m_clientHeight,
		DXGI_FORMAT_R8G8B8A8_UNORM,
		D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE,
		sampleDesc));

	// Normal
	m_gBuffers.push_back(new Common::Texture2D(m_device, m_clientWidth, m_clientHeight,
		DXGI_FORMAT_R16G16_FLOAT,
		D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE,
		sampleDesc));

	// Set up GBuffer resource list
	size_t size = m_gBuffers.size();
	m_gBufferRTVs.resize(size, 0);
	m_gBufferSRVs.resize(size + 1, 0);
	for (std::size_t i = 0; i < size; ++i) {
		m_gBufferRTVs[i] = m_gBuffers[i]->GetRenderTarget();
		m_gBufferSRVs[i] = m_gBuffers[i]->GetShaderResource();
	}

	// Add the depth buffer as a SRV for the Compute Shader
	m_gBufferSRVs.back() = m_depthStencilBuffer->GetShaderResource();

	// Set the viewport transform.
	m_screenViewport.TopLeftX = 0;
	m_screenViewport.TopLeftY = 0;
	m_screenViewport.Width = static_cast<float>(m_clientWidth);
	m_screenViewport.Height = static_cast<float>(m_clientHeight);
	m_screenViewport.MinDepth = 0.0f;
	m_screenViewport.MaxDepth = 1.0f;

	m_immediateContext->RSSetViewports(1, &m_screenViewport);
}

void ObjLoaderDemo::MouseDown(WPARAM buttonState, int x, int y) {
	m_mouseLastPos.x = x;
	m_mouseLastPos.y = y;

	SetCapture(m_hwnd);
}

void ObjLoaderDemo::MouseUp(WPARAM buttonState, int x, int y) {
	ReleaseCapture();
}

void ObjLoaderDemo::MouseMove(WPARAM buttonState, int x, int y) {
	if ((buttonState & MK_LBUTTON) != 0) {
		if (GetKeyState(VK_MENU) & 0x8000) {
			// Calculate the new phi and theta based on mouse position relative to where the user clicked
			float dPhi = ((float)(m_mouseLastPos.y - y) / 300);
			float dTheta = ((float)(m_mouseLastPos.x - x) / 300);

			m_camera.Rotate(-dTheta, dPhi);
		}
	} else if ((buttonState & MK_MBUTTON) != 0) {
		if (GetKeyState(VK_MENU) & 0x8000) {
			float dx = ((float)(m_mouseLastPos.x - x) / 10);
			float dy = ((float)(m_mouseLastPos.y - y) / 10);

			m_camera.Pan(-dx, dy);
		}
	}

	m_mouseLastPos.x = x;
	m_mouseLastPos.y = y;
}

void ObjLoaderDemo::MouseWheel(int zDelta) {
	// Make each wheel dedent correspond to a size based on the scene
	m_camera.Zoom(0.1f * (float)zDelta);
}

void ObjLoaderDemo::CharacterInput(wchar character) {
	if (m_showConsole) {
		m_console.InputCharacter(character);
	}
}

} // End of namespace ObjLoaderDemo
<commit_msg>OBJ_LOADER_DEMO: Fix memory leak<commit_after>/* The Halfling Project - A Graphics Engine and Projects
 *
 * The Halfling Project is the legal property of Adrian Astley
 * Copyright Adrian Astley 2013 - 2014
 */

#include "obj_loader_demo/obj_loader_demo.h"

namespace ObjLoaderDemo {

LRESULT ObjLoaderDemo::MsgProc(HWND hwnd, uint msg, WPARAM wParam, LPARAM lParam) {
	// Send event message to AntTweakBar
	if (TwEventWin(hwnd, msg, wParam, lParam)) {
		return 0;    // Event has been handled by AntTweakBar
	}

	// Let the base engine handle any events that we don't handle
	return Halfling::HalflingEngine::MsgProc(hwnd, msg, wParam, lParam);
}

ObjLoaderDemo::ObjLoaderDemo(HINSTANCE hinstance)
	: Halfling::HalflingEngine(hinstance),
	  m_nearClip(0.1f),
	  m_farClip(5000.0f),
	  m_globalWorldTransform(DirectX::XMMatrixIdentity()),
	  m_camera(0.5f * DirectX::XM_PI, 0.45f * DirectX::XM_PI, 100.0f),
	  m_showConsole(false),
	  m_instanceBuffer(nullptr),
	  m_sceneLoaded(false),
	  m_sceneIsSetup(false),
	  m_sceneScaleFactor(0.0f),
	  m_modelInstanceThreshold(100u),
	  m_pointLightBufferNeedsRebuild(false),
	  m_spotLightBufferNeedsRebuild(false),
	  m_vsync(false),
	  m_wireframe(false),
	  m_animateLights(true),
	  m_shadingType(ShadingType::NoCullDeferred),
	  m_gbufferSelector(GBufferSelector::None),
	  m_showLightLocations(false),
	  m_showGBuffers(false),
	  m_numPointLightsToDraw(100),
	  m_numSpotLightsToDraw(100),
	  m_renderTargetView(nullptr),
	  m_depthStencilBuffer(nullptr),
	  m_defaultInputLayout(nullptr),
	  m_debugObjectInputLayout(nullptr),
	  m_pointLightBuffer(nullptr),
	  m_spotLightBuffer(nullptr),
	  m_gbufferVertexShader(nullptr),
	  m_gbufferPixelShader(nullptr),
	  m_fullscreenTriangleVertexShader(nullptr),
	  m_noCullFinalGatherPixelShader(nullptr),
	  m_debugObjectVertexShader(nullptr),
	  m_debugObjectPixelShader(nullptr),
	  m_transformedFullscreenTriangleVertexShader(nullptr),
	  m_renderGbuffersPixelShader(nullptr) {
}

void ObjLoaderDemo::Shutdown() {
	// Release in the opposite order we initialized in
	delete m_pointLightBuffer;
	delete m_spotLightBuffer;
	delete m_instanceBuffer;
	delete m_frameMaterialListBuffer;
	delete(m_forwardVertexShader);
	delete(m_instancedForwardVertexShader);
	delete(m_forwardPixelShader);
	delete(m_gbufferVertexShader);
	delete(m_gbufferPixelShader);
	delete(m_fullscreenTriangleVertexShader);
	delete(m_noCullFinalGatherPixelShader);
	delete(m_debugObjectVertexShader);
	delete(m_debugObjectPixelShader);
	delete(m_transformedFullscreenTriangleVertexShader);
	delete(m_renderGbuffersPixelShader);
	ReleaseCOM(m_defaultInputLayout);
	ReleaseCOM(m_debugObjectInputLayout);

	for (auto iter = m_pointLightAnimators.begin(); iter != m_pointLightAnimators.end(); ++iter) {
		delete *iter;
	}
	for (auto iter = m_spotLightAnimators.begin(); iter != m_spotLightAnimators.end(); ++iter) {
		delete *iter;
	}
	for (auto iter = m_gBuffers.begin(); iter != m_gBuffers.end(); ++iter) {
		delete *iter;
	}

	delete m_depthStencilBuffer;
	ReleaseCOM(m_renderTargetView);

	if (m_sceneLoaderThread.joinable()) {
		m_sceneLoaderThread.detach();
	}

	TwTerminate();

	Halfling::HalflingEngine::Shutdown();
}

void ObjLoaderDemo::OnResize() {
	if (!m_d3dInitialized) {
		return;
	}

	// Update the projection matrix
	// We swap near and far clip because we are using 1 - depth in our depth buffer
	m_camera.UpdateProjectionMatrix((float)m_clientWidth, (float)m_clientHeight, m_farClip, m_nearClip);

	// Release the gBuffers
	for (auto gbuffer : m_gBuffers) {
		delete gbuffer;
	}
	m_gBuffers.clear();
	m_gBufferRTVs.clear();
	m_gBufferSRVs.clear();

	// Release the old views and the old depth/stencil buffer.
	ReleaseCOM(m_renderTargetView);
	delete m_depthStencilBuffer;
	m_depthStencilBuffer = nullptr;

	// Resize the swap chain and recreate the render target view.
	HR(m_swapChain->ResizeBuffers(2, m_clientWidth, m_clientHeight, DXGI_FORMAT_R8G8B8A8_UNORM, 0));

	// Recreate the render target view.
	ID3D11Texture2D *backBuffer;
	HR(m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void **>(&backBuffer)));
	HR(m_device->CreateRenderTargetView(backBuffer, 0, &m_renderTargetView));
	ReleaseCOM(backBuffer);

	// Create the depth/stencil buffer and view.
	DXGI_SAMPLE_DESC sampleDesc;

	// Use MSAA?
	if (m_msaaCount > 1) {
		uint msaaQuality;
		HR(m_device->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM, m_msaaCount, &msaaQuality));
		assert(msaaQuality > 0);

		sampleDesc.Count = m_msaaCount;
		sampleDesc.Quality = msaaQuality - 1;
	} else {
		sampleDesc.Count = 1;
		sampleDesc.Quality = 0;
	}

	m_depthStencilBuffer = new Common::Depth2D(m_device, m_clientWidth, m_clientHeight,
											   D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE,
											   sampleDesc, m_stencil);

	// Create the gBuffers
	// Diffuse Albedo
	m_gBuffers.push_back(new Common::Texture2D(m_device, m_clientWidth, m_clientHeight,
		DXGI_FORMAT_R11G11B10_FLOAT,
		D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE,
		sampleDesc));

	// Specular Albedo and Spec Power
	m_gBuffers.push_back(new Common::Texture2D(m_device, m_clientWidth, m_clientHeight,
		DXGI_FORMAT_R8G8B8A8_UNORM,
		D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE,
		sampleDesc));

	// Normal
	m_gBuffers.push_back(new Common::Texture2D(m_device, m_clientWidth, m_clientHeight,
		DXGI_FORMAT_R16G16_FLOAT,
		D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE,
		sampleDesc));

	// Set up GBuffer resource list
	size_t size = m_gBuffers.size();
	m_gBufferRTVs.resize(size, 0);
	m_gBufferSRVs.resize(size + 1, 0);
	for (std::size_t i = 0; i < size; ++i) {
		m_gBufferRTVs[i] = m_gBuffers[i]->GetRenderTarget();
		m_gBufferSRVs[i] = m_gBuffers[i]->GetShaderResource();
	}

	// Add the depth buffer as a SRV for the Compute Shader
	m_gBufferSRVs.back() = m_depthStencilBuffer->GetShaderResource();

	// Set the viewport transform.
	m_screenViewport.TopLeftX = 0;
	m_screenViewport.TopLeftY = 0;
	m_screenViewport.Width = static_cast<float>(m_clientWidth);
	m_screenViewport.Height = static_cast<float>(m_clientHeight);
	m_screenViewport.MinDepth = 0.0f;
	m_screenViewport.MaxDepth = 1.0f;

	m_immediateContext->RSSetViewports(1, &m_screenViewport);
}

void ObjLoaderDemo::MouseDown(WPARAM buttonState, int x, int y) {
	m_mouseLastPos.x = x;
	m_mouseLastPos.y = y;

	SetCapture(m_hwnd);
}

void ObjLoaderDemo::MouseUp(WPARAM buttonState, int x, int y) {
	ReleaseCapture();
}

void ObjLoaderDemo::MouseMove(WPARAM buttonState, int x, int y) {
	if ((buttonState & MK_LBUTTON) != 0) {
		if (GetKeyState(VK_MENU) & 0x8000) {
			// Calculate the new phi and theta based on mouse position relative to where the user clicked
			float dPhi = ((float)(m_mouseLastPos.y - y) / 300);
			float dTheta = ((float)(m_mouseLastPos.x - x) / 300);

			m_camera.Rotate(-dTheta, dPhi);
		}
	} else if ((buttonState & MK_MBUTTON) != 0) {
		if (GetKeyState(VK_MENU) & 0x8000) {
			float dx = ((float)(m_mouseLastPos.x - x) / 10);
			float dy = ((float)(m_mouseLastPos.y - y) / 10);

			m_camera.Pan(-dx, dy);
		}
	}

	m_mouseLastPos.x = x;
	m_mouseLastPos.y = y;
}

void ObjLoaderDemo::MouseWheel(int zDelta) {
	// Make each wheel dedent correspond to a size based on the scene
	m_camera.Zoom(0.1f * (float)zDelta);
}

void ObjLoaderDemo::CharacterInput(wchar character) {
	if (m_showConsole) {
		m_console.InputCharacter(character);
	}
}

} // End of namespace ObjLoaderDemo
<|endoftext|>