<commit_before>/* ****************************************************************************
*
* FILE                     main_samsonWorker.cpp
*
* AUTHOR                   Ken Zangelin
*
* CREATION DATE            Dec 14 2010
*
*/
#include "parseArgs/parseArgs.h"
#include "parseArgs/paIsSet.h"
#include "logMsg/logMsg.h"
#include "parseArgs/paConfig.h"
#include "logMsg/traceLevels.h"

#include <signal.h>

#include "au/LockDebugger.h"            // au::LockDebugger
#include "au/ThreadManager.h"

#include "engine/MemoryManager.h"
#include "engine/Engine.h"
#include "engine/DiskManager.h"
#include "engine/ProcessManager.h"

#include "samson/common/samsonVersion.h"
#include "samson/common/samsonVars.h"
#include "samson/common/SamsonSetup.h"
#include "samson/common/daemonize.h"
#include "samson/common/MemoryCheck.h"
#include "samson/network/WorkerNetwork.h"
#include "samson/worker/SamsonWorker.h"
#include "samson/isolated/SharedMemoryManager.h"
#include "samson/stream/BlockManager.h"
#include "samson/module/ModulesManager.h"

/* ****************************************************************************
*
* Option variables
*/
SAMSON_ARG_VARS;

bool     fg;
bool     noLog;
int      valgrind;
int      port;
int      web_port;

/* ****************************************************************************
*
* parse arguments
*/
PaArgument paArgs[] =
{
    SAMSON_ARGS,
    { "-fg",        &fg,        "SAMSON_WORKER_FOREGROUND", PaBool, PaOpt, false,                  false,  true,  "don't start as daemon"             },
    { "-port",      &port,      "",                         PaInt,  PaOpt, SAMSON_WORKER_PORT,     1,      9999,  "Port to receive new connections"   },
    { "-web_port",  &web_port,  "",                         PaInt,  PaOpt, SAMSON_WORKER_WEB_PORT, 1,      9999,  "Port to receive new connections"   },
    { "-nolog",     &noLog,     "SAMSON_WORKER_NO_LOG",     PaBool, PaOpt, false,                  false,  true,  "no logging"                        },
    { "-valgrind",  &valgrind,  "SAMSON_WORKER_VALGRIND",   PaInt,  PaOpt, 0,                      0,        20,  "help valgrind debug process"       },

    PA_END_OF_ARGS
};

/* ****************************************************************************
*
* global variables
*/
int                           logFd             = -1;
samson::SamsonWorker*         worker            = NULL;
au::LockDebugger*             lockDebugger      = NULL;
engine::SharedMemoryManager*  smManager         = NULL;

/* ****************************************************************************
*
* man texts -
*/
static const char* manSynopsis         = " [OPTION]";
static const char* manShortDescription = "samsond is the main process in a SAMSON system.\n\n";
static const char* manDescription      =
    "\n"
    "samsond is the main process in a SAMSON system. All the nodes in the cluster has its own samsonWorker process\n"
    "All samsond processes are responsible for processing a segment of available data"
    "All clients of the platform ( delila's ) are connected to all samsonWorkers in the system"
    "See samson documentation to get more information about how to get a SAMSON system up and running"
    "\n";

static const char* manExitStatus    = "0      if OK\n 1-255  error\n";
static const char* manAuthor        = "Written by Andreu Urruela, Ken Zangelin and J.Gregorio Escalada.";
static const char* manReportingBugs = "bugs to samson-dev@tid.es\n";
static const char* manCopyright     = "Copyright (C) 2011 Telefonica Investigacion y Desarrollo";
static const char* manVersion       = SAMSON_VERSION;

void captureSIGINT( int s )
{
    s = 3;
    LM_X(1, ("Signal SIGINT"));
}

void captureSIGPIPE( int s )
{
    s = 3;
    LM_M(("Captured SIGPIPE"));
}

void captureSIGTERM( int s )
{
    s = 3;
    LM_M(("Captured SIGTERM"));

    LM_M(("Cleaning up"));
    std::string pid_file_name = au::str("%s/samsond.pid" , paLogFilePath );
    if ( remove (pid_file_name.c_str()) != 0)
    {
        LM_W(("Error deleting the pid file %s", pid_file_name.c_str() ));
    }
    exit(1);
}

void cleanup(void)
{
    google::protobuf::ShutdownProtobufLibrary();

    printf("Shutting down worker components (worker at %p)\n", worker);
    if (worker)
    {
        printf("deleting worker\n");
        delete worker;
    }

    printf("Shutting down LockDebugger\n");
    au::LockDebugger::destroy();

    if (smManager != NULL)
    {
        printf("Shutting down Shared Memory Manager\n");
        delete smManager;
        smManager = NULL;
    }

    printf("Shutting down SamsonSetup\n");
    samson::SamsonSetup::destroy();

    printf("destroying ProcessManager\n");
    engine::ProcessManager::destroy();

    printf("destroying DiskManager\n");
    engine::DiskManager::destroy();

    printf("destroying MemoryManager\n");
    engine::MemoryManager::destroy();

    printf("destroying Engine\n");
    engine::Engine::destroy();

    printf("destroying ModulesManager\n");
    samson::ModulesManager::destroy();

    paConfigCleanup();
    lmCleanProgName();
}

static void valgrindExit(int v)
{
    if (v == valgrind)
    {
        LM_M(("Valgrind option is %d - I exit", v));
        exit(0);
    }
}

/* ****************************************************************************
*
* main -
*/
int main(int argC, const char *argV[])
{
    atexit(cleanup);

    paConfig("builtin prefix",                (void*) "SS_WORKER_");
    paConfig("usage and exit on any warning", (void*) true);

    // Andreu: samsonWorker is not a console in foreground (debug) mode ( to ask to status with commands )
    paConfig("log to screen",                 (void*) "only errors");
    //paConfig("log to screen",                 (void*) (void*) false);

    paConfig("log file line format",          (void*) "TYPE:DATE:EXEC-AUX/FILE[LINE](p.PID)(t.TID) FUNC: TEXT");
    paConfig("screen line format",            (void*) "TYPE@TIME  EXEC: TEXT");
    paConfig("log to file",                   (void*) true);

    paConfig("man synopsis",                  (void*) manSynopsis);
    paConfig("man shortdescription",          (void*) manShortDescription);
    paConfig("man description",               (void*) manDescription);
    paConfig("man exitstatus",                (void*) manExitStatus);
    paConfig("man author",                    (void*) manAuthor);
    paConfig("man reportingbugs",             (void*) manReportingBugs);
    paConfig("man copyright",                 (void*) manCopyright);
    paConfig("man version",                   (void*) manVersion);

    const char* extra = paIsSetSoGet(argC, (char**) argV, "-port");
    paParse(paArgs, argC, (char**) argV, 1, false, extra);

    valgrindExit(1);

    lmAux((char*) "father");

    LM_V(("Started with arguments:"));
    for (int ix = 0; ix < argC; ix++)
        LM_V(("  %02d: '%s'", ix, argV[ix]));

    logFd = lmFirstDiskFileDescriptor();

    // Capturing SIGPIPE
    if (signal(SIGPIPE, captureSIGPIPE) == SIG_ERR)
        LM_W(("SIGPIPE cannot be handled"));

    if (signal(SIGINT, captureSIGINT) == SIG_ERR)
        LM_W(("SIGINT cannot be handled"));

    if (signal(SIGTERM, captureSIGTERM) == SIG_ERR)
        LM_W(("SIGTERM cannot be handled"));

    // Init basic setup stuff (necessary for memory check)
    lockDebugger = au::LockDebugger::shared();  // VALGRIND complains ...
    samson::SamsonSetup::init(samsonHome, samsonWorking);          // Load setup and create default directories

    valgrindExit(2);

    // Check to see if the current memory configuration is ok or not
    if (samson::MemoryCheck() == false)
        LM_X(1,("Insufficient memory configured. Check %ssamsonWorkerLog for more information.", paLogFilePath));

    if (fg == false)
    {
        std::cout << "OK. samsonWorker is now working in background.\n";
        daemonize();
    }

    valgrindExit(3);
    // ------------------------------------------------------
    // Write pid in /var/log/samson/samsond.pid
    // ------------------------------------------------------

    char pid_file_name[256];
    snprintf(pid_file_name, sizeof(pid_file_name), "%s/samsond.pid", paLogFilePath);
    FILE *file = fopen(pid_file_name, "w");
    if (!file)
        LM_X(1, ("Error opening file '%s' to store pid", pid_file_name));
    int pid = (int) getpid();
    if (fprintf(file, "%d" , pid) == 0)
       LM_X(1,("Error writing pid %d to file %s", pid, pid_file_name));
    fclose(file);
    // ------------------------------------------------------

    // Make sure this singleton is created just once
    LM_D(("createWorkingDirectories"));
    samson::SamsonSetup::shared()->createWorkingDirectories();      // Create working directories

    valgrindExit(4);
    LM_D(("engine::Engine::init"));
    engine::Engine::init();

    valgrindExit(5);
    LM_D(("engine::SharedMemoryManager::init"));
    engine::SharedMemoryManager::init(samson::SamsonSetup::shared()->getInt("general.num_processess") , samson::SamsonSetup::shared()->getUInt64("general.shared_memory_size_per_buffer")); // VALGRIND complains ...
    smManager = engine::SharedMemoryManager::shared();

    valgrindExit(6);
    LM_D(("engine::DiskManager::init"));
    engine::DiskManager::init(1);

    valgrindExit(7);
    LM_D(("engine::ProcessManager::init"));
    engine::ProcessManager::init(samson::SamsonSetup::shared()->getInt("general.num_processess"));

    valgrindExit(8);
    LM_D(("engine::MemoryManager::init"));
    engine::MemoryManager::init(samson::SamsonSetup::shared()->getUInt64("general.memory"));

    valgrindExit(9);
    LM_D(("samson::ModulesManager::init"));
    samson::ModulesManager::init();

    valgrindExit(10);
    LM_D(("samson::stream::BlockManager::init"));
    samson::stream::BlockManager::init();

    valgrindExit(11);

    // Instance of network object and initialization
    // --------------------------------------------------------------------
    samson::WorkerNetwork*  networkP  = new samson::WorkerNetwork(port, web_port);

    valgrindExit(12);

    // Instance of SamsonWorker object (network contains at least the number of workers)
    // -----------------------------------------------------------------------------------
    worker = new samson::SamsonWorker(networkP);

    LM_M(("Worker Running"));
    LM_D(("worker at %p", worker));
    valgrindExit(13);

    if (fg == false)
    {
        while (true)
            sleep(10);
    }

    worker->runConsole();

    LM_D(("Worker Cleanup"));

    if (worker)
        delete worker;

    google::protobuf::ShutdownProtobufLibrary();

    // ------------------------------------------------------------------------
    // Close everything
    // ------------------------------------------------------------------------

    samson::ModulesManager::destroy();

    engine::ProcessManager::destroy();
    engine::DiskManager::destroy();
    engine::MemoryManager::destroy();
    engine::Engine::destroy();

    samson::SamsonSetup::destroy();

    // Check background threads
    au::StringVector background_threads = au::ThreadManager::shared()->getThreadNames();
    if( background_threads.size() > 0 )
    {
        LM_W(("Still %lu background threads running (%s)" , background_threads.size() , background_threads.str().c_str() ));
        std::cerr << au::ThreadManager::shared()->str();
    }
    else
        LM_M(("Finished correctly with 0 background processes"));

    return 0;
}
<commit_msg>SAMSON-988 NETDATANA-92 Changing samsond.pid from paLogFilePath to paLogDir (this last one is controlled by SS_WORKER_LOG_DIR<commit_after>/* ****************************************************************************
*
* FILE                     main_samsonWorker.cpp
*
* AUTHOR                   Ken Zangelin
*
* CREATION DATE            Dec 14 2010
*
*/
#include "parseArgs/parseArgs.h"
#include "parseArgs/paIsSet.h"
#include "logMsg/logMsg.h"
#include "parseArgs/paConfig.h"
#include "logMsg/traceLevels.h"

#include <signal.h>

#include "au/LockDebugger.h"            // au::LockDebugger
#include "au/ThreadManager.h"

#include "engine/MemoryManager.h"
#include "engine/Engine.h"
#include "engine/DiskManager.h"
#include "engine/ProcessManager.h"

#include "samson/common/samsonVersion.h"
#include "samson/common/samsonVars.h"
#include "samson/common/SamsonSetup.h"
#include "samson/common/daemonize.h"
#include "samson/common/MemoryCheck.h"
#include "samson/network/WorkerNetwork.h"
#include "samson/worker/SamsonWorker.h"
#include "samson/isolated/SharedMemoryManager.h"
#include "samson/stream/BlockManager.h"
#include "samson/module/ModulesManager.h"

/* ****************************************************************************
*
* Option variables
*/
SAMSON_ARG_VARS;

bool     fg;
bool     noLog;
int      valgrind;
int      port;
int      web_port;

/* ****************************************************************************
*
* parse arguments
*/
PaArgument paArgs[] =
{
    SAMSON_ARGS,
    { "-fg",        &fg,        "SAMSON_WORKER_FOREGROUND", PaBool, PaOpt, false,                  false,  true,  "don't start as daemon"             },
    { "-port",      &port,      "",                         PaInt,  PaOpt, SAMSON_WORKER_PORT,     1,      9999,  "Port to receive new connections"   },
    { "-web_port",  &web_port,  "",                         PaInt,  PaOpt, SAMSON_WORKER_WEB_PORT, 1,      9999,  "Port to receive new connections"   },
    { "-nolog",     &noLog,     "SAMSON_WORKER_NO_LOG",     PaBool, PaOpt, false,                  false,  true,  "no logging"                        },
    { "-valgrind",  &valgrind,  "SAMSON_WORKER_VALGRIND",   PaInt,  PaOpt, 0,                      0,        20,  "help valgrind debug process"       },

    PA_END_OF_ARGS
};

/* ****************************************************************************
*
* global variables
*/
int                           logFd             = -1;
samson::SamsonWorker*         worker            = NULL;
au::LockDebugger*             lockDebugger      = NULL;
engine::SharedMemoryManager*  smManager         = NULL;

/* ****************************************************************************
*
* man texts -
*/
static const char* manSynopsis         = " [OPTION]";
static const char* manShortDescription = "samsond is the main process in a SAMSON system.\n\n";
static const char* manDescription      =
    "\n"
    "samsond is the main process in a SAMSON system. All the nodes in the cluster has its own samsonWorker process\n"
    "All samsond processes are responsible for processing a segment of available data"
    "All clients of the platform ( delila's ) are connected to all samsonWorkers in the system"
    "See samson documentation to get more information about how to get a SAMSON system up and running"
    "\n";

static const char* manExitStatus    = "0      if OK\n 1-255  error\n";
static const char* manAuthor        = "Written by Andreu Urruela, Ken Zangelin and J.Gregorio Escalada.";
static const char* manReportingBugs = "bugs to samson-dev@tid.es\n";
static const char* manCopyright     = "Copyright (C) 2011 Telefonica Investigacion y Desarrollo";
static const char* manVersion       = SAMSON_VERSION;

void captureSIGINT( int s )
{
    s = 3;
    LM_X(1, ("Signal SIGINT"));
}

void captureSIGPIPE( int s )
{
    s = 3;
    LM_M(("Captured SIGPIPE"));
}

void captureSIGTERM( int s )
{
    s = 3;
    LM_M(("Captured SIGTERM"));

    LM_M(("Cleaning up"));
    std::string pid_file_name = au::str("%s/samsond.pid" , paLogDir );
    if ( remove (pid_file_name.c_str()) != 0)
    {
        LM_W(("Error deleting the pid file %s", pid_file_name.c_str() ));
    }
    exit(1);
}

void cleanup(void)
{
    google::protobuf::ShutdownProtobufLibrary();

    printf("Shutting down worker components (worker at %p)\n", worker);
    if (worker)
    {
        printf("deleting worker\n");
        delete worker;
    }

    printf("Shutting down LockDebugger\n");
    au::LockDebugger::destroy();

    if (smManager != NULL)
    {
        printf("Shutting down Shared Memory Manager\n");
        delete smManager;
        smManager = NULL;
    }

    printf("Shutting down SamsonSetup\n");
    samson::SamsonSetup::destroy();

    printf("destroying ProcessManager\n");
    engine::ProcessManager::destroy();

    printf("destroying DiskManager\n");
    engine::DiskManager::destroy();

    printf("destroying MemoryManager\n");
    engine::MemoryManager::destroy();

    printf("destroying Engine\n");
    engine::Engine::destroy();

    printf("destroying ModulesManager\n");
    samson::ModulesManager::destroy();

    paConfigCleanup();
    lmCleanProgName();
}

static void valgrindExit(int v)
{
    if (v == valgrind)
    {
        LM_M(("Valgrind option is %d - I exit", v));
        exit(0);
    }
}

/* ****************************************************************************
*
* main -
*/
int main(int argC, const char *argV[])
{
    atexit(cleanup);

    paConfig("builtin prefix",                (void*) "SS_WORKER_");
    paConfig("usage and exit on any warning", (void*) true);

    // Andreu: samsonWorker is not a console in foreground (debug) mode ( to ask to status with commands )
    paConfig("log to screen",                 (void*) "only errors");
    //paConfig("log to screen",                 (void*) (void*) false);

    paConfig("log file line format",          (void*) "TYPE:DATE:EXEC-AUX/FILE[LINE](p.PID)(t.TID) FUNC: TEXT");
    paConfig("screen line format",            (void*) "TYPE@TIME  EXEC: TEXT");
    paConfig("log to file",                   (void*) true);

    paConfig("man synopsis",                  (void*) manSynopsis);
    paConfig("man shortdescription",          (void*) manShortDescription);
    paConfig("man description",               (void*) manDescription);
    paConfig("man exitstatus",                (void*) manExitStatus);
    paConfig("man author",                    (void*) manAuthor);
    paConfig("man reportingbugs",             (void*) manReportingBugs);
    paConfig("man copyright",                 (void*) manCopyright);
    paConfig("man version",                   (void*) manVersion);

    const char* extra = paIsSetSoGet(argC, (char**) argV, "-port");
    paParse(paArgs, argC, (char**) argV, 1, false, extra);

    valgrindExit(1);

    lmAux((char*) "father");

    LM_V(("Started with arguments:"));
    for (int ix = 0; ix < argC; ix++)
        LM_V(("  %02d: '%s'", ix, argV[ix]));

    logFd = lmFirstDiskFileDescriptor();

    // Capturing SIGPIPE
    if (signal(SIGPIPE, captureSIGPIPE) == SIG_ERR)
        LM_W(("SIGPIPE cannot be handled"));

    if (signal(SIGINT, captureSIGINT) == SIG_ERR)
        LM_W(("SIGINT cannot be handled"));

    if (signal(SIGTERM, captureSIGTERM) == SIG_ERR)
        LM_W(("SIGTERM cannot be handled"));

    // Init basic setup stuff (necessary for memory check)
    lockDebugger = au::LockDebugger::shared();  // VALGRIND complains ...
    samson::SamsonSetup::init(samsonHome, samsonWorking);          // Load setup and create default directories

    valgrindExit(2);

    // Check to see if the current memory configuration is ok or not
    if (samson::MemoryCheck() == false)
        LM_X(1,("Insufficient memory configured. Check %ssamsonWorkerLog for more information.", paLogDir));

    if (fg == false)
    {
        std::cout << "OK. samsonWorker is now working in background.\n";
        daemonize();
    }

    valgrindExit(3);
    // ------------------------------------------------------
    // Write pid in /var/log/samson/samsond.pid
    // ------------------------------------------------------

    char pid_file_name[256];
    snprintf(pid_file_name, sizeof(pid_file_name), "%s/samsond.pid", paLogDir);
    FILE *file = fopen(pid_file_name, "w");
    if (!file)
        LM_X(1, ("Error opening file '%s' to store pid", pid_file_name));
    int pid = (int) getpid();
    if (fprintf(file, "%d" , pid) == 0)
       LM_X(1,("Error writing pid %d to file %s", pid, pid_file_name));
    fclose(file);
    // ------------------------------------------------------

    // Make sure this singleton is created just once
    LM_D(("createWorkingDirectories"));
    samson::SamsonSetup::shared()->createWorkingDirectories();      // Create working directories

    valgrindExit(4);
    LM_D(("engine::Engine::init"));
    engine::Engine::init();

    valgrindExit(5);
    LM_D(("engine::SharedMemoryManager::init"));
    engine::SharedMemoryManager::init(samson::SamsonSetup::shared()->getInt("general.num_processess") , samson::SamsonSetup::shared()->getUInt64("general.shared_memory_size_per_buffer")); // VALGRIND complains ...
    smManager = engine::SharedMemoryManager::shared();

    valgrindExit(6);
    LM_D(("engine::DiskManager::init"));
    engine::DiskManager::init(1);

    valgrindExit(7);
    LM_D(("engine::ProcessManager::init"));
    engine::ProcessManager::init(samson::SamsonSetup::shared()->getInt("general.num_processess"));

    valgrindExit(8);
    LM_D(("engine::MemoryManager::init"));
    engine::MemoryManager::init(samson::SamsonSetup::shared()->getUInt64("general.memory"));

    valgrindExit(9);
    LM_D(("samson::ModulesManager::init"));
    samson::ModulesManager::init();

    valgrindExit(10);
    LM_D(("samson::stream::BlockManager::init"));
    samson::stream::BlockManager::init();

    valgrindExit(11);

    // Instance of network object and initialization
    // --------------------------------------------------------------------
    samson::WorkerNetwork*  networkP  = new samson::WorkerNetwork(port, web_port);

    valgrindExit(12);

    // Instance of SamsonWorker object (network contains at least the number of workers)
    // -----------------------------------------------------------------------------------
    worker = new samson::SamsonWorker(networkP);

    LM_M(("Worker Running"));
    LM_D(("worker at %p", worker));
    valgrindExit(13);

    if (fg == false)
    {
        while (true)
            sleep(10);
    }

    worker->runConsole();

    LM_D(("Worker Cleanup"));

    if (worker)
        delete worker;

    google::protobuf::ShutdownProtobufLibrary();

    // ------------------------------------------------------------------------
    // Close everything
    // ------------------------------------------------------------------------

    samson::ModulesManager::destroy();

    engine::ProcessManager::destroy();
    engine::DiskManager::destroy();
    engine::MemoryManager::destroy();
    engine::Engine::destroy();

    samson::SamsonSetup::destroy();

    // Check background threads
    au::StringVector background_threads = au::ThreadManager::shared()->getThreadNames();
    if( background_threads.size() > 0 )
    {
        LM_W(("Still %lu background threads running (%s)" , background_threads.size() , background_threads.str().c_str() ));
        std::cerr << au::ThreadManager::shared()->str();
    }
    else
        LM_M(("Finished correctly with 0 background processes"));

    return 0;
}
<|endoftext|>


<commit_before>///
/// @file  PrimeSieve-lock.hpp
///
/// Copyright (C) 2013 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef PRIMESIEVE_LOCK_HPP
#define PRIMESIEVE_LOCK_HPP

#include "config.hpp"
#include "PrimeSieve.hpp"

namespace primesieve {

/// Block the current PrimeSieve (or ParallelPrimeSieve) thread
/// until it can set a lock, then continue execution.
///
class LockGuard {
public:
  LockGuard(PrimeSieve& ps) : ps_(ps) { ps_.setLock(); }
  ~LockGuard() { ps_.unsetLock(); }
private:
  PrimeSieve& ps_;
  DISALLOW_COPY_AND_ASSIGN(LockGuard);
};

} // namespace primesieve

#endif
<commit_msg>Update comment<commit_after>///
/// @file  PrimeSieve-lock.hpp
///
/// Copyright (C) 2017 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef PRIMESIEVE_LOCK_HPP
#define PRIMESIEVE_LOCK_HPP

#include "config.hpp"
#include "PrimeSieve.hpp"

namespace primesieve {

/// Block the current PrimeSieve (or ParallelPrimeSieve) thread
/// until it can set a lock, then continue execution.
///
class LockGuard {
public:
  LockGuard(PrimeSieve& ps) : ps_(ps) { ps_.setLock(); }
  ~LockGuard() { ps_.unsetLock(); }
private:
  PrimeSieve& ps_;
  DISALLOW_COPY_AND_ASSIGN(LockGuard);
};

} // namespace

#endif
<|endoftext|>


<commit_before>#ifndef __PLUGINSETTINGS_HPP__
#define __PLUGINSETTINGS_HPP__

#include "plugin.hpp"

class PluginSettings
{
	HANDLE handle;
	FARAPISETTINGSCONTROL SettingsControl;

public:

	PluginSettings(const GUID &guid, FARAPISETTINGSCONTROL SettingsControl)
	{
		this->SettingsControl = SettingsControl;
		handle = INVALID_HANDLE_VALUE;

		FarSettingsCreate settings={sizeof(FarSettingsCreate),guid,handle};
		if (SettingsControl(INVALID_HANDLE_VALUE,SCTL_CREATE,0,&settings))
			handle = settings.Handle;
	}

	~PluginSettings()
	{
		SettingsControl(handle,SCTL_FREE,0,{});
	}

	int CreateSubKey(size_t Root, const wchar_t *Name)
	{
		FarSettingsValue value={sizeof(FarSettingsValue),Root,Name};
		return (int)SettingsControl(handle,SCTL_CREATESUBKEY,0,&value);
	}

	int OpenSubKey(size_t Root, const wchar_t *Name)
	{
		FarSettingsValue value={sizeof(FarSettingsValue),Root,Name};
		return (int)SettingsControl(handle,SCTL_OPENSUBKEY,0,&value);
	}

	bool DeleteSubKey(size_t Root)
	{
		FarSettingsValue value={sizeof(FarSettingsValue),Root,nullptr};
		return (int)SettingsControl(handle,SCTL_DELETE,0,&value) ? true : false;
	}

	bool DeleteValue(size_t Root, const wchar_t *Name)
	{
		FarSettingsValue value={sizeof(FarSettingsValue),Root,Name};
		return (int)SettingsControl(handle,SCTL_DELETE,0,&value) ? true : false;
	}

	const wchar_t *Get(size_t Root, const wchar_t *Name, const wchar_t *Default)
	{
		FarSettingsItem item={sizeof(FarSettingsItem),Root,Name,FST_STRING};
		if (SettingsControl(handle,SCTL_GET,0,&item))
		{
			return item.String;
		}
		return Default;
	}

	void Get(size_t Root, const wchar_t *Name, wchar_t *Value, size_t Size, const wchar_t *Default)
	{
		lstrcpyn(Value, Get(Root,Name,Default), (int)Size);
	}

	unsigned __int64 Get(size_t Root, const wchar_t *Name, unsigned __int64 Default)
	{
		FarSettingsItem item={sizeof(FarSettingsItem),Root,Name,FST_QWORD};
		if (SettingsControl(handle,SCTL_GET,0,&item))
		{
			return item.Number;
		}
		return Default;
	}

	__int64      Get(size_t Root, const wchar_t *Name, __int64 Default) { return (__int64)Get(Root,Name,(unsigned __int64)Default); }
	int          Get(size_t Root, const wchar_t *Name, int Default)  { return (int)Get(Root,Name,(unsigned __int64)Default); }
	unsigned int Get(size_t Root, const wchar_t *Name, unsigned int Default) { return (unsigned int)Get(Root,Name,(unsigned __int64)Default); }
	DWORD        Get(size_t Root, const wchar_t *Name, DWORD Default) { return (DWORD)Get(Root,Name,(unsigned __int64)Default); }
	bool         Get(size_t Root, const wchar_t *Name, bool Default) { return Get(Root,Name,Default?1ull:0ull)?true:false; }

	size_t Get(size_t Root, const wchar_t *Name, void *Value, size_t Size)
	{
		FarSettingsItem item={sizeof(FarSettingsItem),Root,Name,FST_DATA};
		if (SettingsControl(handle,SCTL_GET,0,&item))
		{
			Size = (item.Data.Size>Size)?Size:item.Data.Size;
			memcpy(Value,item.Data.Data,Size);
			return Size;
		}
		return 0;
	}

	bool Set(size_t Root, const wchar_t *Name, const wchar_t *Value)
	{
		FarSettingsItem item={sizeof(FarSettingsItem),Root,Name,FST_STRING};
		item.String=Value;
		return SettingsControl(handle,SCTL_SET,0,&item)!=FALSE;
	}

	bool Set(size_t Root, const wchar_t *Name, unsigned __int64 Value)
	{
		FarSettingsItem item={sizeof(FarSettingsItem),Root,Name,FST_QWORD};
		item.Number=Value;
		return SettingsControl(handle,SCTL_SET,0,&item)!=FALSE;
	}

	bool Set(size_t Root, const wchar_t *Name, __int64 Value) { return Set(Root,Name,(unsigned __int64)Value); }
	bool Set(size_t Root, const wchar_t *Name, int Value) { return Set(Root,Name,(unsigned __int64)Value); }
	bool Set(size_t Root, const wchar_t *Name, unsigned int Value) { return Set(Root,Name,(unsigned __int64)Value); }
	bool Set(size_t Root, const wchar_t *Name, DWORD Value) { return Set(Root,Name,(unsigned __int64)Value); }
	bool Set(size_t Root, const wchar_t *Name, bool Value) { return Set(Root,Name,Value?1ull:0ull); }

	bool Set(size_t Root, const wchar_t *Name, const void *Value, size_t Size)
	{
		FarSettingsItem item={sizeof(FarSettingsItem),Root,Name,FST_DATA};
		item.Data.Size=Size;
		item.Data.Data=Value;
		return SettingsControl(handle,SCTL_SET,0,&item)!=FALSE;
	}
};

#endif
<commit_msg>plugins: can build some plugins with 'old' compilers (supported c++11, but not supported c++17)<commit_after>#ifndef __PLUGINSETTINGS_HPP__
#define __PLUGINSETTINGS_HPP__

#include "plugin.hpp"

class PluginSettings
{
	HANDLE handle;
	FARAPISETTINGSCONTROL SettingsControl;

public:

	PluginSettings(const GUID &guid, FARAPISETTINGSCONTROL SettingsControl)
	{
		this->SettingsControl = SettingsControl;
		handle = INVALID_HANDLE_VALUE;

		FarSettingsCreate settings={sizeof(FarSettingsCreate),guid,handle};
		if (SettingsControl(INVALID_HANDLE_VALUE,SCTL_CREATE,0,&settings))
			handle = settings.Handle;
	}

	~PluginSettings()
	{
		SettingsControl(handle,SCTL_FREE,0,nullptr);
	}

	int CreateSubKey(size_t Root, const wchar_t *Name)
	{
		FarSettingsValue value={sizeof(FarSettingsValue),Root,Name};
		return (int)SettingsControl(handle,SCTL_CREATESUBKEY,0,&value);
	}

	int OpenSubKey(size_t Root, const wchar_t *Name)
	{
		FarSettingsValue value={sizeof(FarSettingsValue),Root,Name};
		return (int)SettingsControl(handle,SCTL_OPENSUBKEY,0,&value);
	}

	bool DeleteSubKey(size_t Root)
	{
		FarSettingsValue value={sizeof(FarSettingsValue),Root,nullptr};
		return (int)SettingsControl(handle,SCTL_DELETE,0,&value) ? true : false;
	}

	bool DeleteValue(size_t Root, const wchar_t *Name)
	{
		FarSettingsValue value={sizeof(FarSettingsValue),Root,Name};
		return (int)SettingsControl(handle,SCTL_DELETE,0,&value) ? true : false;
	}

	const wchar_t *Get(size_t Root, const wchar_t *Name, const wchar_t *Default)
	{
		FarSettingsItem item={sizeof(FarSettingsItem),Root,Name,FST_STRING};
		if (SettingsControl(handle,SCTL_GET,0,&item))
		{
			return item.String;
		}
		return Default;
	}

	void Get(size_t Root, const wchar_t *Name, wchar_t *Value, size_t Size, const wchar_t *Default)
	{
		lstrcpyn(Value, Get(Root,Name,Default), (int)Size);
	}

	unsigned __int64 Get(size_t Root, const wchar_t *Name, unsigned __int64 Default)
	{
		FarSettingsItem item={sizeof(FarSettingsItem),Root,Name,FST_QWORD};
		if (SettingsControl(handle,SCTL_GET,0,&item))
		{
			return item.Number;
		}
		return Default;
	}

	__int64      Get(size_t Root, const wchar_t *Name, __int64 Default) { return (__int64)Get(Root,Name,(unsigned __int64)Default); }
	int          Get(size_t Root, const wchar_t *Name, int Default)  { return (int)Get(Root,Name,(unsigned __int64)Default); }
	unsigned int Get(size_t Root, const wchar_t *Name, unsigned int Default) { return (unsigned int)Get(Root,Name,(unsigned __int64)Default); }
	DWORD        Get(size_t Root, const wchar_t *Name, DWORD Default) { return (DWORD)Get(Root,Name,(unsigned __int64)Default); }
	bool         Get(size_t Root, const wchar_t *Name, bool Default) { return Get(Root,Name,Default?1ull:0ull)?true:false; }

	size_t Get(size_t Root, const wchar_t *Name, void *Value, size_t Size)
	{
		FarSettingsItem item={sizeof(FarSettingsItem),Root,Name,FST_DATA};
		if (SettingsControl(handle,SCTL_GET,0,&item))
		{
			Size = (item.Data.Size>Size)?Size:item.Data.Size;
			memcpy(Value,item.Data.Data,Size);
			return Size;
		}
		return 0;
	}

	bool Set(size_t Root, const wchar_t *Name, const wchar_t *Value)
	{
		FarSettingsItem item={sizeof(FarSettingsItem),Root,Name,FST_STRING};
		item.String=Value;
		return SettingsControl(handle,SCTL_SET,0,&item)!=FALSE;
	}

	bool Set(size_t Root, const wchar_t *Name, unsigned __int64 Value)
	{
		FarSettingsItem item={sizeof(FarSettingsItem),Root,Name,FST_QWORD};
		item.Number=Value;
		return SettingsControl(handle,SCTL_SET,0,&item)!=FALSE;
	}

	bool Set(size_t Root, const wchar_t *Name, __int64 Value) { return Set(Root,Name,(unsigned __int64)Value); }
	bool Set(size_t Root, const wchar_t *Name, int Value) { return Set(Root,Name,(unsigned __int64)Value); }
	bool Set(size_t Root, const wchar_t *Name, unsigned int Value) { return Set(Root,Name,(unsigned __int64)Value); }
	bool Set(size_t Root, const wchar_t *Name, DWORD Value) { return Set(Root,Name,(unsigned __int64)Value); }
	bool Set(size_t Root, const wchar_t *Name, bool Value) { return Set(Root,Name,Value?1ull:0ull); }

	bool Set(size_t Root, const wchar_t *Name, const void *Value, size_t Size)
	{
		FarSettingsItem item={sizeof(FarSettingsItem),Root,Name,FST_DATA};
		item.Data.Size=Size;
		item.Data.Data=Value;
		return SettingsControl(handle,SCTL_SET,0,&item)!=FALSE;
	}
};

#endif
<|endoftext|>


<commit_before>#include <netdb.h>
#include <unistd.h>
#include <sys/fcntl.h>

#include "client.h"
#include "duckchat.h"
#include "raw.h"

// Variables
struct sockaddr_in client_addr;
struct sockaddr_in server_addr;
int client_socket;
struct addrinfo *server_info;
char *channel;

// Prints an error message and exits the program.
void Error(const char *msg) {
  std::cerr << msg << std::endl;
  exit(1);
}

// Connects to the server at a the given port.
void Connect(char *domain, const char *port) {
  std::cout << "Connecting to " << domain << std::endl;

  struct addrinfo hints;
  struct addrinfo *server_info_tmp;
  int status;

  memset(&hints, 0, sizeof(hints));
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_DGRAM;
  hints.ai_protocol = 0;

  if ((status = getaddrinfo(domain, port, &hints, &server_info_tmp)) != 0) {
    std::cerr << "client: unable to resolve address: " << gai_strerror(status) << std::endl;
    exit(1);
  }

  // getaddrinfo() returns a list of address structures into server_info_tmp.
  // Try each address until we successfully connect().
  // If socket() (or connect()) fails, close the socket and try the next address.

  for (server_info = server_info_tmp; server_info != NULL; server_info = server_info->ai_next) {
    if ((client_socket = socket(server_info->ai_family, server_info->ai_socktype, server_info->ai_protocol)) < 0) {
      continue;
    }
    if (connect(client_socket, server_info->ai_addr, server_info->ai_addrlen) != -1) {
      fcntl(client_socket, F_SETFL, O_NONBLOCK);
      break; // Success
    }
    close(client_socket);
  }

  if (server_info == NULL) {
    Error("client: all sockets failed to connect");
  }
}

// Sends a message to all users in on the active channel.
int RequestSay(const char *message) {
  struct request_say say;
  memset(&say, 0, sizeof(say));
  say.req_type = REQ_SAY;
  strncpy(say.req_text, message, SAY_MAX);
  strncpy(say.req_channel, channel, CHANNEL_MAX);

  if (sendto(client_socket, &say, sizeof(say), 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to send message\n");
  }

  return 0;
}

// Sends login requests to the server.
int RequestLogin(char *username) {
  struct request_login login;
  memset(&login, 0, sizeof(login));
  login.req_type = REQ_LOGIN;
  strncpy(login.req_username, username, USERNAME_MAX);

  size_t message_size = sizeof(struct request_login);

  if (sendto(client_socket, &login, message_size, 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to request login\n");
  }

  return 0;
}

// Sends logout requests to the server.
int RequestLogout() {
  struct request_logout logout;
  memset((char *) &logout, 0, sizeof(logout));
  logout.req_type = REQ_LOGOUT;

  size_t message_size = sizeof(struct request_logout);

  if (sendto(client_socket, &logout, message_size, 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to request logout\n");
  }

  return 0;
}

// Sends join requests to the server.
int RequestJoin(char *channel) {
  struct request_join join;
  memset((char *) &join, 0, sizeof(join));
  join.req_type = REQ_JOIN;
  strncpy(join.req_channel, channel, CHANNEL_MAX);

  size_t message_size = sizeof(struct request_join);

  if (sendto(client_socket, &join, message_size, 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to request join\n");
  }

  return 0;
}

// Splits strings around spaces.
std::vector<std::string> StringSplit(std::string input) {
  std::istringstream iss(input);
  std::vector<std::string> result{std::istream_iterator<std::string>{iss}, std::istream_iterator<std::string>{}};

  return result;
}

// Splits strings around spaces.
std::vector<std::string> SplitString(char *input, char delimiter) {
  std::vector<std::string> result;
  std::string word = "";

  size_t input_size = strlen(input);
  for (size_t i = 0; i < input_size; i++) {
    if (input[i] != delimiter) {
      word += input[i];
    } else {
      result.push_back(word);
      word = "";
    }
  }
  result.push_back(word);

  return result;
}

void StripChar(char *input, char c) {
  size_t size = strlen(input);
  for (size_t i = 0; i < size; i++) {
    if (input[i] == c) {
      input[i] = '\0';
    }
  }
}

// Processes the input string to decide what type of command it is.
bool ProcessInput(std::string input) {
  std::vector<std::string> inputs = StringSplit(input);
  bool result = true;

  if (inputs[0] == "/exit") {
    RequestLogout();
//    cooked_mode();
    result = false;
  } else if (inputs[0] == "/list") {

  } else if (inputs[0] == "/join") {

  } else if (inputs[0] == "/leave") {

  } else if (inputs[0] == "/who") {

  } else if (inputs[0] == "/switch") {

  } else {
    std::cout << "\n*Unknown command" << std::endl;
  }

  return result;
}

int main(int argc, char *argv[]) {
  char *domain;
  char *port_str;
  int port_num;
  char *username;
  char *input;
  char tmp_buffer[SAY_MAX];
  memset(&tmp_buffer, 0, SAY_MAX);

  char stdin_buffer[SAY_MAX + 1];
  char *stdin_buffer_position = stdin_buffer;

//  struct timeval timeout;
  fd_set read_set;
//  int file_desc = 0;
  int result;
  char receive_buffer[kBufferSize];
  memset(&receive_buffer, 0, kBufferSize);

//  char stdin_buffer[kBufferSize];
//  memset(&stdin_buffer, 0, kBufferSize);

  if (argc < 4) {
    Error("usage: client [server name] [port] [username]");
  }

  domain = argv[1];
  port_str = argv[2];
  port_num = atoi(argv[2]);
  username = argv[3];

  if (strlen(domain) > UNIX_PATH_MAX) {
    Error("client: server name must be less than 108 characters");
  }

  if (port_num < 0 || port_num > 65535) {
    Error("client: port number must be between 0 and 65535");
  }

  if (strlen(username) > USERNAME_MAX) {
    Error("client: username must be less than 32 characters");
  }

  Connect(domain, port_str);

  RequestLogin(username);

  channel = (char *) "Common";
  RequestJoin(channel);

  // TODO handle response from send

  if (raw_mode() != 0){
    Error("client: error using raw mode");
  }

  std::cout << ">" << std::flush;

  while (1) {
    FD_ZERO(&read_set);
    FD_SET(client_socket, &read_set);
    FD_SET(STDIN_FILENO, &read_set);

    if ((result = select(client_socket + 1, &read_set, NULL, NULL, NULL)) < 0) {
      Error("client: problem using select");
    }

    if (result > 0) {
      if (FD_ISSET(STDIN_FILENO, &read_set)) {
//        char c = (char) getchar();
//        *bufPosition++ = c;
//        std::cout << c << std::endl;
//        fflush(stdout);

//        int read_stdin_size = read(STDIN_FILENO, stdin_buffer, kBufferSize);

//        input = NewInputString();

        char c = (char) getchar();
        if (c == '\n') {
          *stdin_buffer_position++ = '\0';
          stdin_buffer_position = stdin_buffer;
          printf("\n");
          fflush(stdout);
          input = stdin_buffer;
          if (input[0] == '/') {
            std::cout << "input[0] == '/'" << std::endl;
            ProcessInput(input);
          } else {
            // Send chat messages
//            StripChar(stdin_buffer, '\n');
            RequestSay(input);
          }

        } else if (stdin_buffer_position != stdin_buffer + SAY_MAX) {
          *stdin_buffer_position++ = c;
          printf("%c", c);
          fflush(stdout);
        }
//
//        const char *DELIM = " \n";
//        char *tok = (char*) malloc(sizeof(char) * (strlen(input) + 1));
//        strcpy(tok, input);
//        char *command = strtok(tok, DELIM);
//        free(tok);
//
//        if (command != NULL) {
//          if (input[0] == '/') {
//            ProcessInput(input);
//          } else {
//            // Send chat messages
////            StripChar(stdin_buffer, '\n');
//            RequestSay(input);
//          }
//        }
//
//        memset(&stdin_buffer, 0, kBufferSize);
      } // end of if STDIN_FILENO

      if (FD_ISSET(client_socket, &read_set)) {
        // Socket has data
        int read_size = read(client_socket, receive_buffer, kBufferSize);

        if (read_size != 0) {
          // TODO capture user input, store, clean input, then print buffer, afterward replace input
          struct text message;
          memcpy(&message, receive_buffer, sizeof(struct text));
          text_t text_type = message.txt_type;

          switch (text_type) {
            case TXT_SAY:
              struct text_say say;
              memcpy(&say, receive_buffer, sizeof(struct text_say));
//              std::cin.readsome(tmp_buffer, sizeof(tmp_buffer));
              std::cout << "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b";
              std::cout << "[" << say.txt_channel << "]" << "[" << say.txt_username << "]: " << say.txt_text << std::endl;
              std::cout << ">" << tmp_buffer << std::flush;
              memset(&tmp_buffer, 0, SAY_MAX);
              break;
            default:
              break;
          }
        }

        memset(&receive_buffer, 0, SAY_MAX);
      } // end of if client_socket

    } // end of if result

  } // end of while

  return 0;
}<commit_msg>fix /exit<commit_after>#include <netdb.h>
#include <unistd.h>
#include <sys/fcntl.h>

#include "client.h"
#include "duckchat.h"
#include "raw.h"

// Variables
struct sockaddr_in client_addr;
struct sockaddr_in server_addr;
int client_socket;
struct addrinfo *server_info;
char *channel;

// Prints an error message and exits the program.
void Error(const char *msg) {
  std::cerr << msg << std::endl;
  exit(1);
}

// Connects to the server at a the given port.
void Connect(char *domain, const char *port) {
  std::cout << "Connecting to " << domain << std::endl;

  struct addrinfo hints;
  struct addrinfo *server_info_tmp;
  int status;

  memset(&hints, 0, sizeof(hints));
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_DGRAM;
  hints.ai_protocol = 0;

  if ((status = getaddrinfo(domain, port, &hints, &server_info_tmp)) != 0) {
    std::cerr << "client: unable to resolve address: " << gai_strerror(status) << std::endl;
    exit(1);
  }

  // getaddrinfo() returns a list of address structures into server_info_tmp.
  // Try each address until we successfully connect().
  // If socket() (or connect()) fails, close the socket and try the next address.

  for (server_info = server_info_tmp; server_info != NULL; server_info = server_info->ai_next) {
    if ((client_socket = socket(server_info->ai_family, server_info->ai_socktype, server_info->ai_protocol)) < 0) {
      continue;
    }
    if (connect(client_socket, server_info->ai_addr, server_info->ai_addrlen) != -1) {
      fcntl(client_socket, F_SETFL, O_NONBLOCK);
      break; // Success
    }
    close(client_socket);
  }

  if (server_info == NULL) {
    Error("client: all sockets failed to connect");
  }
}

// Sends a message to all users in on the active channel.
int RequestSay(const char *message) {
  struct request_say say;
  memset(&say, 0, sizeof(say));
  say.req_type = REQ_SAY;
  strncpy(say.req_text, message, SAY_MAX);
  strncpy(say.req_channel, channel, CHANNEL_MAX);

  if (sendto(client_socket, &say, sizeof(say), 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to send message\n");
  }

  return 0;
}

// Sends login requests to the server.
int RequestLogin(char *username) {
  struct request_login login;
  memset(&login, 0, sizeof(login));
  login.req_type = REQ_LOGIN;
  strncpy(login.req_username, username, USERNAME_MAX);

  size_t message_size = sizeof(struct request_login);

  if (sendto(client_socket, &login, message_size, 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to request login\n");
  }

  return 0;
}

// Sends logout requests to the server.
int RequestLogout() {
  struct request_logout logout;
  memset((char *) &logout, 0, sizeof(logout));
  logout.req_type = REQ_LOGOUT;

  size_t message_size = sizeof(struct request_logout);

  if (sendto(client_socket, &logout, message_size, 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to request logout\n");
  }

  return 0;
}

// Sends join requests to the server.
int RequestJoin(char *channel) {
  struct request_join join;
  memset((char *) &join, 0, sizeof(join));
  join.req_type = REQ_JOIN;
  strncpy(join.req_channel, channel, CHANNEL_MAX);

  size_t message_size = sizeof(struct request_join);

  if (sendto(client_socket, &join, message_size, 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to request join\n");
  }

  return 0;
}

// Splits strings around spaces.
std::vector<std::string> StringSplit(std::string input) {
  std::istringstream iss(input);
  std::vector<std::string> result{std::istream_iterator<std::string>{iss}, std::istream_iterator<std::string>{}};

  return result;
}

// Splits strings around spaces.
std::vector<std::string> SplitString(char *input, char delimiter) {
  std::vector<std::string> result;
  std::string word = "";

  size_t input_size = strlen(input);
  for (size_t i = 0; i < input_size; i++) {
    if (input[i] != delimiter) {
      word += input[i];
    } else {
      result.push_back(word);
      word = "";
    }
  }
  result.push_back(word);

  return result;
}

void StripChar(char *input, char c) {
  size_t size = strlen(input);
  for (size_t i = 0; i < size; i++) {
    if (input[i] == c) {
      input[i] = '\0';
    }
  }
}

// Processes the input string to decide what type of command it is.
bool ProcessInput(std::string input) {
  std::vector<std::string> inputs = StringSplit(input);
  bool result = true;

  if (inputs[0] == "/exit") {
    RequestLogout();
    cooked_mode();
    result = false;
  } else if (inputs[0] == "/list") {

  } else if (inputs[0] == "/join") {

  } else if (inputs[0] == "/leave") {

  } else if (inputs[0] == "/who") {

  } else if (inputs[0] == "/switch") {

  } else {
    std::cout << "\n*Unknown command" << std::endl;
  }

  return result;
}

int main(int argc, char *argv[]) {
  char *domain;
  char *port_str;
  int port_num;
  char *username;
  char *input;
  char tmp_buffer[SAY_MAX];
  memset(&tmp_buffer, 0, SAY_MAX);

  char stdin_buffer[SAY_MAX + 1];
  char *stdin_buffer_position = stdin_buffer;

//  struct timeval timeout;
  fd_set read_set;
//  int file_desc = 0;
  int result;
  char receive_buffer[kBufferSize];
  memset(&receive_buffer, 0, kBufferSize);

//  char stdin_buffer[kBufferSize];
//  memset(&stdin_buffer, 0, kBufferSize);

  if (argc < 4) {
    Error("usage: client [server name] [port] [username]");
  }

  domain = argv[1];
  port_str = argv[2];
  port_num = atoi(argv[2]);
  username = argv[3];

  if (strlen(domain) > UNIX_PATH_MAX) {
    Error("client: server name must be less than 108 characters");
  }

  if (port_num < 0 || port_num > 65535) {
    Error("client: port number must be between 0 and 65535");
  }

  if (strlen(username) > USERNAME_MAX) {
    Error("client: username must be less than 32 characters");
  }

  Connect(domain, port_str);

  RequestLogin(username);

  channel = (char *) "Common";
  RequestJoin(channel);

  // TODO handle response from send

  if (raw_mode() != 0){
    Error("client: error using raw mode");
  }

  std::cout << ">" << std::flush;

  while (1) {
    FD_ZERO(&read_set);
    FD_SET(client_socket, &read_set);
    FD_SET(STDIN_FILENO, &read_set);

    if ((result = select(client_socket + 1, &read_set, NULL, NULL, NULL)) < 0) {
      Error("client: problem using select");
    }

    if (result > 0) {
      if (FD_ISSET(STDIN_FILENO, &read_set)) {
        char c = (char) getchar();
        if (c == '\n') {
//          *stdin_buffer_position++ = '\0';
          stdin_buffer_position = stdin_buffer;
          printf("\n");
          fflush(stdout);
          input = stdin_buffer;
          if (input[0] == '/') {
            if (!ProcessInput(input)) {
              break;
            }
          } else {
            // Send chat messages
//            StripChar(stdin_buffer, '\n');
            RequestSay(input);
          }

        } else if (stdin_buffer_position != stdin_buffer + SAY_MAX) {
          *stdin_buffer_position++ = c;
          std::cout << c << std::endl;
          fflush(stdout);
        }

//        if (input != NULL) {
//          if (input[0] == '/') {
//            ProcessInput(input);
//          } else {
//            // Send chat messages
////            StripChar(stdin_buffer, '\n');
//            RequestSay(input);
//          }
//        }
//
//        memset(&stdin_buffer, 0, kBufferSize);
      } // end of if STDIN_FILENO

      if (FD_ISSET(client_socket, &read_set)) {
        // Socket has data
        int read_size = read(client_socket, receive_buffer, kBufferSize);

        if (read_size != 0) {
          // TODO capture user input, store, clean input, then print buffer, afterward replace input
          struct text message;
          memcpy(&message, receive_buffer, sizeof(struct text));
          text_t text_type = message.txt_type;

          switch (text_type) {
            case TXT_SAY:
              struct text_say say;
              memcpy(&say, receive_buffer, sizeof(struct text_say));
//              std::cin.readsome(tmp_buffer, sizeof(tmp_buffer));
              std::cout << "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b";
              std::cout << "[" << say.txt_channel << "]" << "[" << say.txt_username << "]: " << say.txt_text << std::endl;
              std::cout << ">" << tmp_buffer << std::flush;
              memset(&tmp_buffer, 0, SAY_MAX);
              break;
            default:
              break;
          }
        }

        memset(&receive_buffer, 0, SAY_MAX);
      } // end of if client_socket

    } // end of if result

  } // end of while

  return 0;
}<|endoftext|>


<commit_before>#include "cinder/app/AppNative.h"
#include "cinder/app/RendererGl.h"

#include "cinder/Rand.h"

#include "cinder/gl/gl.h"
#include "cinder/gl/Context.h"
#include "cinder/gl/Shader.h"
#include "cinder/gl/Vbo.h"
#include "cinder/gl/Vao.h"
#include "cinder/gl/GlslProg.h"

using namespace ci;
using namespace ci::app;
using namespace std;

/**
 Particle type holds information for rendering and simulation.
 Used to buffer initial simulation values.
 */
struct Particle
{
	vec3	pos;
	vec3	ppos;
	vec3	home;
	ColorA  color;	// Q: how to specify type of default attributes to Cinder? e.g. switch to Color8u
	float	damping;
};

// Home many particles to create. (600k default)
const int NUM_PARTICLES = 600e3;

/**
	Simple particle simulation with Verlet integration and mouse interaction.
	A sphere of particles is deformed by mouse interaction.
	Simulation is run using transform feedback on the GPU.
	particleUpdate.vs defines the simulation update step.
	Designed to have the same behavior as ParticleSphereCPU.
 */
class ParticleSphereGPUApp : public AppNative {
  public:
	void prepareSettings( Settings *settings ) override;
	void setup() override;
	void update() override;
	void draw() override;
  private:
	gl::GlslProgRef mRenderProg;
	gl::GlslProgRef mUpdateProg;

	// Descriptions of particle data layout.
	gl::VaoRef		mAttributes[2];
	// Buffers holding raw particle data on GPU.
	gl::VboRef		mParticleBuffer[2];

	// Current source and destination buffers for transform feedback.
	// Source and destination are swapped each frame after update.
	std::uint32_t	mSourceIndex		= 0;
	std::uint32_t	mDestinationIndex	= 1;

	// Mouse state suitable for passing as uniforms to update program
	bool			mMouseDown = false;
	float			mMouseForce = 0.0f;
	vec3			mMousePos = vec3( 0, 0, 0 );
};

void ParticleSphereGPUApp::prepareSettings( Settings *settings )
{
	settings->setWindowSize( 1280, 720 );
}

void ParticleSphereGPUApp::setup()
{
	// Create initial particle layout.
	vector<Particle> particles;
	particles.assign( NUM_PARTICLES, Particle() );
	const float azimuth = 256.0f * M_PI / particles.size();
	const float inclination = M_PI / particles.size();
	const float radius = 180.0f;
	vec3 center = vec3( getWindowCenter(), 0.0f );
	for( int i = 0; i < particles.size(); ++i )
	{	// assign starting values to particles.
		float x = radius * sin( inclination * i ) * cos( azimuth * i );
		float y = radius * cos( inclination * i );
		float z = radius * sin( inclination * i ) * sin( azimuth * i );

		auto &p = particles.at( i );
		p.pos = center + vec3( x, y, z );
		p.home = p.pos;
		p.ppos = p.home + Rand::randVec3f() * 10.0f; // random initial velocity
		p.damping = Rand::randFloat( 0.965f, 0.985f );
		p.color = Color( CM_HSV, lmap<float>( i, 0.0f, particles.size(), 0.0f, 0.66f ), 1.0f, 1.0f );
	}

	// Create particle buffers on GPU and copy data into the first buffer.
	// Mark as static since we only write from the CPU once.
	mParticleBuffer[mSourceIndex] = gl::Vbo::create( GL_ARRAY_BUFFER, particles.size() * sizeof(Particle), particles.data(), GL_STATIC_DRAW );
	mParticleBuffer[mDestinationIndex] = gl::Vbo::create( GL_ARRAY_BUFFER, particles.size() * sizeof(Particle), nullptr, GL_STATIC_DRAW );

	// Create a default color shader.
	mRenderProg = gl::getStockShader( gl::ShaderDef().color() );

	for( int i = 0; i < 2; ++i )
	{	// Describe the particle layout for OpenGL.
		mAttributes[i] = gl::Vao::create();
		mAttributes[i]->bind();

		// Define attributes as offsets into the bound particle buffer
		mParticleBuffer[i]->bind();
		gl::enableVertexAttribArray( 0 );
		gl::enableVertexAttribArray( 1 );
		gl::enableVertexAttribArray( 2 );
		gl::enableVertexAttribArray( 3 );
		gl::enableVertexAttribArray( 4 );
		gl::vertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, sizeof(Particle), (const GLvoid*)offsetof(Particle, pos) );
		gl::vertexAttribPointer( 1, 4, GL_FLOAT, GL_FALSE, sizeof(Particle), (const GLvoid*)offsetof(Particle, color) );
		gl::vertexAttribPointer( 2, 3, GL_FLOAT, GL_FALSE, sizeof(Particle), (const GLvoid*)offsetof(Particle, ppos) );
		gl::vertexAttribPointer( 3, 3, GL_FLOAT, GL_FALSE, sizeof(Particle), (const GLvoid*)offsetof(Particle, home) );
		gl::vertexAttribPointer( 4, 1, GL_FLOAT, GL_FALSE, sizeof(Particle), (const GLvoid*)offsetof(Particle, damping) );
		mAttributes[i]->unbind();
	}

	// Load our update program.
	// Match up our attribute locations with the description we gave.
	mUpdateProg = gl::GlslProg::create( gl::GlslProg::Format().vertex( loadAsset( "particleUpdate.vs" ) )
		.feedbackFormat( GL_INTERLEAVED_ATTRIBS )
		.feedbackVaryings( { "position", "pposition", "home", "color", "damping" } )
		.attribLocation( "iPosition", 0 )
		.attribLocation( "iColor", 1 )
		.attribLocation( "iPPosition", 2 )
		.attribLocation( "iHome", 3 )
		.attribLocation( "iDamping", 4 )
									   );

	// Listen to mouse events so we can send data as uniforms.
	getWindow()->getSignalMouseDown().connect( [this]( MouseEvent event )
											  {
												  mMouseDown = true;
												  mMouseForce = 500.0f;
												  mMousePos = vec3( event.getX(), event.getY(), 0.0f );
											  } );
	getWindow()->getSignalMouseDrag().connect( [this]( MouseEvent event )
											  {
												  mMousePos = vec3( event.getX(), event.getY(), 0.0f );
											  } );
	getWindow()->getSignalMouseUp().connect( [this]( MouseEvent event )
											{
												mMouseForce = 0.0f;
												mMouseDown = false;
											} );
}

void ParticleSphereGPUApp::update()
{
	// Update particles on the GPU
	gl::ScopedGlslProg prog( mUpdateProg );
	gl::ScopedState rasterizer( GL_RASTERIZER_DISCARD, true );	// turn off fragment stage
	mUpdateProg->uniform( "uMouseForce", mMouseForce );
	mUpdateProg->uniform( "uMousePos", mMousePos );

	// Bind the source data (Attributes refer to specific buffers).
	gl::ScopedVao source( mAttributes[mSourceIndex] );
	// Bind destination as buffer base.
	gl::bindBufferBase( GL_TRANSFORM_FEEDBACK_BUFFER, 0, mParticleBuffer[mDestinationIndex] );
	gl::beginTransformFeedback( GL_POINTS );

	// Draw source into destination, performing our vertex transformations.
	gl::drawArrays( GL_POINTS, 0, NUM_PARTICLES );

	gl::endTransformFeedback();

	// Swap source and destination for next loop
	std::swap( mSourceIndex, mDestinationIndex );

	// Update mouse force.
	if( mMouseDown ) {
		mMouseForce = 150.0f;
	}
}

void ParticleSphereGPUApp::draw()
{
	gl::clear( Color( 0, 0, 0 ) );
	gl::setMatricesWindowPersp( getWindowSize() );

	gl::ScopedGlslProg render( mRenderProg );
	gl::ScopedVao vao( mAttributes[mSourceIndex] );
	gl::context()->setDefaultShaderVars();
	gl::drawArrays( GL_POINTS, 0, NUM_PARTICLES );
}

CINDER_APP_NATIVE( ParticleSphereGPUApp, RendererGl )
<commit_msg>Removed question from source code.<commit_after>#include "cinder/app/AppNative.h"
#include "cinder/app/RendererGl.h"

#include "cinder/Rand.h"

#include "cinder/gl/gl.h"
#include "cinder/gl/Context.h"
#include "cinder/gl/Shader.h"
#include "cinder/gl/Vbo.h"
#include "cinder/gl/Vao.h"
#include "cinder/gl/GlslProg.h"

using namespace ci;
using namespace ci::app;
using namespace std;

/**
 Particle type holds information for rendering and simulation.
 Used to buffer initial simulation values.
 */
struct Particle
{
	vec3	pos;
	vec3	ppos;
	vec3	home;
	ColorA  color;
	float	damping;
};

// Home many particles to create. (600k default)
const int NUM_PARTICLES = 600e3;

/**
	Simple particle simulation with Verlet integration and mouse interaction.
	A sphere of particles is deformed by mouse interaction.
	Simulation is run using transform feedback on the GPU.
	particleUpdate.vs defines the simulation update step.
	Designed to have the same behavior as ParticleSphereCPU.
 */
class ParticleSphereGPUApp : public AppNative {
  public:
	void prepareSettings( Settings *settings ) override;
	void setup() override;
	void update() override;
	void draw() override;
  private:
	gl::GlslProgRef mRenderProg;
	gl::GlslProgRef mUpdateProg;

	// Descriptions of particle data layout.
	gl::VaoRef		mAttributes[2];
	// Buffers holding raw particle data on GPU.
	gl::VboRef		mParticleBuffer[2];

	// Current source and destination buffers for transform feedback.
	// Source and destination are swapped each frame after update.
	std::uint32_t	mSourceIndex		= 0;
	std::uint32_t	mDestinationIndex	= 1;

	// Mouse state suitable for passing as uniforms to update program
	bool			mMouseDown = false;
	float			mMouseForce = 0.0f;
	vec3			mMousePos = vec3( 0, 0, 0 );
};

void ParticleSphereGPUApp::prepareSettings( Settings *settings )
{
	settings->setWindowSize( 1280, 720 );
}

void ParticleSphereGPUApp::setup()
{
	// Create initial particle layout.
	vector<Particle> particles;
	particles.assign( NUM_PARTICLES, Particle() );
	const float azimuth = 256.0f * M_PI / particles.size();
	const float inclination = M_PI / particles.size();
	const float radius = 180.0f;
	vec3 center = vec3( getWindowCenter(), 0.0f );
	for( int i = 0; i < particles.size(); ++i )
	{	// assign starting values to particles.
		float x = radius * sin( inclination * i ) * cos( azimuth * i );
		float y = radius * cos( inclination * i );
		float z = radius * sin( inclination * i ) * sin( azimuth * i );

		auto &p = particles.at( i );
		p.pos = center + vec3( x, y, z );
		p.home = p.pos;
		p.ppos = p.home + Rand::randVec3f() * 10.0f; // random initial velocity
		p.damping = Rand::randFloat( 0.965f, 0.985f );
		p.color = Color( CM_HSV, lmap<float>( i, 0.0f, particles.size(), 0.0f, 0.66f ), 1.0f, 1.0f );
	}

	// Create particle buffers on GPU and copy data into the first buffer.
	// Mark as static since we only write from the CPU once.
	mParticleBuffer[mSourceIndex] = gl::Vbo::create( GL_ARRAY_BUFFER, particles.size() * sizeof(Particle), particles.data(), GL_STATIC_DRAW );
	mParticleBuffer[mDestinationIndex] = gl::Vbo::create( GL_ARRAY_BUFFER, particles.size() * sizeof(Particle), nullptr, GL_STATIC_DRAW );

	// Create a default color shader.
	mRenderProg = gl::getStockShader( gl::ShaderDef().color() );

	for( int i = 0; i < 2; ++i )
	{	// Describe the particle layout for OpenGL.
		mAttributes[i] = gl::Vao::create();
		mAttributes[i]->bind();

		// Define attributes as offsets into the bound particle buffer
		mParticleBuffer[i]->bind();
		gl::enableVertexAttribArray( 0 );
		gl::enableVertexAttribArray( 1 );
		gl::enableVertexAttribArray( 2 );
		gl::enableVertexAttribArray( 3 );
		gl::enableVertexAttribArray( 4 );
		gl::vertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, sizeof(Particle), (const GLvoid*)offsetof(Particle, pos) );
		gl::vertexAttribPointer( 1, 4, GL_FLOAT, GL_FALSE, sizeof(Particle), (const GLvoid*)offsetof(Particle, color) );
		gl::vertexAttribPointer( 2, 3, GL_FLOAT, GL_FALSE, sizeof(Particle), (const GLvoid*)offsetof(Particle, ppos) );
		gl::vertexAttribPointer( 3, 3, GL_FLOAT, GL_FALSE, sizeof(Particle), (const GLvoid*)offsetof(Particle, home) );
		gl::vertexAttribPointer( 4, 1, GL_FLOAT, GL_FALSE, sizeof(Particle), (const GLvoid*)offsetof(Particle, damping) );
		mAttributes[i]->unbind();
	}

	// Load our update program.
	// Match up our attribute locations with the description we gave.
	mUpdateProg = gl::GlslProg::create( gl::GlslProg::Format().vertex( loadAsset( "particleUpdate.vs" ) )
		.feedbackFormat( GL_INTERLEAVED_ATTRIBS )
		.feedbackVaryings( { "position", "pposition", "home", "color", "damping" } )
		.attribLocation( "iPosition", 0 )
		.attribLocation( "iColor", 1 )
		.attribLocation( "iPPosition", 2 )
		.attribLocation( "iHome", 3 )
		.attribLocation( "iDamping", 4 )
									   );

	// Listen to mouse events so we can send data as uniforms.
	getWindow()->getSignalMouseDown().connect( [this]( MouseEvent event )
											  {
												  mMouseDown = true;
												  mMouseForce = 500.0f;
												  mMousePos = vec3( event.getX(), event.getY(), 0.0f );
											  } );
	getWindow()->getSignalMouseDrag().connect( [this]( MouseEvent event )
											  {
												  mMousePos = vec3( event.getX(), event.getY(), 0.0f );
											  } );
	getWindow()->getSignalMouseUp().connect( [this]( MouseEvent event )
											{
												mMouseForce = 0.0f;
												mMouseDown = false;
											} );
}

void ParticleSphereGPUApp::update()
{
	// Update particles on the GPU
	gl::ScopedGlslProg prog( mUpdateProg );
	gl::ScopedState rasterizer( GL_RASTERIZER_DISCARD, true );	// turn off fragment stage
	mUpdateProg->uniform( "uMouseForce", mMouseForce );
	mUpdateProg->uniform( "uMousePos", mMousePos );

	// Bind the source data (Attributes refer to specific buffers).
	gl::ScopedVao source( mAttributes[mSourceIndex] );
	// Bind destination as buffer base.
	gl::bindBufferBase( GL_TRANSFORM_FEEDBACK_BUFFER, 0, mParticleBuffer[mDestinationIndex] );
	gl::beginTransformFeedback( GL_POINTS );

	// Draw source into destination, performing our vertex transformations.
	gl::drawArrays( GL_POINTS, 0, NUM_PARTICLES );

	gl::endTransformFeedback();

	// Swap source and destination for next loop
	std::swap( mSourceIndex, mDestinationIndex );

	// Update mouse force.
	if( mMouseDown ) {
		mMouseForce = 150.0f;
	}
}

void ParticleSphereGPUApp::draw()
{
	gl::clear( Color( 0, 0, 0 ) );
	gl::setMatricesWindowPersp( getWindowSize() );

	gl::ScopedGlslProg render( mRenderProg );
	gl::ScopedVao vao( mAttributes[mSourceIndex] );
	gl::context()->setDefaultShaderVars();
	gl::drawArrays( GL_POINTS, 0, NUM_PARTICLES );
}

CINDER_APP_NATIVE( ParticleSphereGPUApp, RendererGl )
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2002-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * 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;
 * neither the name of the copyright holders 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
 * OWNER 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.
 *
 * Authors: Steve Reinhardt
 */

#include "arch/utility.hh"
#include "arch/faults.hh"
#include "base/cprintf.hh"
#include "base/inifile.hh"
#include "base/loader/symtab.hh"
#include "base/misc.hh"
#include "base/pollevent.hh"
#include "base/range.hh"
#include "base/stats/events.hh"
#include "base/trace.hh"
#include "cpu/base.hh"
#include "cpu/exetrace.hh"
#include "cpu/profile.hh"
#include "cpu/simple/base.hh"
#include "cpu/simple_thread.hh"
#include "cpu/smt.hh"
#include "cpu/static_inst.hh"
#include "cpu/thread_context.hh"
#include "mem/packet.hh"
#include "sim/builder.hh"
#include "sim/byteswap.hh"
#include "sim/debug.hh"
#include "sim/host.hh"
#include "sim/sim_events.hh"
#include "sim/sim_object.hh"
#include "sim/stats.hh"
#include "sim/system.hh"

#if FULL_SYSTEM
#include "arch/kernel_stats.hh"
#include "arch/stacktrace.hh"
#include "arch/tlb.hh"
#include "arch/vtophys.hh"
#include "base/remote_gdb.hh"
#else // !FULL_SYSTEM
#include "mem/mem_object.hh"
#endif // FULL_SYSTEM

using namespace std;
using namespace TheISA;

BaseSimpleCPU::BaseSimpleCPU(Params *p)
    : BaseCPU(p), thread(NULL), predecoder(NULL)
{
#if FULL_SYSTEM
    thread = new SimpleThread(this, 0, p->system, p->itb, p->dtb);
#else
    thread = new SimpleThread(this, /* thread_num */ 0, p->process,
            /* asid */ 0);
#endif // !FULL_SYSTEM

    thread->setStatus(ThreadContext::Suspended);

    tc = thread->getTC();

    numInst = 0;
    startNumInst = 0;
    numLoad = 0;
    startNumLoad = 0;
    lastIcacheStall = 0;
    lastDcacheStall = 0;

    threadContexts.push_back(tc);
}

BaseSimpleCPU::~BaseSimpleCPU()
{
}

void
BaseSimpleCPU::deallocateContext(int thread_num)
{
    // for now, these are equivalent
    suspendContext(thread_num);
}

void
BaseSimpleCPU::haltContext(int thread_num)
{
    // for now, these are equivalent
    suspendContext(thread_num);
}

void
BaseSimpleCPU::regStats()
{
    using namespace Stats;

    BaseCPU::regStats();

    numInsts
        .name(name() + ".num_insts")
        .desc("Number of instructions executed")
        ;

    numMemRefs
        .name(name() + ".num_refs")
        .desc("Number of memory references")
        ;

    notIdleFraction
        .name(name() + ".not_idle_fraction")
        .desc("Percentage of non-idle cycles")
        ;

    idleFraction
        .name(name() + ".idle_fraction")
        .desc("Percentage of idle cycles")
        ;

    icacheStallCycles
        .name(name() + ".icache_stall_cycles")
        .desc("ICache total stall cycles")
        .prereq(icacheStallCycles)
        ;

    dcacheStallCycles
        .name(name() + ".dcache_stall_cycles")
        .desc("DCache total stall cycles")
        .prereq(dcacheStallCycles)
        ;

    icacheRetryCycles
        .name(name() + ".icache_retry_cycles")
        .desc("ICache total retry cycles")
        .prereq(icacheRetryCycles)
        ;

    dcacheRetryCycles
        .name(name() + ".dcache_retry_cycles")
        .desc("DCache total retry cycles")
        .prereq(dcacheRetryCycles)
        ;

    idleFraction = constant(1.0) - notIdleFraction;
}

void
BaseSimpleCPU::resetStats()
{
//    startNumInst = numInst;
    // notIdleFraction = (_status != Idle);
}

void
BaseSimpleCPU::serialize(ostream &os)
{
    BaseCPU::serialize(os);
//    SERIALIZE_SCALAR(inst);
    nameOut(os, csprintf("%s.xc.0", name()));
    thread->serialize(os);
}

void
BaseSimpleCPU::unserialize(Checkpoint *cp, const string &section)
{
    BaseCPU::unserialize(cp, section);
//    UNSERIALIZE_SCALAR(inst);
    thread->unserialize(cp, csprintf("%s.xc.0", section));
}

void
change_thread_state(int thread_number, int activate, int priority)
{
}

Fault
BaseSimpleCPU::copySrcTranslate(Addr src)
{
#if 0
    static bool no_warn = true;
    int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64;
    // Only support block sizes of 64 atm.
    assert(blk_size == 64);
    int offset = src & (blk_size - 1);

    // Make sure block doesn't span page
    if (no_warn &&
        (src & PageMask) != ((src + blk_size) & PageMask) &&
        (src >> 40) != 0xfffffc) {
        warn("Copied block source spans pages %x.", src);
        no_warn = false;
    }

    memReq->reset(src & ~(blk_size - 1), blk_size);

    // translate to physical address
    Fault fault = thread->translateDataReadReq(req);

    if (fault == NoFault) {
        thread->copySrcAddr = src;
        thread->copySrcPhysAddr = memReq->paddr + offset;
    } else {
        assert(!fault->isAlignmentFault());

        thread->copySrcAddr = 0;
        thread->copySrcPhysAddr = 0;
    }
    return fault;
#else
    return NoFault;
#endif
}

Fault
BaseSimpleCPU::copy(Addr dest)
{
#if 0
    static bool no_warn = true;
    int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64;
    // Only support block sizes of 64 atm.
    assert(blk_size == 64);
    uint8_t data[blk_size];
    //assert(thread->copySrcAddr);
    int offset = dest & (blk_size - 1);

    // Make sure block doesn't span page
    if (no_warn &&
        (dest & PageMask) != ((dest + blk_size) & PageMask) &&
        (dest >> 40) != 0xfffffc) {
        no_warn = false;
        warn("Copied block destination spans pages %x. ", dest);
    }

    memReq->reset(dest & ~(blk_size -1), blk_size);
    // translate to physical address
    Fault fault = thread->translateDataWriteReq(req);

    if (fault == NoFault) {
        Addr dest_addr = memReq->paddr + offset;
        // Need to read straight from memory since we have more than 8 bytes.
        memReq->paddr = thread->copySrcPhysAddr;
        thread->mem->read(memReq, data);
        memReq->paddr = dest_addr;
        thread->mem->write(memReq, data);
        if (dcacheInterface) {
            memReq->cmd = Copy;
            memReq->completionEvent = NULL;
            memReq->paddr = thread->copySrcPhysAddr;
            memReq->dest = dest_addr;
            memReq->size = 64;
            memReq->time = curTick;
            memReq->flags &= ~INST_READ;
            dcacheInterface->access(memReq);
        }
    }
    else
        assert(!fault->isAlignmentFault());

    return fault;
#else
    panic("copy not implemented");
    return NoFault;
#endif
}

#if FULL_SYSTEM
Addr
BaseSimpleCPU::dbg_vtophys(Addr addr)
{
    return vtophys(tc, addr);
}
#endif // FULL_SYSTEM

#if FULL_SYSTEM
void
BaseSimpleCPU::post_interrupt(int int_num, int index)
{
    BaseCPU::post_interrupt(int_num, index);

    if (thread->status() == ThreadContext::Suspended) {
                DPRINTF(Quiesce,"Suspended Processor awoke\n");
        thread->activate();
    }
}
#endif // FULL_SYSTEM

void
BaseSimpleCPU::checkForInterrupts()
{
#if FULL_SYSTEM
    if (check_interrupts(tc)) {
        Fault interrupt = interrupts.getInterrupt(tc);

        if (interrupt != NoFault) {
            interrupts.updateIntrInfo(tc);
            interrupt->invoke(tc);
        }
    }
#endif
}

Fault
BaseSimpleCPU::setupFetchRequest(Request *req)
{
    // set up memory request for instruction fetch
#if ISA_HAS_DELAY_SLOT
    DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p NNPC:%08p\n",thread->readPC(),
            thread->readNextPC(),thread->readNextNPC());
#else
    DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p",thread->readPC(),
            thread->readNextPC());
#endif

    req->setVirt(0, thread->readPC() & ~3, sizeof(MachInst), 0,
            thread->readPC());

    Fault fault = thread->translateInstReq(req);

    return fault;
}

void
BaseSimpleCPU::preExecute()
{
    // maintain $r0 semantics
    thread->setIntReg(ZeroReg, 0);
#if THE_ISA == ALPHA_ISA
    thread->setFloatReg(ZeroReg, 0.0);
#endif // ALPHA_ISA

    // keep an instruction count
    numInst++;
    numInsts++;

    thread->funcExeInst++;

    // check for instruction-count-based events
    comInstEventQueue[0]->serviceEvents(numInst);

    // decode the instruction
    inst = gtoh(inst);
    //If we're not in the middle of a macro instruction
    if (!curMacroStaticInst) {
        StaticInstPtr instPtr = NULL;

        //Predecode, ie bundle up an ExtMachInst
        //This should go away once the constructor can be set up properly
        predecoder.setTC(thread->getTC());
        //If more fetch data is needed, pass it in.
        if(predecoder.needMoreBytes())
            predecoder.moreBytes(thread->readPC(), 0, inst);
        else
            predecoder.process();
        //If an instruction is ready, decode it
        if (predecoder.extMachInstReady())
            instPtr = StaticInst::decode(predecoder.getExtMachInst());

        //If we decoded an instruction and it's microcoded, start pulling
        //out micro ops
        if (instPtr && instPtr->isMacroOp()) {
            curMacroStaticInst = instPtr;
            curStaticInst = curMacroStaticInst->
                fetchMicroOp(thread->readMicroPC());
        } else {
            curStaticInst = instPtr;
        }
    } else {
        //Read the next micro op from the macro op
        curStaticInst = curMacroStaticInst->
            fetchMicroOp(thread->readMicroPC());
    }

    //If we decoded an instruction this "tick", record information about it.
    if(curStaticInst)
    {
        traceData = Trace::getInstRecord(curTick, tc, curStaticInst,
                                         thread->readPC());

        DPRINTF(Decode,"Decode: Decoded %s instruction: 0x%x\n",
                curStaticInst->getName(), curStaticInst->machInst);

#if FULL_SYSTEM
        thread->setInst(inst);
#endif // FULL_SYSTEM
    }
}

void
BaseSimpleCPU::postExecute()
{
#if FULL_SYSTEM
    if (thread->profile) {
        bool usermode = TheISA::inUserMode(tc);
        thread->profilePC = usermode ? 1 : thread->readPC();
        StaticInstPtr si(inst);
        ProfileNode *node = thread->profile->consume(tc, si);
        if (node)
            thread->profileNode = node;
    }
#endif

    if (curStaticInst->isMemRef()) {
        numMemRefs++;
    }

    if (curStaticInst->isLoad()) {
        ++numLoad;
        comLoadEventQueue[0]->serviceEvents(numLoad);
    }

    traceFunctions(thread->readPC());

    if (traceData) {
        traceData->dump();
        delete traceData;
        traceData = NULL;
    }
}

void
BaseSimpleCPU::advancePC(Fault fault)
{
    if (fault != NoFault) {
        curMacroStaticInst = StaticInst::nullStaticInstPtr;
        fault->invoke(tc);
        thread->setMicroPC(0);
        thread->setNextMicroPC(1);
    } else if (predecoder.needMoreBytes()) {
        //If we're at the last micro op for this instruction
        if (curStaticInst && curStaticInst->isLastMicroOp()) {
            //We should be working with a macro op
            assert(curMacroStaticInst);
            //Close out this macro op, and clean up the
            //microcode state
            curMacroStaticInst = StaticInst::nullStaticInstPtr;
            thread->setMicroPC(0);
            thread->setNextMicroPC(1);
        }
        //If we're still in a macro op
        if (curMacroStaticInst) {
            //Advance the micro pc
            thread->setMicroPC(thread->readNextMicroPC());
            //Advance the "next" micro pc. Note that there are no delay
            //slots, and micro ops are "word" addressed.
            thread->setNextMicroPC(thread->readNextMicroPC() + 1);
        } else {
            // go to the next instruction
            thread->setPC(thread->readNextPC());
            thread->setNextPC(thread->readNextNPC());
            thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst));
            assert(thread->readNextPC() != thread->readNextNPC());
        }
    }

#if FULL_SYSTEM
    Addr oldpc;
    do {
        oldpc = thread->readPC();
        system->pcEventQueue.service(tc);
    } while (oldpc != thread->readPC());
#endif
}

<commit_msg>Use a computed mask to mask out the fetch address and not a hard coded one.<commit_after>/*
 * Copyright (c) 2002-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * 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;
 * neither the name of the copyright holders 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
 * OWNER 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.
 *
 * Authors: Steve Reinhardt
 */

#include "arch/utility.hh"
#include "arch/faults.hh"
#include "base/cprintf.hh"
#include "base/inifile.hh"
#include "base/loader/symtab.hh"
#include "base/misc.hh"
#include "base/pollevent.hh"
#include "base/range.hh"
#include "base/stats/events.hh"
#include "base/trace.hh"
#include "cpu/base.hh"
#include "cpu/exetrace.hh"
#include "cpu/profile.hh"
#include "cpu/simple/base.hh"
#include "cpu/simple_thread.hh"
#include "cpu/smt.hh"
#include "cpu/static_inst.hh"
#include "cpu/thread_context.hh"
#include "mem/packet.hh"
#include "sim/builder.hh"
#include "sim/byteswap.hh"
#include "sim/debug.hh"
#include "sim/host.hh"
#include "sim/sim_events.hh"
#include "sim/sim_object.hh"
#include "sim/stats.hh"
#include "sim/system.hh"

#if FULL_SYSTEM
#include "arch/kernel_stats.hh"
#include "arch/stacktrace.hh"
#include "arch/tlb.hh"
#include "arch/vtophys.hh"
#include "base/remote_gdb.hh"
#else // !FULL_SYSTEM
#include "mem/mem_object.hh"
#endif // FULL_SYSTEM

using namespace std;
using namespace TheISA;

BaseSimpleCPU::BaseSimpleCPU(Params *p)
    : BaseCPU(p), thread(NULL), predecoder(NULL)
{
#if FULL_SYSTEM
    thread = new SimpleThread(this, 0, p->system, p->itb, p->dtb);
#else
    thread = new SimpleThread(this, /* thread_num */ 0, p->process,
            /* asid */ 0);
#endif // !FULL_SYSTEM

    thread->setStatus(ThreadContext::Suspended);

    tc = thread->getTC();

    numInst = 0;
    startNumInst = 0;
    numLoad = 0;
    startNumLoad = 0;
    lastIcacheStall = 0;
    lastDcacheStall = 0;

    threadContexts.push_back(tc);
}

BaseSimpleCPU::~BaseSimpleCPU()
{
}

void
BaseSimpleCPU::deallocateContext(int thread_num)
{
    // for now, these are equivalent
    suspendContext(thread_num);
}

void
BaseSimpleCPU::haltContext(int thread_num)
{
    // for now, these are equivalent
    suspendContext(thread_num);
}

void
BaseSimpleCPU::regStats()
{
    using namespace Stats;

    BaseCPU::regStats();

    numInsts
        .name(name() + ".num_insts")
        .desc("Number of instructions executed")
        ;

    numMemRefs
        .name(name() + ".num_refs")
        .desc("Number of memory references")
        ;

    notIdleFraction
        .name(name() + ".not_idle_fraction")
        .desc("Percentage of non-idle cycles")
        ;

    idleFraction
        .name(name() + ".idle_fraction")
        .desc("Percentage of idle cycles")
        ;

    icacheStallCycles
        .name(name() + ".icache_stall_cycles")
        .desc("ICache total stall cycles")
        .prereq(icacheStallCycles)
        ;

    dcacheStallCycles
        .name(name() + ".dcache_stall_cycles")
        .desc("DCache total stall cycles")
        .prereq(dcacheStallCycles)
        ;

    icacheRetryCycles
        .name(name() + ".icache_retry_cycles")
        .desc("ICache total retry cycles")
        .prereq(icacheRetryCycles)
        ;

    dcacheRetryCycles
        .name(name() + ".dcache_retry_cycles")
        .desc("DCache total retry cycles")
        .prereq(dcacheRetryCycles)
        ;

    idleFraction = constant(1.0) - notIdleFraction;
}

void
BaseSimpleCPU::resetStats()
{
//    startNumInst = numInst;
    // notIdleFraction = (_status != Idle);
}

void
BaseSimpleCPU::serialize(ostream &os)
{
    BaseCPU::serialize(os);
//    SERIALIZE_SCALAR(inst);
    nameOut(os, csprintf("%s.xc.0", name()));
    thread->serialize(os);
}

void
BaseSimpleCPU::unserialize(Checkpoint *cp, const string &section)
{
    BaseCPU::unserialize(cp, section);
//    UNSERIALIZE_SCALAR(inst);
    thread->unserialize(cp, csprintf("%s.xc.0", section));
}

void
change_thread_state(int thread_number, int activate, int priority)
{
}

Fault
BaseSimpleCPU::copySrcTranslate(Addr src)
{
#if 0
    static bool no_warn = true;
    int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64;
    // Only support block sizes of 64 atm.
    assert(blk_size == 64);
    int offset = src & (blk_size - 1);

    // Make sure block doesn't span page
    if (no_warn &&
        (src & PageMask) != ((src + blk_size) & PageMask) &&
        (src >> 40) != 0xfffffc) {
        warn("Copied block source spans pages %x.", src);
        no_warn = false;
    }

    memReq->reset(src & ~(blk_size - 1), blk_size);

    // translate to physical address
    Fault fault = thread->translateDataReadReq(req);

    if (fault == NoFault) {
        thread->copySrcAddr = src;
        thread->copySrcPhysAddr = memReq->paddr + offset;
    } else {
        assert(!fault->isAlignmentFault());

        thread->copySrcAddr = 0;
        thread->copySrcPhysAddr = 0;
    }
    return fault;
#else
    return NoFault;
#endif
}

Fault
BaseSimpleCPU::copy(Addr dest)
{
#if 0
    static bool no_warn = true;
    int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64;
    // Only support block sizes of 64 atm.
    assert(blk_size == 64);
    uint8_t data[blk_size];
    //assert(thread->copySrcAddr);
    int offset = dest & (blk_size - 1);

    // Make sure block doesn't span page
    if (no_warn &&
        (dest & PageMask) != ((dest + blk_size) & PageMask) &&
        (dest >> 40) != 0xfffffc) {
        no_warn = false;
        warn("Copied block destination spans pages %x. ", dest);
    }

    memReq->reset(dest & ~(blk_size -1), blk_size);
    // translate to physical address
    Fault fault = thread->translateDataWriteReq(req);

    if (fault == NoFault) {
        Addr dest_addr = memReq->paddr + offset;
        // Need to read straight from memory since we have more than 8 bytes.
        memReq->paddr = thread->copySrcPhysAddr;
        thread->mem->read(memReq, data);
        memReq->paddr = dest_addr;
        thread->mem->write(memReq, data);
        if (dcacheInterface) {
            memReq->cmd = Copy;
            memReq->completionEvent = NULL;
            memReq->paddr = thread->copySrcPhysAddr;
            memReq->dest = dest_addr;
            memReq->size = 64;
            memReq->time = curTick;
            memReq->flags &= ~INST_READ;
            dcacheInterface->access(memReq);
        }
    }
    else
        assert(!fault->isAlignmentFault());

    return fault;
#else
    panic("copy not implemented");
    return NoFault;
#endif
}

#if FULL_SYSTEM
Addr
BaseSimpleCPU::dbg_vtophys(Addr addr)
{
    return vtophys(tc, addr);
}
#endif // FULL_SYSTEM

#if FULL_SYSTEM
void
BaseSimpleCPU::post_interrupt(int int_num, int index)
{
    BaseCPU::post_interrupt(int_num, index);

    if (thread->status() == ThreadContext::Suspended) {
                DPRINTF(Quiesce,"Suspended Processor awoke\n");
        thread->activate();
    }
}
#endif // FULL_SYSTEM

void
BaseSimpleCPU::checkForInterrupts()
{
#if FULL_SYSTEM
    if (check_interrupts(tc)) {
        Fault interrupt = interrupts.getInterrupt(tc);

        if (interrupt != NoFault) {
            interrupts.updateIntrInfo(tc);
            interrupt->invoke(tc);
        }
    }
#endif
}

Fault
BaseSimpleCPU::setupFetchRequest(Request *req)
{
    // set up memory request for instruction fetch
#if ISA_HAS_DELAY_SLOT
    DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p NNPC:%08p\n",thread->readPC(),
            thread->readNextPC(),thread->readNextNPC());
#else
    DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p",thread->readPC(),
            thread->readNextPC());
#endif

    // This will generate a mask which aligns the pc on MachInst size
    // boundaries. It won't work for non-power-of-two sized MachInsts, but
    // it will work better than a hard coded mask.
    const Addr PCMask = ~(sizeof(MachInst) - 1);
    req->setVirt(0, thread->readPC() & PCMask, sizeof(MachInst), 0,
            thread->readPC());

    Fault fault = thread->translateInstReq(req);

    return fault;
}

void
BaseSimpleCPU::preExecute()
{
    // maintain $r0 semantics
    thread->setIntReg(ZeroReg, 0);
#if THE_ISA == ALPHA_ISA
    thread->setFloatReg(ZeroReg, 0.0);
#endif // ALPHA_ISA

    // keep an instruction count
    numInst++;
    numInsts++;

    thread->funcExeInst++;

    // check for instruction-count-based events
    comInstEventQueue[0]->serviceEvents(numInst);

    // decode the instruction
    inst = gtoh(inst);
    //If we're not in the middle of a macro instruction
    if (!curMacroStaticInst) {
        StaticInstPtr instPtr = NULL;

        //Predecode, ie bundle up an ExtMachInst
        //This should go away once the constructor can be set up properly
        predecoder.setTC(thread->getTC());
        //If more fetch data is needed, pass it in.
        if(predecoder.needMoreBytes())
            predecoder.moreBytes(thread->readPC(), 0, inst);
        else
            predecoder.process();
        //If an instruction is ready, decode it
        if (predecoder.extMachInstReady())
            instPtr = StaticInst::decode(predecoder.getExtMachInst());

        //If we decoded an instruction and it's microcoded, start pulling
        //out micro ops
        if (instPtr && instPtr->isMacroOp()) {
            curMacroStaticInst = instPtr;
            curStaticInst = curMacroStaticInst->
                fetchMicroOp(thread->readMicroPC());
        } else {
            curStaticInst = instPtr;
        }
    } else {
        //Read the next micro op from the macro op
        curStaticInst = curMacroStaticInst->
            fetchMicroOp(thread->readMicroPC());
    }

    //If we decoded an instruction this "tick", record information about it.
    if(curStaticInst)
    {
        traceData = Trace::getInstRecord(curTick, tc, curStaticInst,
                                         thread->readPC());

        DPRINTF(Decode,"Decode: Decoded %s instruction: 0x%x\n",
                curStaticInst->getName(), curStaticInst->machInst);

#if FULL_SYSTEM
        thread->setInst(inst);
#endif // FULL_SYSTEM
    }
}

void
BaseSimpleCPU::postExecute()
{
#if FULL_SYSTEM
    if (thread->profile) {
        bool usermode = TheISA::inUserMode(tc);
        thread->profilePC = usermode ? 1 : thread->readPC();
        StaticInstPtr si(inst);
        ProfileNode *node = thread->profile->consume(tc, si);
        if (node)
            thread->profileNode = node;
    }
#endif

    if (curStaticInst->isMemRef()) {
        numMemRefs++;
    }

    if (curStaticInst->isLoad()) {
        ++numLoad;
        comLoadEventQueue[0]->serviceEvents(numLoad);
    }

    traceFunctions(thread->readPC());

    if (traceData) {
        traceData->dump();
        delete traceData;
        traceData = NULL;
    }
}

void
BaseSimpleCPU::advancePC(Fault fault)
{
    if (fault != NoFault) {
        curMacroStaticInst = StaticInst::nullStaticInstPtr;
        fault->invoke(tc);
        thread->setMicroPC(0);
        thread->setNextMicroPC(1);
    } else if (predecoder.needMoreBytes()) {
        //If we're at the last micro op for this instruction
        if (curStaticInst && curStaticInst->isLastMicroOp()) {
            //We should be working with a macro op
            assert(curMacroStaticInst);
            //Close out this macro op, and clean up the
            //microcode state
            curMacroStaticInst = StaticInst::nullStaticInstPtr;
            thread->setMicroPC(0);
            thread->setNextMicroPC(1);
        }
        //If we're still in a macro op
        if (curMacroStaticInst) {
            //Advance the micro pc
            thread->setMicroPC(thread->readNextMicroPC());
            //Advance the "next" micro pc. Note that there are no delay
            //slots, and micro ops are "word" addressed.
            thread->setNextMicroPC(thread->readNextMicroPC() + 1);
        } else {
            // go to the next instruction
            thread->setPC(thread->readNextPC());
            thread->setNextPC(thread->readNextNPC());
            thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst));
            assert(thread->readNextPC() != thread->readNextNPC());
        }
    }

#if FULL_SYSTEM
    Addr oldpc;
    do {
        oldpc = thread->readPC();
        system->pcEventQueue.service(tc);
    } while (oldpc != thread->readPC());
#endif
}

<|endoftext|>


<commit_before>#include "stdafx.h"
#include "Effect10.h"

using namespace System;
using namespace System::Collections::Generic;

namespace SlimDX
{
	namespace Direct3D10
	{
		EffectPass10::EffectPass10(ID3D10EffectPass* native) : native(native) {
		}

		void EffectPass10::Apply() {
			native->Apply(0);
		}

		EffectPassDescription10 EffectPass10::GetDescription() {
			EffectPassDescription10 result;
			D3D10_PASS_DESC passDesc;
			native->GetDesc(&passDesc);

			result.Name = gcnew System::String(passDesc.Name);
			result.Annotations = passDesc.Annotations;
			result.StencilRef = passDesc.StencilRef;
			result.SampleMask = passDesc.SampleMask;
			result.BlendFactorR = passDesc.BlendFactor[0];
			result.BlendFactorG = passDesc.BlendFactor[1];
			result.BlendFactorB = passDesc.BlendFactor[2];
			result.BlendFactorA = passDesc.BlendFactor[3];

			ShaderSignature10 signature;
			signature.Signature = IntPtr(passDesc.pIAInputSignature);
			signature.SignatureLength = passDesc.IAInputSignatureSize;

			result.ShaderSignature = signature;

			return result;
		}

		EffectTechnique10::EffectTechnique10(ID3D10EffectTechnique* native) : native(native) {
			passes = gcnew Dictionary<IntPtr, EffectPass10^>();
		}

		IEffectPass10^ EffectTechnique10::GetPassByIndex(int index) {
			ID3D10EffectPass* pass = native->GetPassByIndex(index);
			if(!passes->ContainsKey(IntPtr(pass))) {
				passes->Add(IntPtr(pass), gcnew EffectPass10(pass));;
			}

			return passes[IntPtr(pass)];
		}

		Effect10::Effect10( ID3D10Effect* native ) : ComObject<ID3D10Effect>(native) {
			techniques = gcnew Dictionary<IntPtr, EffectTechnique10^>();
		}

		Effect10::Effect10( System::IntPtr native ) : ComObject<ID3D10Effect>(native) {
			techniques = gcnew Dictionary<IntPtr, EffectTechnique10^>();
		}

		IEffectTechnique10^ Effect10::GetTechniqueByIndex(int index) {
			ID3D10EffectTechnique* technique = NativePointer->GetTechniqueByIndex(index);
			if(!techniques->ContainsKey(IntPtr(technique))) {
				techniques->Add(IntPtr(technique), gcnew EffectTechnique10(technique));;
			}

			return techniques[IntPtr(technique)];
		}
	}
}<commit_msg>Fixed a signed/unsigned warning.<commit_after>#include "stdafx.h"
#include "Effect10.h"

using namespace System;
using namespace System::Collections::Generic;

namespace SlimDX
{
	namespace Direct3D10
	{
		EffectPass10::EffectPass10(ID3D10EffectPass* native) : native(native) {
		}

		void EffectPass10::Apply() {
			native->Apply(0);
		}

		EffectPassDescription10 EffectPass10::GetDescription() {
			EffectPassDescription10 result;
			D3D10_PASS_DESC passDesc;
			native->GetDesc(&passDesc);

			result.Name = gcnew System::String(passDesc.Name);
			result.Annotations = passDesc.Annotations;
			result.StencilRef = passDesc.StencilRef;
			result.SampleMask = passDesc.SampleMask;
			result.BlendFactorR = passDesc.BlendFactor[0];
			result.BlendFactorG = passDesc.BlendFactor[1];
			result.BlendFactorB = passDesc.BlendFactor[2];
			result.BlendFactorA = passDesc.BlendFactor[3];

			ShaderSignature10 signature;
			signature.Signature = IntPtr(passDesc.pIAInputSignature);
			signature.SignatureLength = static_cast<int>( passDesc.IAInputSignatureSize );

			result.ShaderSignature = signature;

			return result;
		}

		EffectTechnique10::EffectTechnique10(ID3D10EffectTechnique* native) : native(native) {
			passes = gcnew Dictionary<IntPtr, EffectPass10^>();
		}

		IEffectPass10^ EffectTechnique10::GetPassByIndex(int index) {
			ID3D10EffectPass* pass = native->GetPassByIndex(index);
			if(!passes->ContainsKey(IntPtr(pass))) {
				passes->Add(IntPtr(pass), gcnew EffectPass10(pass));;
			}

			return passes[IntPtr(pass)];
		}

		Effect10::Effect10( ID3D10Effect* native ) : ComObject<ID3D10Effect>(native) {
			techniques = gcnew Dictionary<IntPtr, EffectTechnique10^>();
		}

		Effect10::Effect10( System::IntPtr native ) : ComObject<ID3D10Effect>(native) {
			techniques = gcnew Dictionary<IntPtr, EffectTechnique10^>();
		}

		IEffectTechnique10^ Effect10::GetTechniqueByIndex(int index) {
			ID3D10EffectTechnique* technique = NativePointer->GetTechniqueByIndex(index);
			if(!techniques->ContainsKey(IntPtr(technique))) {
				techniques->Add(IntPtr(technique), gcnew EffectTechnique10(technique));;
			}

			return techniques[IntPtr(technique)];
		}
	}
}<|endoftext|>


<commit_before><commit_msg>Fix another name I missed. Review URL: http://codereview.chromium.org/113727<commit_after><|endoftext|>