<commit_before>/*
Copyright (c) 2012-2020, Intel Corporation
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 Intel Corporation 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.
*/

// written by Roman Dementiev
#define HACK_TO_REMOVE_DUPLICATE_ERROR
#include "cpucounters.h"
#ifdef _MSC_VER
#include <windows.h>
#include "../PCM_Win/windriver.h"
#else
#include <unistd.h>
#endif
#include <iostream>
#include <stdlib.h>
#include <iomanip>
#include <string.h>
#ifdef _MSC_VER
#include "freegetopt/getopt.h"
#endif

uint64 read_number(char * str)
{
    std::istringstream stream(str);
    if (strstr(str, "x")) stream >> std::hex;
    uint64 result = 0;
    stream >> result;
    return result;
}

void print_usage(const char * progname)
{
    std::cout << "Usage " << progname << " [-w value] [-c core] [-d] msr\n\n";
    std::cout << "  Reads specified msr (model specific register) \n";
    std::cout << "   -w value : write the value before reading \n";
    std::cout << "   -c core  : perform msr read/write on specified core (default is 0)\n";
    std::cout << "   -d       : output all numbers in dec (default is hex)\n";
    std::cout << "   -a       : perform msr read/write operations on all cores\n";
    std::cout << "\n";
}

int main(int argc, char * argv[])
{
    std::cout << "\n Processor Counter Monitor " << PCM_VERSION << std::endl;

    std::cout << "\n MSR read/write utility\n\n";

    uint64 value = 0;
    bool write = false;
    int core = 0;
    int msr = -1;
    bool dec = false;

    int my_opt = -1;
    while ((my_opt = getopt(argc, argv, "w:c:d:a")) != -1)
    {
        switch (my_opt)
        {
        case 'w':
            write = true;
            value = read_number(optarg);
            break;
        case 'c':
            core = (int)read_number(optarg);
            break;
        case 'd':
            dec = true;
            break;
        case 'a':
            core = -1;
            break;
        default:
            print_usage(argv[0]);
            return -1;
        }
    }

    if (optind >= argc)
    {
        print_usage(argv[0]);
        return -1;
    }

    msr = (int)read_number(argv[optind]);

    #ifdef _MSC_VER
    // Increase the priority a bit to improve context switching delays on Windows
    SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);

    // WARNING: This driver code (msr.sys) is only for testing purposes, not for production use
    Driver drv = Driver(Driver::msrLocalPath());
    // drv.stop();     // restart driver (usually not needed)
    if (!drv.start())
    {
        std::wcerr << "Can not load MSR driver." << std::endl;
        std::wcerr << "You must have a signed  driver at " << drv.driverPath() << " and have administrator rights to run this program" << std::endl;
        return -1;
    }
    #endif
    auto doOne = [&dec, &write, &msr](int core, uint64 value)
    {
        try {
            MsrHandle h(core);
            if (!dec) std::cout << std::hex << std::showbase;
            if (write)
            {
                std::cout << " Writing " << value << " to MSR " << msr << " on core " << core << std::endl;
                if (h.write(msr, value) != 8)
                {
                    std::cout << " Write error!" << std::endl;
                }
            }
            value = 0;
            if (h.read(msr, &value) == 8)
            {
                std::cout << " Read value " << value << " from MSR " << msr << " on core " << core << "\n" << std::endl;
            }
            else
            {
                std::cout << " Read error!" << std::endl;
            }
        }
        catch (std::exception & e)
        {
            std::cerr << "Error accessing MSRs: " << e.what() << std::endl;
            std::cerr << "Please check if the program can access MSR drivers." << std::endl;
        }
    };
    if (core >= 0)
    {
        doOne(core, value);
    }
    else
    {
        set_signal_handlers();
        auto m = PCM::getInstance();
        for (uint32 i = 0; i < m->getNumCores(); ++i)
        {
            if (m->isCoreOnline(i))
            {
                doOne(i, value);
            }
        }
    }
}
<commit_msg>Replace endl with \n to get rid of many unnecessary flushes<commit_after>/*
Copyright (c) 2012-2020, Intel Corporation
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 Intel Corporation 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.
*/

// written by Roman Dementiev
#define HACK_TO_REMOVE_DUPLICATE_ERROR
#include "cpucounters.h"
#ifdef _MSC_VER
#include <windows.h>
#include "../PCM_Win/windriver.h"
#else
#include <unistd.h>
#endif
#include <iostream>
#include <stdlib.h>
#include <iomanip>
#include <string.h>
#ifdef _MSC_VER
#include "freegetopt/getopt.h"
#endif

uint64 read_number(char * str)
{
    std::istringstream stream(str);
    if (strstr(str, "x")) stream >> std::hex;
    uint64 result = 0;
    stream >> result;
    return result;
}

void print_usage(const char * progname)
{
    std::cout << "Usage " << progname << " [-w value] [-c core] [-d] msr\n\n";
    std::cout << "  Reads specified msr (model specific register) \n";
    std::cout << "   -w value : write the value before reading \n";
    std::cout << "   -c core  : perform msr read/write on specified core (default is 0)\n";
    std::cout << "   -d       : output all numbers in dec (default is hex)\n";
    std::cout << "   -a       : perform msr read/write operations on all cores\n";
    std::cout << "\n";
}

int main(int argc, char * argv[])
{
    std::cout << "\n Processor Counter Monitor " << PCM_VERSION << "\n";

    std::cout << "\n MSR read/write utility\n\n";

    uint64 value = 0;
    bool write = false;
    int core = 0;
    int msr = -1;
    bool dec = false;

    int my_opt = -1;
    while ((my_opt = getopt(argc, argv, "w:c:d:a")) != -1)
    {
        switch (my_opt)
        {
        case 'w':
            write = true;
            value = read_number(optarg);
            break;
        case 'c':
            core = (int)read_number(optarg);
            break;
        case 'd':
            dec = true;
            break;
        case 'a':
            core = -1;
            break;
        default:
            print_usage(argv[0]);
            return -1;
        }
    }

    if (optind >= argc)
    {
        print_usage(argv[0]);
        return -1;
    }

    msr = (int)read_number(argv[optind]);

    #ifdef _MSC_VER
    // Increase the priority a bit to improve context switching delays on Windows
    SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);

    // WARNING: This driver code (msr.sys) is only for testing purposes, not for production use
    Driver drv = Driver(Driver::msrLocalPath());
    // drv.stop();     // restart driver (usually not needed)
    if (!drv.start())
    {
        std::wcerr << "Can not load MSR driver.\n";
        std::wcerr << "You must have a signed  driver at " << drv.driverPath() << " and have administrator rights to run this program\n";
        return -1;
    }
    #endif
    auto doOne = [&dec, &write, &msr](int core, uint64 value)
    {
        try {
            MsrHandle h(core);
            if (!dec) std::cout << std::hex << std::showbase;
            if (write)
            {
                std::cout << " Writing " << value << " to MSR " << msr << " on core " << core << "\n";
                if (h.write(msr, value) != 8)
                {
                    std::cout << " Write error!\n";
                }
            }
            value = 0;
            if (h.read(msr, &value) == 8)
            {
                std::cout << " Read value " << value << " from MSR " << msr << " on core " << core << "\n\n";
            }
            else
            {
                std::cout << " Read error!\n";
            }
        }
        catch (std::exception & e)
        {
            std::cerr << "Error accessing MSRs: " << e.what() << "\n";
            std::cerr << "Please check if the program can access MSR drivers.\n";
        }
    };
    if (core >= 0)
    {
        doOne(core, value);
    }
    else
    {
        set_signal_handlers();
        auto m = PCM::getInstance();
        for (uint32 i = 0; i < m->getNumCores(); ++i)
        {
            if (m->isCoreOnline(i))
            {
                doOne(i, value);
            }
        }
    }
}
<|endoftext|>


<commit_before>#include "mainwindow.h"
#include "cardreader.h"
#include "shoppinglist.h"

#include <QGridLayout>
#include <QLabel>
#include <QMessageBox>
#include <QPushButton>
#include <QStatusBar>
#include <QTimer>
#include <QApplication>

MainWindow::MainWindow(QWidget *parent)
{
	QVBoxLayout *layout = new QVBoxLayout(this);

	QPushButton *addTestItems = new QPushButton(tr("Add test items"));
	connect(addTestItems, SIGNAL(clicked()), SLOT(addTestItems()));
	layout->addWidget(addTestItems);

	//status message widget
	statusBar = new StatusBar;
	layout->addWidget(statusBar);

	//install cardReader as an filter which intercepts _all_ keyboard events to the application
	cardReader = new CardReader(this);
	connect(cardReader, SIGNAL(newCardNumber(QString)), SLOT(triggerTransaction(QString)));

	//shoppinglist and associated view
	shoppingList = new ShoppingList(this);

	ShoppingListWidget *shoppingListWidget = new ShoppingListWidget(shoppingList);
	layout->addWidget(shoppingListWidget);

	//daemon client
	transactionDaemon = new DaemonClient(this);
	connect(transactionDaemon, SIGNAL(transactionFeedback(QString, float, DaemonClient::TransactionStatus)), SLOT(receiveTransactionFeedback(QString, float, DaemonClient::TransactionStatus)));
}

void MainWindow::addTestItems()
{
	shoppingList->newItem("Brus", 15, 2);
	shoppingList->newItem("Godterisopp", 2, 35);
	shoppingList->newItem("Kvikklunsj", 10, 1);
	shoppingList->newItem("Ragni spesial", 788.5, 3);
}

void MainWindow::triggerTransaction(QString cardNumber)
{
	if (shoppingList->numItems() > 0) {
		this->setEnabled(false);
		double totalPrice = shoppingList->getTotalPrice();
		transactionDaemon->processTransaction(cardNumber, totalPrice);
	}
}

void MainWindow::receiveTransactionFeedback(QString username, float newBalance, DaemonClient::TransactionStatus status)
{
	if (status == DaemonClient::TRANSACTION_SUCCESSFUL) {
		statusBar->showMessage(tr("Transaction processed. New balance: kr ") + QString::number(newBalance), StatusBar::SUCCESS_ICON);
		shoppingList->wipeList();
	} else {
		statusBar->showMessage(DaemonClient::errorMessage(status), StatusBar::ERROR_ICON);
	}
	this->setEnabled(true);
}

StatusBar::StatusBar(QObject *parent)
{
	QHBoxLayout *layout = new QHBoxLayout(this);
	text = new QLabel;
	icon = new QLabel;
	timer = new QTimer(this);

	layout->addWidget(icon);
	layout->addWidget(text, Qt::AlignLeft);

	connect(timer, SIGNAL(timeout()), SLOT(clearMessage()));
}

void StatusBar::showMessage(QString message, StatusIcon icon, int timeout)
{
	timer->stop();

	//status text
	text->setText(message.simplified());

	//status icon
	QSize iconSize = text->size();
	switch (icon) {
		case ERROR_ICON:
			this->icon->setPixmap(qApp->style()->standardIcon(QStyle::SP_MessageBoxCritical).pixmap(iconSize));
			break;
		case SUCCESS_ICON:
			this->icon->setPixmap(qApp->style()->standardIcon(QStyle::SP_DialogApplyButton).pixmap(iconSize));
			break;
	}

	timer->start(timeout);
}

void StatusBar::clearMessage()
{
	text->clear();
	icon->clear();
	timer->stop();
}
<commit_msg>Display username.<commit_after>#include "mainwindow.h"
#include "cardreader.h"
#include "shoppinglist.h"

#include <QGridLayout>
#include <QLabel>
#include <QMessageBox>
#include <QPushButton>
#include <QStatusBar>
#include <QTimer>
#include <QApplication>

MainWindow::MainWindow(QWidget *parent)
{
	QVBoxLayout *layout = new QVBoxLayout(this);

	QPushButton *addTestItems = new QPushButton(tr("Add test items"));
	connect(addTestItems, SIGNAL(clicked()), SLOT(addTestItems()));
	layout->addWidget(addTestItems);

	//status message widget
	statusBar = new StatusBar;
	layout->addWidget(statusBar);

	//install cardReader as an filter which intercepts _all_ keyboard events to the application
	cardReader = new CardReader(this);
	connect(cardReader, SIGNAL(newCardNumber(QString)), SLOT(triggerTransaction(QString)));

	//shoppinglist and associated view
	shoppingList = new ShoppingList(this);

	ShoppingListWidget *shoppingListWidget = new ShoppingListWidget(shoppingList);
	layout->addWidget(shoppingListWidget);

	//daemon client
	transactionDaemon = new DaemonClient(this);
	connect(transactionDaemon, SIGNAL(transactionFeedback(QString, float, DaemonClient::TransactionStatus)), SLOT(receiveTransactionFeedback(QString, float, DaemonClient::TransactionStatus)));
}

void MainWindow::addTestItems()
{
	shoppingList->newItem("Brus", 15, 2);
	shoppingList->newItem("Godterisopp", 2, 35);
	shoppingList->newItem("Kvikklunsj", 10, 1);
	shoppingList->newItem("Ragni spesial", 788.5, 3);
}

void MainWindow::triggerTransaction(QString cardNumber)
{
	if (shoppingList->numItems() > 0) {
		this->setEnabled(false);
		double totalPrice = shoppingList->getTotalPrice();
		transactionDaemon->processTransaction(cardNumber, totalPrice);
	}
}

void MainWindow::receiveTransactionFeedback(QString username, float newBalance, DaemonClient::TransactionStatus status)
{
	if (status == DaemonClient::TRANSACTION_SUCCESSFUL) {
		statusBar->showMessage(tr("Transaction processed. New balance for ") + username + ": kr " + QString::number(newBalance), StatusBar::SUCCESS_ICON);
		shoppingList->wipeList();
	} else {
		statusBar->showMessage(DaemonClient::errorMessage(status), StatusBar::ERROR_ICON);
	}
	this->setEnabled(true);
}

StatusBar::StatusBar(QObject *parent)
{
	QHBoxLayout *layout = new QHBoxLayout(this);
	text = new QLabel;
	icon = new QLabel;
	timer = new QTimer(this);

	layout->addWidget(icon);
	layout->addWidget(text, Qt::AlignLeft);

	connect(timer, SIGNAL(timeout()), SLOT(clearMessage()));
}

void StatusBar::showMessage(QString message, StatusIcon icon, int timeout)
{
	timer->stop();

	//status text
	text->setText(message.simplified());

	//status icon
	QSize iconSize = text->size();
	switch (icon) {
		case ERROR_ICON:
			this->icon->setPixmap(qApp->style()->standardIcon(QStyle::SP_MessageBoxCritical).pixmap(iconSize));
			break;
		case SUCCESS_ICON:
			this->icon->setPixmap(qApp->style()->standardIcon(QStyle::SP_DialogApplyButton).pixmap(iconSize));
			break;
	}

	timer->start(timeout);
}

void StatusBar::clearMessage()
{
	text->clear();
	icon->clear();
	timer->stop();
}
<|endoftext|>


<commit_before>/*
 * WIN32 Events for POSIX
 * Author: Mahmoud Al-Qudsi <mqudsi@neosmart.net>
 * Copyright (C) 2011 - 2012 by NeoSmart Technologies
 * This code is released under the terms of the MIT License
 */

#include "pevents.h"
#include <assert.h>
#include <errno.h>
#include <sys/time.h>
#ifdef WFMO
#include <vector>
#include <deque>
#endif

namespace neosmart
{
#ifdef WFMO
	struct neosmart_wfmo_t_
	{
		pthread_mutex_t Mutex;
		pthread_cond_t CVariable;
		std::vector<bool> EventStatus;
		bool StillWaiting;
		int RefCount;
		bool WaitAll;

		void Destroy()
		{
			pthread_mutex_destroy(&Mutex);
			pthread_cond_destroy(&CVariable);
		}
	};
	typedef neosmart_wfmo_t_ *neosmart_wfmo_t;

	struct neosmart_wfmo_info_t_
	{
		neosmart_wfmo_t Waiter;
		int WaitIndex;
	};
	typedef neosmart_wfmo_info_t_ *neosmart_wfmo_info_t;
#endif

	struct neosmart_event_t_
	{
		bool AutoReset;
		pthread_cond_t CVariable;
		pthread_mutex_t Mutex;
		bool State;
#ifdef WFMO
		std::deque<neosmart_wfmo_info_t_> RegisteredWaits;
#endif
	};

	neosmart_event_t CreateEvent(bool manualReset, bool initialState)
	{
		neosmart_event_t event = new neosmart_event_t_;

		int result = pthread_cond_init(&event->CVariable, 0);
		if(result != 0)
			return NULL;

		result = pthread_mutex_init(&event->Mutex, 0);
		if(result != 0)
			return NULL;

		event->State = false;
		event->AutoReset = !manualReset;

		if(initialState && SetEvent(event) != 0)
			return NULL; //Shouldn't ever happen

		return event;
	}

	int UnlockedWaitForEvent(neosmart_event_t event, uint64_t milliseconds)
	{
		int result = 0;
		if(!event->State)
		{
			//Zero-timeout event state check optimization
			if(milliseconds == 0)
			{
				return ETIMEDOUT;
			}

			timespec ts;
			if(milliseconds != (uint64_t) -1)
			{
				timeval tv;
				gettimeofday(&tv, NULL);

				uint64_t nanoseconds = ((uint64_t) tv.tv_sec) * 1000 * 1000 * 1000 + milliseconds * 1000 * 1000 + ((uint64_t) tv.tv_usec) * 1000;

				ts.tv_sec = nanoseconds / 1000 / 1000 / 1000;
				ts.tv_nsec = (nanoseconds - ((uint64_t) ts.tv_sec) * 1000 * 1000 * 1000);
			}

			do
			{
				//Regardless of whether it's an auto-reset or manual-reset event:
				//wait to obtain the event, then lock anyone else out
				if(milliseconds != (uint64_t) -1)
				{
					result = pthread_cond_timedwait(&event->CVariable, &event->Mutex, &ts);
				}
				else
				{
					result = pthread_cond_wait(&event->CVariable, &event->Mutex);
				}
			} while(result == 0 && !event->State);

			if(result == 0 && event->AutoReset)
			{
				//We've only accquired the event if the wait succeeded
				event->State = false;
			}
		}
		else if(event->AutoReset)
		{
			//It's an auto-reset event that's currently available;
			//we need to stop anyone else from using it
			result = 0;
			event->State = false;
		}
		//Else we're trying to obtain a manual reset event with a signalled state;
		//don't do anything

		return result;
	}

	int WaitForEvent(neosmart_event_t event, uint64_t milliseconds)
	{
		int result = pthread_mutex_lock(&event->Mutex);
		if(result != 0)
			return result;

		result = UnlockedWaitForEvent(event, milliseconds);

		pthread_mutex_unlock(&event->Mutex);

		return result;
	}

#ifdef WFMO
	int WaitForMultipleEvents(neosmart_event_t *events, int count, bool waitAll, uint64_t milliseconds)
	{
		int unused;
		return WaitForMultipleEvents(events, count, waitAll, milliseconds, unused);
	}

	int WaitForMultipleEvents(neosmart_event_t *events, int count, bool waitAll, uint64_t milliseconds, int &waitIndex)
	{
		neosmart_wfmo_t wfmo = new neosmart_wfmo_t_;

		int result = pthread_mutex_init(&wfmo->Mutex, 0);
		if(result != 0)
		{
			delete wfmo;
			return result;
		}

		result = pthread_cond_init(&wfmo->CVariable, 0);
		if(result != 0)
		{
			delete wfmo;
			return result;
		}

		neosmart_wfmo_info_t_ waitInfo;
		waitInfo.Waiter = wfmo;
		waitInfo.WaitIndex = -1;

		wfmo->WaitAll = waitAll;
		wfmo->StillWaiting = true;
		wfmo->RefCount = 1;
		wfmo->EventStatus.resize(count, false);

		pthread_mutex_lock(&wfmo->Mutex);

		bool done = false;
		waitIndex = -1;

		for(int i = 0; i < count; ++i)
		{
			waitInfo.WaitIndex = i;

			//Must not release lock until RegisteredWait is potentially added
			int result = pthread_mutex_lock(&events[i]->Mutex);
			if(result != 0)
			{
				delete wfmo;
				return result;
			}

			if(UnlockedWaitForEvent(events[i], 0) == 0)
			{
				result = pthread_mutex_unlock(&events[i]->Mutex);
				if(result != 0)
				{
					delete wfmo;
					return result;
				}

				wfmo->EventStatus[i] = true;
				if(!waitAll)
				{
					waitIndex = i;
					done = true;
					break;
				}
			}
			else
			{
				events[i]->RegisteredWaits.push_back(waitInfo);
				++wfmo->RefCount;

				pthread_mutex_unlock(&events[i]->Mutex);
			}
		}

		timespec ts;
		if(!done)
		{
			if(milliseconds == 0)
			{
				result = ETIMEDOUT;
				done = true;
			}
			else if(milliseconds != (uint64_t) -1)
			{
				timeval tv;
				gettimeofday(&tv, NULL);

				uint64_t nanoseconds = ((uint64_t) tv.tv_sec) * 1000 * 1000 * 1000 + milliseconds * 1000 * 1000 + ((uint64_t) tv.tv_usec) * 1000;

				ts.tv_sec = nanoseconds / 1000 / 1000 / 1000;
				ts.tv_nsec = (nanoseconds - ((uint64_t) ts.tv_sec) * 1000 * 1000 * 1000);
			}
		}

		while(!done)
		{
			//One (or more) of the events we're monitoring has been triggered?

			//If we're waiting for all events, assume we're done and check if there's an event that hasn't fired
			//But if we're waiting for just one event, assume we're not done until we find a fired event
			done = waitAll;
			for(int i = 0; i < count; ++i)
			{
				if(!waitAll && wfmo->EventStatus[i])
				{
					done = true;
					waitIndex = i;
					break;
				}
				if(waitAll && !wfmo->EventStatus[i])
				{
					done = false;
					break;
				}
			}

			if(!done)
			{
				if(milliseconds != (uint64_t) -1)
				{
					result = pthread_cond_timedwait(&wfmo->CVariable, &wfmo->Mutex, &ts);
				}
				else
				{
					result = pthread_cond_wait(&wfmo->CVariable, &wfmo->Mutex);
				}

				if(result != 0)
					break;
			}
		}

		wfmo->StillWaiting = false;

		--wfmo->RefCount;
		if(wfmo->RefCount == 0)
		{
			wfmo->Destroy();
			delete wfmo;
		}
		else
		{
			pthread_mutex_unlock(&wfmo->Mutex);
		}

		return result;
	}
#endif

	int DestroyEvent(neosmart_event_t event)
	{
		int result = pthread_cond_destroy(&event->CVariable);
		if(result != 0)
			return result;

		result = pthread_mutex_destroy(&event->Mutex);
		if(result != 0)
			return result;

		delete event;

		return 0;
	}

	int SetEvent(neosmart_event_t event)
	{
		int result = pthread_mutex_lock(&event->Mutex);
		if(result != 0)
			return result;

		event->State = true;

		//Depending on the event type, we either trigger everyone or only one
		if(event->AutoReset)
		{
#ifdef WFMO
			while(!event->RegisteredWaits.empty())
			{
				neosmart_wfmo_info_t i = &event->RegisteredWaits.front();
				pthread_mutex_lock(&i->Waiter->Mutex);
				--i->Waiter->RefCount;
				if(!i->Waiter->StillWaiting)
				{
					if(i->Waiter->RefCount == 0)
					{
						i->Waiter->Destroy();
						delete i->Waiter;
					}
					else
					{
						pthread_mutex_unlock(&i->Waiter->Mutex);
					}
					event->RegisteredWaits.pop_front();
					continue;
				}

				event->State = false;
				i->Waiter->EventStatus[i->WaitIndex] = true;
				if(!i->Waiter->WaitAll)
					i->Waiter->StillWaiting = false;
				pthread_mutex_unlock(&i->Waiter->Mutex);
				result = pthread_cond_signal(&i->Waiter->CVariable);
				event->RegisteredWaits.pop_front();
				pthread_mutex_unlock(&event->Mutex);

				return result;
			}
#endif
			//event->State can be false if compiled with WFMO support
			if(event->State)
			{
				pthread_mutex_unlock(&event->Mutex);
				result = pthread_cond_signal(&event->CVariable);

				return result;
			}
		}
		else
		{
#ifdef WFMO
			for(size_t i = 0; i < event->RegisteredWaits.size(); ++i)
			{
				neosmart_wfmo_info_t info = &event->RegisteredWaits[i];
				pthread_mutex_lock(&info->Waiter->Mutex);
				--info->Waiter->RefCount;
				if(!info->Waiter->StillWaiting)
				{
					if(info->Waiter->RefCount == 0)
					{
						info->Waiter->Destroy();
						delete info->Waiter;
					}
					else
					{
						pthread_mutex_unlock(&info->Waiter->Mutex);
					}
					continue;
				}
				info->Waiter->EventStatus[info->WaitIndex] = true;
				pthread_mutex_unlock(&info->Waiter->Mutex);
				pthread_cond_signal(&info->Waiter->CVariable);
			}
			event->RegisteredWaits.clear();
#endif
			pthread_mutex_unlock(&event->Mutex);
			result = pthread_cond_broadcast(&event->CVariable);
		}

		return result;
	}

	int ResetEvent(neosmart_event_t event)
	{
		int result = pthread_mutex_lock(&event->Mutex);
		if(result != 0)
			return result;

		event->State = false;

		pthread_mutex_unlock(&event->Mutex);

		return result;
	}
}
<commit_msg>Better ensure signals for manual reset events aren't lost<commit_after>/*
 * WIN32 Events for POSIX
 * Author: Mahmoud Al-Qudsi <mqudsi@neosmart.net>
 * Copyright (C) 2011 - 2012 by NeoSmart Technologies
 * This code is released under the terms of the MIT License
 */

#include "pevents.h"
#include <assert.h>
#include <errno.h>
#include <sys/time.h>
#ifdef WFMO
#include <vector>
#include <deque>
#endif

namespace neosmart
{
#ifdef WFMO
	struct neosmart_wfmo_t_
	{
		pthread_mutex_t Mutex;
		pthread_cond_t CVariable;
		std::vector<bool> EventStatus;
		bool StillWaiting;
		int RefCount;
		bool WaitAll;

		void Destroy()
		{
			pthread_mutex_destroy(&Mutex);
			pthread_cond_destroy(&CVariable);
		}
	};
	typedef neosmart_wfmo_t_ *neosmart_wfmo_t;

	struct neosmart_wfmo_info_t_
	{
		neosmart_wfmo_t Waiter;
		int WaitIndex;
	};
	typedef neosmart_wfmo_info_t_ *neosmart_wfmo_info_t;
#endif

	struct neosmart_event_t_
	{
		bool AutoReset;
		pthread_cond_t CVariable;
		pthread_mutex_t Mutex;
		bool State;
#ifdef WFMO
		std::deque<neosmart_wfmo_info_t_> RegisteredWaits;
#endif
	};

	neosmart_event_t CreateEvent(bool manualReset, bool initialState)
	{
		neosmart_event_t event = new neosmart_event_t_;

		int result = pthread_cond_init(&event->CVariable, 0);
		if(result != 0)
			return NULL;

		result = pthread_mutex_init(&event->Mutex, 0);
		if(result != 0)
			return NULL;

		event->State = false;
		event->AutoReset = !manualReset;

		if(initialState && SetEvent(event) != 0)
			return NULL; //Shouldn't ever happen

		return event;
	}

	int UnlockedWaitForEvent(neosmart_event_t event, uint64_t milliseconds)
	{
		int result = 0;
		if(!event->State)
		{
			//Zero-timeout event state check optimization
			if(milliseconds == 0)
			{
				return ETIMEDOUT;
			}

			timespec ts;
			if(milliseconds != (uint64_t) -1)
			{
				timeval tv;
				gettimeofday(&tv, NULL);

				uint64_t nanoseconds = ((uint64_t) tv.tv_sec) * 1000 * 1000 * 1000 + milliseconds * 1000 * 1000 + ((uint64_t) tv.tv_usec) * 1000;

				ts.tv_sec = nanoseconds / 1000 / 1000 / 1000;
				ts.tv_nsec = (nanoseconds - ((uint64_t) ts.tv_sec) * 1000 * 1000 * 1000);
			}

			do
			{
				//Regardless of whether it's an auto-reset or manual-reset event:
				//wait to obtain the event, then lock anyone else out
				if(milliseconds != (uint64_t) -1)
				{
					result = pthread_cond_timedwait(&event->CVariable, &event->Mutex, &ts);
				}
				else
				{
					result = pthread_cond_wait(&event->CVariable, &event->Mutex);
				}
			} while(result == 0 && !event->State);

			if(result == 0 && event->AutoReset)
			{
				//We've only accquired the event if the wait succeeded
				event->State = false;
			}
		}
		else if(event->AutoReset)
		{
			//It's an auto-reset event that's currently available;
			//we need to stop anyone else from using it
			result = 0;
			event->State = false;
		}
		//Else we're trying to obtain a manual reset event with a signalled state;
		//don't do anything

		return result;
	}

	int WaitForEvent(neosmart_event_t event, uint64_t milliseconds)
	{
		int result = pthread_mutex_lock(&event->Mutex);
		if(result != 0)
			return result;

		result = UnlockedWaitForEvent(event, milliseconds);

		pthread_mutex_unlock(&event->Mutex);

		return result;
	}

#ifdef WFMO
	int WaitForMultipleEvents(neosmart_event_t *events, int count, bool waitAll, uint64_t milliseconds)
	{
		int unused;
		return WaitForMultipleEvents(events, count, waitAll, milliseconds, unused);
	}

	int WaitForMultipleEvents(neosmart_event_t *events, int count, bool waitAll, uint64_t milliseconds, int &waitIndex)
	{
		neosmart_wfmo_t wfmo = new neosmart_wfmo_t_;

		int result = pthread_mutex_init(&wfmo->Mutex, 0);
		if(result != 0)
		{
			delete wfmo;
			return result;
		}

		result = pthread_cond_init(&wfmo->CVariable, 0);
		if(result != 0)
		{
			delete wfmo;
			return result;
		}

		neosmart_wfmo_info_t_ waitInfo;
		waitInfo.Waiter = wfmo;
		waitInfo.WaitIndex = -1;

		wfmo->WaitAll = waitAll;
		wfmo->StillWaiting = true;
		wfmo->RefCount = 1;
		wfmo->EventStatus.resize(count, false);

		pthread_mutex_lock(&wfmo->Mutex);

		bool done = false;
		waitIndex = -1;

		for(int i = 0; i < count; ++i)
		{
			waitInfo.WaitIndex = i;

			//Must not release lock until RegisteredWait is potentially added
			int result = pthread_mutex_lock(&events[i]->Mutex);
			if(result != 0)
			{
				delete wfmo;
				return result;
			}

			if(UnlockedWaitForEvent(events[i], 0) == 0)
			{
				result = pthread_mutex_unlock(&events[i]->Mutex);
				if(result != 0)
				{
					delete wfmo;
					return result;
				}

				wfmo->EventStatus[i] = true;
				if(!waitAll)
				{
					waitIndex = i;
					done = true;
					break;
				}
			}
			else
			{
				events[i]->RegisteredWaits.push_back(waitInfo);
				++wfmo->RefCount;

				pthread_mutex_unlock(&events[i]->Mutex);
			}
		}

		timespec ts;
		if(!done)
		{
			if(milliseconds == 0)
			{
				result = ETIMEDOUT;
				done = true;
			}
			else if(milliseconds != (uint64_t) -1)
			{
				timeval tv;
				gettimeofday(&tv, NULL);

				uint64_t nanoseconds = ((uint64_t) tv.tv_sec) * 1000 * 1000 * 1000 + milliseconds * 1000 * 1000 + ((uint64_t) tv.tv_usec) * 1000;

				ts.tv_sec = nanoseconds / 1000 / 1000 / 1000;
				ts.tv_nsec = (nanoseconds - ((uint64_t) ts.tv_sec) * 1000 * 1000 * 1000);
			}
		}

		while(!done)
		{
			//One (or more) of the events we're monitoring has been triggered?

			//If we're waiting for all events, assume we're done and check if there's an event that hasn't fired
			//But if we're waiting for just one event, assume we're not done until we find a fired event
			done = waitAll;
			for(int i = 0; i < count; ++i)
			{
				if(!waitAll && wfmo->EventStatus[i])
				{
					done = true;
					waitIndex = i;
					break;
				}
				if(waitAll && !wfmo->EventStatus[i])
				{
					done = false;
					break;
				}
			}

			if(!done)
			{
				if(milliseconds != (uint64_t) -1)
				{
					result = pthread_cond_timedwait(&wfmo->CVariable, &wfmo->Mutex, &ts);
				}
				else
				{
					result = pthread_cond_wait(&wfmo->CVariable, &wfmo->Mutex);
				}

				if(result != 0)
					break;
			}
		}

		wfmo->StillWaiting = false;

		--wfmo->RefCount;
		if(wfmo->RefCount == 0)
		{
			wfmo->Destroy();
			delete wfmo;
		}
		else
		{
			pthread_mutex_unlock(&wfmo->Mutex);
		}

		return result;
	}
#endif

	int DestroyEvent(neosmart_event_t event)
	{
		int result = pthread_cond_destroy(&event->CVariable);
		if(result != 0)
			return result;

		result = pthread_mutex_destroy(&event->Mutex);
		if(result != 0)
			return result;

		delete event;

		return 0;
	}

	int SetEvent(neosmart_event_t event)
	{
		int result = pthread_mutex_lock(&event->Mutex);
		if(result != 0)
			return result;

		event->State = true;

		//Depending on the event type, we either trigger everyone or only one
		if(event->AutoReset)
		{
#ifdef WFMO
			while(!event->RegisteredWaits.empty())
			{
				neosmart_wfmo_info_t i = &event->RegisteredWaits.front();
				pthread_mutex_lock(&i->Waiter->Mutex);
				--i->Waiter->RefCount;
				if(!i->Waiter->StillWaiting)
				{
					if(i->Waiter->RefCount == 0)
					{
						i->Waiter->Destroy();
						delete i->Waiter;
					}
					else
					{
						pthread_mutex_unlock(&i->Waiter->Mutex);
					}
					event->RegisteredWaits.pop_front();
					continue;
				}

				event->State = false;
				i->Waiter->EventStatus[i->WaitIndex] = true;
				if(!i->Waiter->WaitAll)
					i->Waiter->StillWaiting = false;
				pthread_mutex_unlock(&i->Waiter->Mutex);
				result = pthread_cond_signal(&i->Waiter->CVariable);
				event->RegisteredWaits.pop_front();
				pthread_mutex_unlock(&event->Mutex);

				return result;
			}
#endif
			//event->State can be false if compiled with WFMO support
			if(event->State)
			{
				pthread_mutex_unlock(&event->Mutex);
				result = pthread_cond_signal(&event->CVariable);

				return result;
			}
		}
		else
		{
#ifdef WFMO
			for(size_t i = 0; i < event->RegisteredWaits.size(); ++i)
			{
				neosmart_wfmo_info_t info = &event->RegisteredWaits[i];
				pthread_mutex_lock(&info->Waiter->Mutex);
				--info->Waiter->RefCount;
				if(!info->Waiter->StillWaiting)
				{
					if(info->Waiter->RefCount == 0)
					{
						info->Waiter->Destroy();
						delete info->Waiter;
					}
					else
					{
						pthread_mutex_unlock(&info->Waiter->Mutex);
					}
					continue;
				}
				info->Waiter->EventStatus[info->WaitIndex] = true;
				if(!info->Waiter->WaitAll)
					info->Waiter->StillWaiting = false;
				pthread_mutex_unlock(&info->Waiter->Mutex);
				pthread_cond_signal(&info->Waiter->CVariable);
			}
			event->RegisteredWaits.clear();
#endif
			pthread_mutex_unlock(&event->Mutex);
			result = pthread_cond_broadcast(&event->CVariable);
		}

		return result;
	}

	int ResetEvent(neosmart_event_t event)
	{
		int result = pthread_mutex_lock(&event->Mutex);
		if(result != 0)
			return result;

		event->State = false;

		pthread_mutex_unlock(&event->Mutex);

		return result;
	}
}
<|endoftext|>


<commit_before>#include <cstddef>
#include <cstring>
#include <array>
#include <fallbacks/optional.hpp>
#include <algorithm.hpp>
#include <cube.hpp>
using namespace std;
using namespace InsertionFinder;

namespace {
    constexpr int corner_twist_table[24][8] = {
        {0, 3, 6, 9, 12, 15, 18, 21},
        {9, 0, 3, 6, 12, 15, 18, 21},
        {6, 9, 0, 3, 12, 15, 18, 21},
        {3, 6, 9, 0, 12, 15, 18, 21},
        {0, 3, 6, 9, 12, 15, 18, 21},
        {0, 3, 6, 9, 15, 18, 21, 12},
        {0, 3, 6, 9, 18, 21, 12, 15},
        {0, 3, 6, 9, 21, 12, 15, 18},
        {0, 3, 6, 9, 12, 15, 18, 21},
        {0, 3, 11, 22, 12, 15, 7, 20},
        {0, 3, 21, 18, 12, 15, 9, 6},
        {0, 3, 20, 7, 12, 15, 22, 11},
        {0, 3, 6, 9, 12, 15, 18, 21},
        {5, 16, 6, 9, 1, 14, 18, 21},
        {15, 12, 6, 9, 3, 0, 18, 21},
        {14, 1, 6, 9, 16, 5, 18, 21},
        {0, 3, 6, 9, 12, 15, 18, 21},
        {0, 8, 19, 9, 12, 4, 17, 21},
        {0, 18, 15, 9, 12, 6, 3, 21},
        {0, 17, 4, 9, 12, 19, 8, 21},
        {0, 3, 6, 9, 12, 15, 18, 21},
        {13, 3, 6, 2, 23, 15, 18, 10},
        {21, 3, 6, 12, 9, 15, 18, 0},
        {10, 3, 6, 23, 2, 15, 18, 13}
    };

    constexpr int edge_twist_table[24][12] = {
        {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22},
        {6, 0, 2, 4, 8, 10, 12, 14, 16, 18, 20, 22},
        {4, 6, 0, 2, 8, 10, 12, 14, 16, 18, 20, 22},
        {2, 4, 6, 0, 8, 10, 12, 14, 16, 18, 20, 22},
        {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22},
        {0, 2, 4, 6, 10, 12, 14, 8, 16, 18, 20, 22},
        {0, 2, 4, 6, 12, 14, 8, 10, 16, 18, 20, 22},
        {0, 2, 4, 6, 14, 8, 10, 12, 16, 18, 20, 22},
        {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22},
        {0, 2, 4, 22, 8, 10, 12, 20, 16, 18, 6, 14},
        {0, 2, 4, 14, 8, 10, 12, 6, 16, 18, 22, 20},
        {0, 2, 4, 20, 8, 10, 12, 22, 16, 18, 14, 6},
        {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22},
        {0, 18, 4, 6, 8, 16, 12, 14, 2, 10, 20, 22},
        {0, 10, 4, 6, 8, 2, 12, 14, 18, 16, 20, 22},
        {0, 16, 4, 6, 8, 18, 12, 14, 10, 2, 20, 22},
        {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22},
        {0, 2, 21, 6, 8, 10, 19, 14, 16, 5, 13, 22},
        {0, 2, 12, 6, 8, 10, 4, 14, 16, 20, 18, 22},
        {0, 2, 19, 6, 8, 10, 21, 14, 16, 13, 5, 22},
        {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22},
        {17, 2, 4, 6, 23, 10, 12, 14, 9, 18, 20, 1},
        {8, 2, 4, 6, 0, 10, 12, 14, 22, 18, 20, 16},
        {23, 2, 4, 6, 17, 10, 12, 14, 1, 18, 20, 9}
    };
};

const array<Cube, 24> Cube::twist_cube = Cube::generate_twist_cube_table();

array<Cube, 24> Cube::generate_twist_cube_table() noexcept {
    array<Cube, 24> twist_cube;
    for (int i = 0; i < 24; ++i) {
        memcpy(twist_cube[i].corner, corner_twist_table[i], 8 * sizeof(int));
        memcpy(twist_cube[i].edge, edge_twist_table[i], 12 * sizeof(int));
    }
    return twist_cube;
}

void Cube::twist(int twist, byte flags) {
    this->twist(twist_cube[twist], flags);
}

void Cube::twist(const Algorithm& algorithm, byte flags) noexcept {
    this->twist(algorithm, 0, algorithm.length(), flags);
}

void Cube::twist(
    const Algorithm& algorithm,
    size_t begin, size_t end,
    byte flags
) {
    if (static_cast<bool>(flags & CubeTwist::reversed)) {
        this->rotate(Cube::inverse_center[algorithm.cube_rotation()]);
        for (size_t i = end; i-- != begin;) {
            this->twist(
                Algorithm::inverse_twist[algorithm[i]],
                flags
            );
        }
    } else {
        for (size_t i = begin; i < end; ++i) {
            this->twist(algorithm[i], flags);
        }
        this->rotate(algorithm.cube_rotation());
    }
}

void Cube::twist(const Cube& cube, byte flags) noexcept {
    if (static_cast<bool>(flags & CubeTwist::corners)) {
        for (int& item: this->corner) {
            int transform = cube.corner[item / 3];
            item = transform - transform % 3 + (item + transform) % 3;
        }
    }
    if (static_cast<bool>(flags & CubeTwist::edges)) {
        for (int& item: this->edge) {
            item = cube.edge[item >> 1] ^ (item & 1);
        }
    }
    if (static_cast<bool>(flags & CubeTwist::centers)) {
        this->_placement = Cube::center_transform[this->_placement][cube._placement];
    }
}

void Cube::twist_before(int twist, byte flags) {
    this->twist_before(twist_cube[twist], flags);
}

void Cube::twist_before(const Cube& cube, byte flags) noexcept {
    if (static_cast<bool>(flags & CubeTwist::corners)) {
        int corner[8];
        for (int i = 0; i < 8; ++i) {
            int item = cube.corner[i];
            int transform = this->corner[item / 3];
            corner[i] = transform - transform % 3 + (item + transform) % 3;
        }
        memcpy(this->corner, corner, 8 * sizeof(int));
    }
    if (static_cast<bool>(flags & CubeTwist::edges)) {
        int edge[12];
        for (int i = 0; i < 12; ++i) {
            int item = cube.edge[i];
            edge[i] = this->edge[item >> 1] ^ (item & 1);
        }
        memcpy(this->edge, edge, 12 * sizeof(int));
    }
    if (static_cast<bool>(flags & CubeTwist::centers)) {
        this->_placement = Cube::center_transform[cube._placement][this->_placement];
    }
}

optional<Cube> Cube::twist_effectively(
    const Cube& cube, byte flags
) const noexcept {
    Cube result = *this;
    if (static_cast<bool>(flags & CubeTwist::corners)) {
        for (int i = 0; i < 8; ++i) {
            int item = this->corner[i];
            int transform = cube.corner[item / 3];
            int new_corner = transform - transform % 3 + (item + transform) % 3;
            if (new_corner / 3 == i && new_corner % 3 && new_corner != item) {
                return nullopt;
            }
            result.corner[i] = new_corner;
        }
    }
    if (static_cast<bool>(flags & CubeTwist::edges)) {
        for (int i = 0; i < 12; ++i) {
            int item = this->edge[i];
            int new_edge = cube.edge[item >> 1] ^ (item & 1);
            if (new_edge == (i << 1 | 1) && new_edge != item) {
                return nullopt;
            }
            result.edge[i] = new_edge;
        }
    }
    if (static_cast<bool>(flags & CubeTwist::centers)) {
        if (this->_placement == 0) {
            return nullopt;
        }
        result._placement = Cube::center_transform[this->_placement][cube._placement];
    }
    return result;
}

void Cube::rotate(int rotation) {
    if (rotation == 0) {
        return;
    }
    this->twist(Cube::rotation_cube[rotation]);
}
<commit_msg>improve performance with less copies<commit_after>#include <cstddef>
#include <cstring>
#include <array>
#include <fallbacks/optional.hpp>
#include <algorithm.hpp>
#include <cube.hpp>
using namespace std;
using namespace InsertionFinder;

namespace {
    constexpr int corner_twist_table[24][8] = {
        {0, 3, 6, 9, 12, 15, 18, 21},
        {9, 0, 3, 6, 12, 15, 18, 21},
        {6, 9, 0, 3, 12, 15, 18, 21},
        {3, 6, 9, 0, 12, 15, 18, 21},
        {0, 3, 6, 9, 12, 15, 18, 21},
        {0, 3, 6, 9, 15, 18, 21, 12},
        {0, 3, 6, 9, 18, 21, 12, 15},
        {0, 3, 6, 9, 21, 12, 15, 18},
        {0, 3, 6, 9, 12, 15, 18, 21},
        {0, 3, 11, 22, 12, 15, 7, 20},
        {0, 3, 21, 18, 12, 15, 9, 6},
        {0, 3, 20, 7, 12, 15, 22, 11},
        {0, 3, 6, 9, 12, 15, 18, 21},
        {5, 16, 6, 9, 1, 14, 18, 21},
        {15, 12, 6, 9, 3, 0, 18, 21},
        {14, 1, 6, 9, 16, 5, 18, 21},
        {0, 3, 6, 9, 12, 15, 18, 21},
        {0, 8, 19, 9, 12, 4, 17, 21},
        {0, 18, 15, 9, 12, 6, 3, 21},
        {0, 17, 4, 9, 12, 19, 8, 21},
        {0, 3, 6, 9, 12, 15, 18, 21},
        {13, 3, 6, 2, 23, 15, 18, 10},
        {21, 3, 6, 12, 9, 15, 18, 0},
        {10, 3, 6, 23, 2, 15, 18, 13}
    };

    constexpr int edge_twist_table[24][12] = {
        {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22},
        {6, 0, 2, 4, 8, 10, 12, 14, 16, 18, 20, 22},
        {4, 6, 0, 2, 8, 10, 12, 14, 16, 18, 20, 22},
        {2, 4, 6, 0, 8, 10, 12, 14, 16, 18, 20, 22},
        {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22},
        {0, 2, 4, 6, 10, 12, 14, 8, 16, 18, 20, 22},
        {0, 2, 4, 6, 12, 14, 8, 10, 16, 18, 20, 22},
        {0, 2, 4, 6, 14, 8, 10, 12, 16, 18, 20, 22},
        {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22},
        {0, 2, 4, 22, 8, 10, 12, 20, 16, 18, 6, 14},
        {0, 2, 4, 14, 8, 10, 12, 6, 16, 18, 22, 20},
        {0, 2, 4, 20, 8, 10, 12, 22, 16, 18, 14, 6},
        {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22},
        {0, 18, 4, 6, 8, 16, 12, 14, 2, 10, 20, 22},
        {0, 10, 4, 6, 8, 2, 12, 14, 18, 16, 20, 22},
        {0, 16, 4, 6, 8, 18, 12, 14, 10, 2, 20, 22},
        {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22},
        {0, 2, 21, 6, 8, 10, 19, 14, 16, 5, 13, 22},
        {0, 2, 12, 6, 8, 10, 4, 14, 16, 20, 18, 22},
        {0, 2, 19, 6, 8, 10, 21, 14, 16, 13, 5, 22},
        {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22},
        {17, 2, 4, 6, 23, 10, 12, 14, 9, 18, 20, 1},
        {8, 2, 4, 6, 0, 10, 12, 14, 22, 18, 20, 16},
        {23, 2, 4, 6, 17, 10, 12, 14, 1, 18, 20, 9}
    };
};

const array<Cube, 24> Cube::twist_cube = Cube::generate_twist_cube_table();

array<Cube, 24> Cube::generate_twist_cube_table() noexcept {
    array<Cube, 24> twist_cube;
    for (int i = 0; i < 24; ++i) {
        memcpy(twist_cube[i].corner, corner_twist_table[i], 8 * sizeof(int));
        memcpy(twist_cube[i].edge, edge_twist_table[i], 12 * sizeof(int));
    }
    return twist_cube;
}

void Cube::twist(int twist, byte flags) {
    this->twist(twist_cube[twist], flags);
}

void Cube::twist(const Algorithm& algorithm, byte flags) noexcept {
    this->twist(algorithm, 0, algorithm.length(), flags);
}

void Cube::twist(
    const Algorithm& algorithm,
    size_t begin, size_t end,
    byte flags
) {
    if (static_cast<bool>(flags & CubeTwist::reversed)) {
        this->rotate(Cube::inverse_center[algorithm.cube_rotation()]);
        for (size_t i = end; i-- != begin;) {
            this->twist(
                Algorithm::inverse_twist[algorithm[i]],
                flags
            );
        }
    } else {
        for (size_t i = begin; i < end; ++i) {
            this->twist(algorithm[i], flags);
        }
        this->rotate(algorithm.cube_rotation());
    }
}

void Cube::twist(const Cube& cube, byte flags) noexcept {
    if (static_cast<bool>(flags & CubeTwist::corners)) {
        for (int& item: this->corner) {
            int transform = cube.corner[item / 3];
            item = transform - transform % 3 + (item + transform) % 3;
        }
    }
    if (static_cast<bool>(flags & CubeTwist::edges)) {
        for (int& item: this->edge) {
            item = cube.edge[item >> 1] ^ (item & 1);
        }
    }
    if (static_cast<bool>(flags & CubeTwist::centers)) {
        this->_placement = Cube::center_transform[this->_placement][cube._placement];
    }
}

void Cube::twist_before(int twist, byte flags) {
    this->twist_before(twist_cube[twist], flags);
}

void Cube::twist_before(const Cube& cube, byte flags) noexcept {
    if (static_cast<bool>(flags & CubeTwist::corners)) {
        int corner[8];
        for (int i = 0; i < 8; ++i) {
            int item = cube.corner[i];
            int transform = this->corner[item / 3];
            corner[i] = transform - transform % 3 + (item + transform) % 3;
        }
        memcpy(this->corner, corner, 8 * sizeof(int));
    }
    if (static_cast<bool>(flags & CubeTwist::edges)) {
        int edge[12];
        for (int i = 0; i < 12; ++i) {
            int item = cube.edge[i];
            edge[i] = this->edge[item >> 1] ^ (item & 1);
        }
        memcpy(this->edge, edge, 12 * sizeof(int));
    }
    if (static_cast<bool>(flags & CubeTwist::centers)) {
        this->_placement = Cube::center_transform[cube._placement][this->_placement];
    }
}

optional<Cube> Cube::twist_effectively(
    const Cube& cube, byte flags
) const noexcept {
    bool corners_filled = false;
    bool edges_filled = false;
    bool centers_filled = false;
    Cube result(nullopt);
    if (static_cast<bool>(flags & CubeTwist::corners)) {
        for (int i = 0; i < 8; ++i) {
            int item = this->corner[i];
            int transform = cube.corner[item / 3];
            int new_corner = transform - transform % 3 + (item + transform) % 3;
            if (new_corner / 3 == i && new_corner % 3 && new_corner != item) {
                return nullopt;
            }
            result.corner[i] = new_corner;
        }
        corners_filled = true;
    }
    if (static_cast<bool>(flags & CubeTwist::edges)) {
        for (int i = 0; i < 12; ++i) {
            int item = this->edge[i];
            int new_edge = cube.edge[item >> 1] ^ (item & 1);
            if (new_edge == (i << 1 | 1) && new_edge != item) {
                return nullopt;
            }
            result.edge[i] = new_edge;
        }
        edges_filled = true;
    }
    if (static_cast<bool>(flags & CubeTwist::centers)) {
        if (this->_placement == 0) {
            return nullopt;
        }
        result._placement = Cube::center_transform[this->_placement][cube._placement];
        centers_filled = true;
    }
    if (!corners_filled) {
        memcpy(result.corner, this->corner, 8 * sizeof(int));
    }
    if (!edges_filled) {
        memcpy(result.edge, this->edge, 12 * sizeof(int));
    }
    if (!centers_filled) {
        result._placement = this->_placement;
    }
    return result;
}

void Cube::rotate(int rotation) {
    if (rotation == 0) {
        return;
    }
    this->twist(Cube::rotation_cube[rotation]);
}
<|endoftext|>


<commit_before>#include "RemovableDriveManager.hpp"
#include <iostream>
#include "boost/nowide/convert.hpp"

#if _WIN32
#include <windows.h>
#include <tchar.h>
#include <winioctl.h>
#include <shlwapi.h>
DEFINE_GUID(GUID_DEVINTERFACE_USB_DEVICE,
	0xA5DCBF10L, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED);
#else
//linux includes
#include <errno.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <glob.h>
#include <libgen.h>
#include <pwd.h>
#endif

namespace Slic3r {
namespace GUI {
//std::vector<DriveData>  RemovableDriveManager::m_current_drives;
//std::vector<std::function<void()>>  RemovableDriveManager::m_callbacks;

#if _WIN32
void RemovableDriveManager::search_for_drives()
{
	m_current_drives.clear();
	m_current_drives.reserve(26);
	DWORD drives_mask = GetLogicalDrives();
	for (size_t i = 0; i < 26; i++)
	{
		if(drives_mask & (1 << i))
		{
			std::string path (1,(char)('A' + i));
			path+=":";
			UINT drive_type = GetDriveTypeA(path.c_str());
			//std::cout << "found drive" << (char)('A' + i) << ": type:" <<driveType << "\n";
			if (drive_type ==  DRIVE_REMOVABLE)
			{
				// get name of drive
				std::wstring wpath = std::wstring(path.begin(), path.end());
				std::wstring volume_name;
				volume_name.resize(1024);
				std::wstring file_system_name;
				file_system_name.resize(1024);
				LPWSTR  lp_volume_name_buffer = new wchar_t;
				BOOL error = GetVolumeInformationW(wpath.c_str(), &volume_name[0], sizeof(volume_name), NULL, NULL, NULL, &file_system_name[0], sizeof(file_system_name));
				if(error != 0)
				{
					if (volume_name == L"")
					{
						volume_name = L"REMOVABLE DRIVE";
					}
					if (file_system_name != L"")
					{
						ULARGE_INTEGER free_space;
						GetDiskFreeSpaceExA(path.c_str(), &free_space, NULL, NULL);
						//std::cout << std::string(volumeName.begin(), volumeName.end()) << " " << std::string(fileSystemName.begin(), fileSystemName.end()) << " " << freeSpace.QuadPart << "\n";
						if (free_space.QuadPart > 0)
						{
							path += "\\";
							m_current_drives.push_back(DriveData(boost::nowide::narrow(volume_name), path));
						}
					}
				}
			}
		}
	}
	//std::cout << "found drives:" << m_current_drives.size() << "\n";
}
void RemovableDriveManager::eject_drive(const std::string &path)
{

	//if (!update() || !is_drive_mounted(path))
	if(m_current_drives.empty())
		return;
	for (auto it = m_current_drives.begin(); it != m_current_drives.end(); ++it)
	{
		if ((*it).path == path)
		{
			std::string mpath = "\\\\.\\" + path;
			mpath = mpath.substr(0, mpath.size() - 1);
			std::cout << "Ejecting " << mpath << "\n";
			HANDLE handle = CreateFileA(mpath.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
			if (handle == INVALID_HANDLE_VALUE)
			{
				std::cerr << "Ejecting " << mpath << " failed " << GetLastError() << " \n";
				return;
			}
			DWORD deviceControlRetVal(0);
			BOOL error = DeviceIoControl(handle, IOCTL_STORAGE_EJECT_MEDIA, nullptr, 0, nullptr, 0, &deviceControlRetVal, nullptr);
			CloseHandle(handle);
			if (error == 0)
			{
				std::cerr << "Ejecting " << mpath << " failed " << deviceControlRetVal << " " << GetLastError() << " \n";
				return;
			}

			m_current_drives.erase(it);
			break;
		}
	}
}
bool RemovableDriveManager::is_path_on_removable_drive(const std::string &path)
{
	if (m_current_drives.empty())
		return false;
	int letter = PathGetDriveNumberA(path.c_str());
	for (auto it = m_current_drives.begin(); it != m_current_drives.end(); ++it)
	{
		char drive = (*it).path[0];
		if (drive == ('A' + letter))
			return true;
	}
	return false;
}
void RemovableDriveManager::register_window()
{
	/*
	WNDCLASSEX wndClass;

	wndClass.cbSize = sizeof(WNDCLASSEX);
	wndClass.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
	wndClass.hInstance = reinterpret_cast<HINSTANCE>(GetModuleHandle(0));
	wndClass.lpfnWndProc = reinterpret_cast<WNDPROC>(WinProcCallback);
	wndClass.cbClsExtra = 0;
	wndClass.cbWndExtra = 0;
	wndClass.hIcon = LoadIcon(0, IDI_APPLICATION);
	wndClass.hbrBackground = CreateSolidBrush(RGB(192, 192, 192));
	wndClass.hCursor = LoadCursor(0, IDC_ARROW);
	wndClass.lpszClassName = L"SlicerWindowClass";
	wndClass.lpszMenuName = NULL;
	wndClass.hIconSm = wndClass.hIcon;
	*/
}
#else
void RemovableDriveManager::search_for_drives()
{

	m_current_drives.clear();
	m_current_drives.reserve(26);

    //search /media/* folder
	search_path("/media/*", "/media");

    std::string path(std::getenv("USER"));
	std::string pp(path);
	//std::cout << "user: "<< path << "\n";
	if(path == "root"){ //if program is run with sudo, we have to search for all users
		while (true) {
	        passwd* entry = getpwent();
	        if (!entry) {
	            break;
	        }
	        path = entry->pw_name;
	        pp = path;
	        //search /media/USERNAME/* folder
			pp = "/media/"+pp;
			path = "/media/" + path + "/*";
			search_path(path, pp);

			//search /run/media/USERNAME/* folder
			path = "/run" + path;
			pp = "/run"+pp;
			search_path(path, pp);
	    }
	    endpwent();
	}else
	{
		//search /media/USERNAME/* folder
		pp = "/media/"+pp;
		path = "/media/" + path + "/*";
		search_path(path, pp);

		//search /run/media/USERNAME/* folder
		path = "/run" + path;
		pp = "/run"+pp;
		search_path(path, pp);

	}

	//std::cout << "found drives:" <<m_current_drives.size() << "\n";
}
void RemovableDriveManager::search_path(const std::string &path,const std::string &parent_path)
{
    glob_t globbuf;
	globbuf.gl_offs = 2;
	int error = glob(path.c_str(), GLOB_TILDE, NULL, &globbuf);
	if(error == 0)
	{
		for(size_t i = 0; i < globbuf.gl_pathc; i++)
		{
			//if not same file system - could be removable drive
			if(!compare_filesystem_id(globbuf.gl_pathv[i], parent_path))
			{
				std::string name = basename(globbuf.gl_pathv[i]);
	            m_current_drives.push_back(DriveData(name,globbuf.gl_pathv[i]));
			}
		}
	}else
	{
		//if error - path probably doesnt exists so function just exits
		//std::cout<<"glob error "<< error<< "\n";
	}

	globfree(&globbuf);
}

bool RemovableDriveManager::compare_filesystem_id(const std::string &path_a, const std::string &path_b)
{
	struct stat buf;
	stat(path_a.c_str() ,&buf);
	dev_t id_a = buf.st_dev;
	stat(path_b.c_str() ,&buf);
	dev_t id_b = buf.st_dev;
	return id_a == id_b;
}
void RemovableDriveManager::eject_drive(const std::string &path)
{
	if (m_current_drives.empty())
		return;

	for (auto it = m_current_drives.begin(); it != m_current_drives.end(); ++it)
	{
		if((*it).path == path)
		{
            std::cout<<"Ejecting "<<(*it).name<<" from "<< (*it).path<<"\n";
            std::string command = "umount ";
            command += (*it).path;
            int err = system(command.c_str());
            if(err)
            {
                std::cerr<<"Ejecting failed\n";
                return;
            }
            m_current_drives.erase(it);

            break;
		}

	}

}
bool RemovableDriveManager::is_path_on_removable_drive(const std::string &path)
{
	if (m_current_drives.empty())
		return false;
	for (auto it = m_current_drives.begin(); it != m_current_drives.end(); ++it)
	{
		if(compare_filesystem_id(path, (*it).path))
			return true;
	}
	return false;
}
#endif
bool RemovableDriveManager::update(long time)
{
	static long last_update = 0;
	if(last_update == 0)
	{
		//add_callback(std::bind(&RemovableDriveManager::print, RemovableDriveManager::getInstance()));
		add_callback([](void) { RemovableDriveManager::get_instance().print(); });
#if _WIN32
		register_window();
#endif
	}
	if(time != 0) //time = 0 is forced update
	{
		long diff = last_update - time;
		if(diff <= -2)
		{
			last_update = time;
		}else
		{
			return false; // return value shouldnt matter if update didnt run
		}
	}
	search_for_drives();
	check_and_notify();
	return !m_current_drives.empty();
}

bool  RemovableDriveManager::is_drive_mounted(const std::string &path)
{
	for (auto it = m_current_drives.begin(); it != m_current_drives.end(); ++it)
	{
		if ((*it).path == path)
		{
			return true;
		}
	}
	return false;
}

std::string RemovableDriveManager::get_last_drive_path()
{
	if (!m_current_drives.empty())
	{
//#if _WIN32
//		return m_current_drives.back().path + "\\";
//#else
		return m_current_drives.back().path;
//#endif
	}
	return "";
}
std::vector<DriveData> RemovableDriveManager::get_all_drives()
{
	return m_current_drives;
}
void RemovableDriveManager::check_and_notify()
{
	//std::cout<<"drives count: "<<m_drives_count;
	if(m_drives_count != m_current_drives.size())
	{
		//std::cout<<" vs "<< m_current_drives.size();
		for (auto it = m_callbacks.begin(); it != m_callbacks.end(); ++it)
		{
			(*it)();
		}
		m_drives_count = m_current_drives.size();
	}
	//std::cout<<"\n";
}
void RemovableDriveManager::add_callback(std::function<void()> callback)
{
	m_callbacks.push_back(callback);
}
void RemovableDriveManager::print()
{
	std::cout << "notified\n";
}
}}//namespace Slicer::Gui::<commit_msg>osx search for drives<commit_after>#include "RemovableDriveManager.hpp"
#include <iostream>
#include "boost/nowide/convert.hpp"

#if _WIN32
#include <windows.h>
#include <tchar.h>
#include <winioctl.h>
#include <shlwapi.h>
DEFINE_GUID(GUID_DEVINTERFACE_USB_DEVICE,
	0xA5DCBF10L, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED);
#else
//linux includes
#include <errno.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <glob.h>
#include <libgen.h>
#include <pwd.h>
#endif

namespace Slic3r {
namespace GUI {
//std::vector<DriveData>  RemovableDriveManager::m_current_drives;
//std::vector<std::function<void()>>  RemovableDriveManager::m_callbacks;

#if _WIN32
void RemovableDriveManager::search_for_drives()
{
	m_current_drives.clear();
	m_current_drives.reserve(26);
	DWORD drives_mask = GetLogicalDrives();
	for (size_t i = 0; i < 26; i++)
	{
		if(drives_mask & (1 << i))
		{
			std::string path (1,(char)('A' + i));
			path+=":";
			UINT drive_type = GetDriveTypeA(path.c_str());
			//std::cout << "found drive" << (char)('A' + i) << ": type:" <<driveType << "\n";
			if (drive_type ==  DRIVE_REMOVABLE)
			{
				// get name of drive
				std::wstring wpath = std::wstring(path.begin(), path.end());
				std::wstring volume_name;
				volume_name.resize(1024);
				std::wstring file_system_name;
				file_system_name.resize(1024);
				LPWSTR  lp_volume_name_buffer = new wchar_t;
				BOOL error = GetVolumeInformationW(wpath.c_str(), &volume_name[0], sizeof(volume_name), NULL, NULL, NULL, &file_system_name[0], sizeof(file_system_name));
				if(error != 0)
				{
					if (volume_name == L"")
					{
						volume_name = L"REMOVABLE DRIVE";
					}
					if (file_system_name != L"")
					{
						ULARGE_INTEGER free_space;
						GetDiskFreeSpaceExA(path.c_str(), &free_space, NULL, NULL);
						//std::cout << std::string(volumeName.begin(), volumeName.end()) << " " << std::string(fileSystemName.begin(), fileSystemName.end()) << " " << freeSpace.QuadPart << "\n";
						if (free_space.QuadPart > 0)
						{
							path += "\\";
							m_current_drives.push_back(DriveData(boost::nowide::narrow(volume_name), path));
						}
					}
				}
			}
		}
	}
	//std::cout << "found drives:" << m_current_drives.size() << "\n";
}
void RemovableDriveManager::eject_drive(const std::string &path)
{

	//if (!update() || !is_drive_mounted(path))
	if(m_current_drives.empty())
		return;
	for (auto it = m_current_drives.begin(); it != m_current_drives.end(); ++it)
	{
		if ((*it).path == path)
		{
			std::string mpath = "\\\\.\\" + path;
			mpath = mpath.substr(0, mpath.size() - 1);
			std::cout << "Ejecting " << mpath << "\n";
			HANDLE handle = CreateFileA(mpath.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
			if (handle == INVALID_HANDLE_VALUE)
			{
				std::cerr << "Ejecting " << mpath << " failed " << GetLastError() << " \n";
				return;
			}
			DWORD deviceControlRetVal(0);
			BOOL error = DeviceIoControl(handle, IOCTL_STORAGE_EJECT_MEDIA, nullptr, 0, nullptr, 0, &deviceControlRetVal, nullptr);
			CloseHandle(handle);
			if (error == 0)
			{
				std::cerr << "Ejecting " << mpath << " failed " << deviceControlRetVal << " " << GetLastError() << " \n";
				return;
			}

			m_current_drives.erase(it);
			break;
		}
	}
}
bool RemovableDriveManager::is_path_on_removable_drive(const std::string &path)
{
	if (m_current_drives.empty())
		return false;
	int letter = PathGetDriveNumberA(path.c_str());
	for (auto it = m_current_drives.begin(); it != m_current_drives.end(); ++it)
	{
		char drive = (*it).path[0];
		if (drive == ('A' + letter))
			return true;
	}
	return false;
}
void RemovableDriveManager::register_window()
{
	/*
	WNDCLASSEX wndClass;

	wndClass.cbSize = sizeof(WNDCLASSEX);
	wndClass.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
	wndClass.hInstance = reinterpret_cast<HINSTANCE>(GetModuleHandle(0));
	wndClass.lpfnWndProc = reinterpret_cast<WNDPROC>(WinProcCallback);
	wndClass.cbClsExtra = 0;
	wndClass.cbWndExtra = 0;
	wndClass.hIcon = LoadIcon(0, IDI_APPLICATION);
	wndClass.hbrBackground = CreateSolidBrush(RGB(192, 192, 192));
	wndClass.hCursor = LoadCursor(0, IDC_ARROW);
	wndClass.lpszClassName = L"SlicerWindowClass";
	wndClass.lpszMenuName = NULL;
	wndClass.hIconSm = wndClass.hIcon;
	*/
}
#else
void RemovableDriveManager::search_for_drives()
{

	m_current_drives.clear();
	m_current_drives.reserve(26);

    //search /media/* folder
	search_path("/media/*", "/media");

	//search /Volumes/* folder (OSX)
	search_path("/Volumes/*", "/Volumes");

    std::string path(std::getenv("USER"));
	std::string pp(path);
	//std::cout << "user: "<< path << "\n";
	if(path == "root"){ //if program is run with sudo, we have to search for all users
		while (true) {
	        passwd* entry = getpwent();
	        if (!entry) {
	            break;
	        }
	        path = entry->pw_name;
	        pp = path;
	        //search /media/USERNAME/* folder
			pp = "/media/"+pp;
			path = "/media/" + path + "/*";
			search_path(path, pp);

			//search /run/media/USERNAME/* folder
			path = "/run" + path;
			pp = "/run"+pp;
			search_path(path, pp);
	    }
	    endpwent();
	}else
	{
		//search /media/USERNAME/* folder
		pp = "/media/"+pp;
		path = "/media/" + path + "/*";
		search_path(path, pp);

		//search /run/media/USERNAME/* folder
		path = "/run" + path;
		pp = "/run"+pp;
		search_path(path, pp);

	}

	//std::cout << "found drives:" <<m_current_drives.size() << "\n";
}
void RemovableDriveManager::search_path(const std::string &path,const std::string &parent_path)
{
    glob_t globbuf;
	globbuf.gl_offs = 2;
	int error = glob(path.c_str(), GLOB_TILDE, NULL, &globbuf);
	if(error == 0)
	{
		for(size_t i = 0; i < globbuf.gl_pathc; i++)
		{
			//if not same file system - could be removable drive
			if(!compare_filesystem_id(globbuf.gl_pathv[i], parent_path))
			{
				std::string name = basename(globbuf.gl_pathv[i]);
	            m_current_drives.push_back(DriveData(name,globbuf.gl_pathv[i]));
			}
		}
	}else
	{
		//if error - path probably doesnt exists so function just exits
		//std::cout<<"glob error "<< error<< "\n";
	}

	globfree(&globbuf);
}

bool RemovableDriveManager::compare_filesystem_id(const std::string &path_a, const std::string &path_b)
{
	struct stat buf;
	stat(path_a.c_str() ,&buf);
	dev_t id_a = buf.st_dev;
	stat(path_b.c_str() ,&buf);
	dev_t id_b = buf.st_dev;
	return id_a == id_b;
}
void RemovableDriveManager::eject_drive(const std::string &path)
{
	if (m_current_drives.empty())
		return;

	for (auto it = m_current_drives.begin(); it != m_current_drives.end(); ++it)
	{
		if((*it).path == path)
		{
            std::cout<<"Ejecting "<<(*it).name<<" from "<< (*it).path<<"\n";
            std::string command = "umount ";
            command += (*it).path;
            int err = system(command.c_str());
            if(err)
            {
                std::cerr<<"Ejecting failed\n";
                return;
            }
            m_current_drives.erase(it);

            break;
		}

	}

}
bool RemovableDriveManager::is_path_on_removable_drive(const std::string &path)
{
	if (m_current_drives.empty())
		return false;
	for (auto it = m_current_drives.begin(); it != m_current_drives.end(); ++it)
	{
		if(compare_filesystem_id(path, (*it).path))
			return true;
	}
	return false;
}
#endif
bool RemovableDriveManager::update(long time)
{
	static long last_update = 0;
	if(last_update == 0)
	{
		//add_callback(std::bind(&RemovableDriveManager::print, RemovableDriveManager::getInstance()));
		add_callback([](void) { RemovableDriveManager::get_instance().print(); });
#if _WIN32
		register_window();
#endif
	}
	if(time != 0) //time = 0 is forced update
	{
		long diff = last_update - time;
		if(diff <= -2)
		{
			last_update = time;
		}else
		{
			return false; // return value shouldnt matter if update didnt run
		}
	}
	search_for_drives();
	check_and_notify();
	return !m_current_drives.empty();
}

bool  RemovableDriveManager::is_drive_mounted(const std::string &path)
{
	for (auto it = m_current_drives.begin(); it != m_current_drives.end(); ++it)
	{
		if ((*it).path == path)
		{
			return true;
		}
	}
	return false;
}

std::string RemovableDriveManager::get_last_drive_path()
{
	if (!m_current_drives.empty())
	{
//#if _WIN32
//		return m_current_drives.back().path + "\\";
//#else
		return m_current_drives.back().path;
//#endif
	}
	return "";
}
std::vector<DriveData> RemovableDriveManager::get_all_drives()
{
	return m_current_drives;
}
void RemovableDriveManager::check_and_notify()
{
	//std::cout<<"drives count: "<<m_drives_count;
	if(m_drives_count != m_current_drives.size())
	{
		//std::cout<<" vs "<< m_current_drives.size();
		for (auto it = m_callbacks.begin(); it != m_callbacks.end(); ++it)
		{
			(*it)();
		}
		m_drives_count = m_current_drives.size();
	}
	//std::cout<<"\n";
}
void RemovableDriveManager::add_callback(std::function<void()> callback)
{
	m_callbacks.push_back(callback);
}
void RemovableDriveManager::print()
{
	std::cout << "notified\n";
}
}}//namespace Slicer::Gui::<|endoftext|>


<commit_before>// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1, as published by the Free Software
 * Foundation.  See file COPYING.
 *
 */

#include "Elector.h"
#include "Monitor.h"

#include "common/Timer.h"
#include "MonitorStore.h"
#include "messages/MMonElection.h"

#include "config.h"

#define DOUT_SUBSYS mon
#undef dout_prefix
#define dout_prefix _prefix(mon, epoch)
static ostream& _prefix(Monitor *mon, epoch_t epoch) {
  return *_dout << dbeginl
		<< "mon" << mon->whoami
		<< (mon->is_starting() ? (const char*)"(starting)":(mon->is_leader() ? (const char*)"(leader)":(mon->is_peon() ? (const char*)"(peon)":(const char*)"(?\?)")))
		<< ".elector(" << epoch << ") ";
}

void Elector::init()
{
  epoch = mon->store->get_int("election_epoch");
  if (!epoch)
    epoch = 1;
  dout(1) << "init, last seen epoch " << epoch << dendl;
}

void Elector::shutdown()
{
  if (expire_event)
    mon->timer.cancel_event(expire_event);
}

void Elector::bump_epoch(epoch_t e)
{
  dout(10) << "bump_epoch " << epoch << " to " << e << dendl;
  assert(epoch < e);
  epoch = e;
  mon->store->put_int(epoch, "election_epoch");

  // clear up some state
  electing_me = false;
  acked_me.clear();
  leader_acked = -1;
}

void Elector::start()
{
  dout(5) << "start -- can i be leader?" << dendl;

  // start by trying to elect me
  if (epoch % 2 == 0)
    bump_epoch(epoch+1);  // odd == election cycle
  start_stamp = g_clock.now();
  electing_me = true;
  acked_me.insert(whoami);

  // bcast to everyone else
  for (unsigned i=0; i<mon->monmap->size(); ++i) {
    if ((int)i == whoami) continue;
    mon->messenger->send_message(new MMonElection(MMonElection::OP_PROPOSE, epoch, mon->monmap),
				 mon->monmap->get_inst(i));
  }

  reset_timer();
}

void Elector::defer(int who)
{
  dout(5) << "defer to " << who << dendl;

  if (electing_me) {
    // drop out
    acked_me.clear();
    electing_me = false;
  }

  // ack them
  leader_acked = who;
  ack_stamp = g_clock.now();
  mon->messenger->send_message(new MMonElection(MMonElection::OP_ACK, epoch, mon->monmap),
			       mon->monmap->get_inst(who));

  // set a timer
  reset_timer(1.0);  // give the leader some extra time to declare victory
}

void Elector::reset_timer(double plus)
{
  // set the timer
  cancel_timer();
  expire_event = new C_ElectionExpire(this);
  mon->timer.add_event_after(g_conf.mon_lease + plus,
			     expire_event);
}

void Elector::cancel_timer()
{
  if (expire_event) {
    mon->timer.cancel_event(expire_event);
    expire_event = 0;
  }
}

void Elector::expire()
{
  dout(5) << "election timer expired" << dendl;

  // did i win?
  if (electing_me &&
      acked_me.size() > (unsigned)(mon->monmap->size() / 2)) {
    // i win
    victory();
  } else {
    // whoever i deferred to didn't declare victory quickly enough.
    start();
  }
}

void Elector::victory()
{
  leader_acked = -1;
  electing_me = false;
  set<int> quorum = acked_me;

  cancel_timer();

  assert(epoch % 2 == 1);  // election
  bump_epoch(epoch+1);     // is over!

  // tell everyone
  for (set<int>::iterator p = quorum.begin();
       p != quorum.end();
       ++p) {
    if (*p == whoami) continue;
    MMonElection *m = new MMonElection(MMonElection::OP_VICTORY, epoch, mon->monmap);
    m->quorum = quorum;
    mon->messenger->send_message(m, mon->monmap->get_inst(*p));
  }

  // tell monitor
  mon->win_election(epoch, quorum);
}

void Elector::handle_propose(MMonElection *m)
{
  dout(5) << "handle_propose from " << m->get_source() << dendl;
  int from = m->get_source().num();

  assert(m->epoch % 2 == 1); // election
  if (m->epoch > epoch) {
    bump_epoch(m->epoch);
  }
  else if (m->epoch < epoch) {
    // got an "old" propose,
    if (epoch % 2 == 0 &&    // in a non-election cycle
	mon->quorum.count(from) == 0) {  // from someone outside the quorum
      // a mon just started up, call a new election so they can rejoin!
      dout(5) << " got propose from old epoch, quorum is " << mon->quorum
	      << ", " << m->get_source() << " must have just started" << dendl;
      mon->call_election(false);//start();
    } else {
      dout(5) << " ignoring old propose" << dendl;
      delete m;
      return;
    }
  }

  if (whoami < from) {
    // i would win over them.
    if (leader_acked >= 0) {        // we already acked someone
      assert(leader_acked < from);  // and they still win, of course
      dout(5) << "no, we already acked " << leader_acked << dendl;
    } else {
      // wait, i should win!
      if (!electing_me)
	mon->call_election(false);//start();
    }
  } else {
    // they would win over me
    if (leader_acked < 0 ||      // haven't acked anyone yet, or
	leader_acked > from ||   // they would win over who you did ack, or
	leader_acked == from) {  // this is the guy we're already deferring to
      defer(from);
    } else {
      // ignore them!
      dout(5) << "no, we already acked " << leader_acked << dendl;
    }
  }

  delete m;
}

void Elector::handle_ack(MMonElection *m)
{
  dout(5) << "handle_ack from " << m->get_source() << dendl;
  int from = m->get_source().num();

  assert(m->epoch % 2 == 1); // election
  if (m->epoch > epoch) {
    dout(5) << "woah, that's a newer epoch, i must have rebooted.  bumping and re-starting!" << dendl;
    bump_epoch(m->epoch);
    mon->call_election(false);//start();
    delete m;
    return;
  }
  assert(m->epoch == epoch);

  if (electing_me) {
    // thanks
    acked_me.insert(from);
    dout(5) << " so far i have " << acked_me << dendl;

    // is that _everyone_?
    if (acked_me.size() == mon->monmap->size()) {
      // if yes, shortcut to election finish
      victory();
    }
  } else {
    // ignore, i'm deferring already.
    assert(leader_acked >= 0);
  }

  delete m;
}

void Elector::handle_victory(MMonElection *m)
{
  dout(5) << "handle_victory from " << m->get_source() << dendl;
  int from = m->get_source().num();

  assert(from < whoami);
  assert(m->epoch % 2 == 0);

  // i should have seen this election if i'm getting the victory.
  if (m->epoch != epoch + 1) {
    dout(5) << "woah, that's a funny epoch, i must have rebooted.  bumping and re-starting!" << dendl;
    bump_epoch(m->epoch);
    mon->call_election(true);//start();
    delete m;
    return;
  }

  bump_epoch(m->epoch);

  // they win
  mon->lose_election(epoch, m->quorum, from);

  // cancel my timer
  cancel_timer();
  delete m;
}

void Elector::dispatch(Message *m)
{
  switch (m->get_type()) {

  case MSG_MON_ELECTION:
    {
      MMonElection *em = (MMonElection*)m;

      MonMap *peermap = new MonMap;
      peermap->decode(em->monmap_bl);
      if (peermap->epoch > mon->monmap->epoch) {
	dout(0) << m->get_source_inst() << " has newer monmap epoch " << peermap->epoch
		<< " > my epoch " << mon->monmap->epoch
		<< ", taking it"
		<< dendl;
	delete mon->monmap;
	mon->monmap = peermap;
	mon->store->put_bl_sn(em->monmap_bl, "monmap", peermap->epoch);
	mon->store->put_bl_ss(em->monmap_bl, "monmap", "latest");
      } else {
	if (peermap->epoch < mon->monmap->epoch) {
	  dout(0) << m->get_source_inst() << " has older monmap epoch " << peermap->epoch
		  << " < my epoch " << mon->monmap->epoch
		  << dendl;
	}
	delete peermap;
      }

      switch (em->op) {
      case MMonElection::OP_PROPOSE:
	handle_propose(em);
	return;
      }

      if (em->epoch < epoch) {
	dout(5) << "old epoch, dropping" << dendl;
	delete em;
	break;
      }

      switch (em->op) {
      case MMonElection::OP_ACK:
	handle_ack(em);
	return;
      case MMonElection::OP_VICTORY:
	handle_victory(em);
	return;
      default:
	assert(0);
      }
    }
    break;

  default:
    assert(0);
  }
}

<commit_msg>elector: off by one check<commit_after>// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1, as published by the Free Software
 * Foundation.  See file COPYING.
 *
 */

#include "Elector.h"
#include "Monitor.h"

#include "common/Timer.h"
#include "MonitorStore.h"
#include "messages/MMonElection.h"

#include "config.h"

#define DOUT_SUBSYS mon
#undef dout_prefix
#define dout_prefix _prefix(mon, epoch)
static ostream& _prefix(Monitor *mon, epoch_t epoch) {
  return *_dout << dbeginl
		<< "mon" << mon->whoami
		<< (mon->is_starting() ? (const char*)"(starting)":(mon->is_leader() ? (const char*)"(leader)":(mon->is_peon() ? (const char*)"(peon)":(const char*)"(?\?)")))
		<< ".elector(" << epoch << ") ";
}

void Elector::init()
{
  epoch = mon->store->get_int("election_epoch");
  if (!epoch)
    epoch = 1;
  dout(1) << "init, last seen epoch " << epoch << dendl;
}

void Elector::shutdown()
{
  if (expire_event)
    mon->timer.cancel_event(expire_event);
}

void Elector::bump_epoch(epoch_t e)
{
  dout(10) << "bump_epoch " << epoch << " to " << e << dendl;
  assert(epoch <= e);
  epoch = e;
  mon->store->put_int(epoch, "election_epoch");

  // clear up some state
  electing_me = false;
  acked_me.clear();
  leader_acked = -1;
}

void Elector::start()
{
  dout(5) << "start -- can i be leader?" << dendl;

  // start by trying to elect me
  if (epoch % 2 == 0)
    bump_epoch(epoch+1);  // odd == election cycle
  start_stamp = g_clock.now();
  electing_me = true;
  acked_me.insert(whoami);

  // bcast to everyone else
  for (unsigned i=0; i<mon->monmap->size(); ++i) {
    if ((int)i == whoami) continue;
    mon->messenger->send_message(new MMonElection(MMonElection::OP_PROPOSE, epoch, mon->monmap),
				 mon->monmap->get_inst(i));
  }

  reset_timer();
}

void Elector::defer(int who)
{
  dout(5) << "defer to " << who << dendl;

  if (electing_me) {
    // drop out
    acked_me.clear();
    electing_me = false;
  }

  // ack them
  leader_acked = who;
  ack_stamp = g_clock.now();
  mon->messenger->send_message(new MMonElection(MMonElection::OP_ACK, epoch, mon->monmap),
			       mon->monmap->get_inst(who));

  // set a timer
  reset_timer(1.0);  // give the leader some extra time to declare victory
}

void Elector::reset_timer(double plus)
{
  // set the timer
  cancel_timer();
  expire_event = new C_ElectionExpire(this);
  mon->timer.add_event_after(g_conf.mon_lease + plus,
			     expire_event);
}

void Elector::cancel_timer()
{
  if (expire_event) {
    mon->timer.cancel_event(expire_event);
    expire_event = 0;
  }
}

void Elector::expire()
{
  dout(5) << "election timer expired" << dendl;

  // did i win?
  if (electing_me &&
      acked_me.size() > (unsigned)(mon->monmap->size() / 2)) {
    // i win
    victory();
  } else {
    // whoever i deferred to didn't declare victory quickly enough.
    start();
  }
}

void Elector::victory()
{
  leader_acked = -1;
  electing_me = false;
  set<int> quorum = acked_me;

  cancel_timer();

  assert(epoch % 2 == 1);  // election
  bump_epoch(epoch+1);     // is over!

  // tell everyone
  for (set<int>::iterator p = quorum.begin();
       p != quorum.end();
       ++p) {
    if (*p == whoami) continue;
    MMonElection *m = new MMonElection(MMonElection::OP_VICTORY, epoch, mon->monmap);
    m->quorum = quorum;
    mon->messenger->send_message(m, mon->monmap->get_inst(*p));
  }

  // tell monitor
  mon->win_election(epoch, quorum);
}

void Elector::handle_propose(MMonElection *m)
{
  dout(5) << "handle_propose from " << m->get_source() << dendl;
  int from = m->get_source().num();

  assert(m->epoch % 2 == 1); // election
  if (m->epoch > epoch) {
    bump_epoch(m->epoch);
  }
  else if (m->epoch < epoch) {
    // got an "old" propose,
    if (epoch % 2 == 0 &&    // in a non-election cycle
	mon->quorum.count(from) == 0) {  // from someone outside the quorum
      // a mon just started up, call a new election so they can rejoin!
      dout(5) << " got propose from old epoch, quorum is " << mon->quorum
	      << ", " << m->get_source() << " must have just started" << dendl;
      mon->call_election(false);//start();
    } else {
      dout(5) << " ignoring old propose" << dendl;
      delete m;
      return;
    }
  }

  if (whoami < from) {
    // i would win over them.
    if (leader_acked >= 0) {        // we already acked someone
      assert(leader_acked < from);  // and they still win, of course
      dout(5) << "no, we already acked " << leader_acked << dendl;
    } else {
      // wait, i should win!
      if (!electing_me)
	mon->call_election(false);//start();
    }
  } else {
    // they would win over me
    if (leader_acked < 0 ||      // haven't acked anyone yet, or
	leader_acked > from ||   // they would win over who you did ack, or
	leader_acked == from) {  // this is the guy we're already deferring to
      defer(from);
    } else {
      // ignore them!
      dout(5) << "no, we already acked " << leader_acked << dendl;
    }
  }

  delete m;
}

void Elector::handle_ack(MMonElection *m)
{
  dout(5) << "handle_ack from " << m->get_source() << dendl;
  int from = m->get_source().num();

  assert(m->epoch % 2 == 1); // election
  if (m->epoch > epoch) {
    dout(5) << "woah, that's a newer epoch, i must have rebooted.  bumping and re-starting!" << dendl;
    bump_epoch(m->epoch);
    mon->call_election(false);//start();
    delete m;
    return;
  }
  assert(m->epoch == epoch);

  if (electing_me) {
    // thanks
    acked_me.insert(from);
    dout(5) << " so far i have " << acked_me << dendl;

    // is that _everyone_?
    if (acked_me.size() == mon->monmap->size()) {
      // if yes, shortcut to election finish
      victory();
    }
  } else {
    // ignore, i'm deferring already.
    assert(leader_acked >= 0);
  }

  delete m;
}

void Elector::handle_victory(MMonElection *m)
{
  dout(5) << "handle_victory from " << m->get_source() << dendl;
  int from = m->get_source().num();

  assert(from < whoami);
  assert(m->epoch % 2 == 0);

  // i should have seen this election if i'm getting the victory.
  if (m->epoch != epoch + 1) {
    dout(5) << "woah, that's a funny epoch, i must have rebooted.  bumping and re-starting!" << dendl;
    bump_epoch(m->epoch);
    mon->call_election(true);//start();
    delete m;
    return;
  }

  bump_epoch(m->epoch);

  // they win
  mon->lose_election(epoch, m->quorum, from);

  // cancel my timer
  cancel_timer();
  delete m;
}

void Elector::dispatch(Message *m)
{
  switch (m->get_type()) {

  case MSG_MON_ELECTION:
    {
      MMonElection *em = (MMonElection*)m;

      MonMap *peermap = new MonMap;
      peermap->decode(em->monmap_bl);
      if (peermap->epoch > mon->monmap->epoch) {
	dout(0) << m->get_source_inst() << " has newer monmap epoch " << peermap->epoch
		<< " > my epoch " << mon->monmap->epoch
		<< ", taking it"
		<< dendl;
	delete mon->monmap;
	mon->monmap = peermap;
	mon->store->put_bl_sn(em->monmap_bl, "monmap", peermap->epoch);
	mon->store->put_bl_ss(em->monmap_bl, "monmap", "latest");
      } else {
	if (peermap->epoch < mon->monmap->epoch) {
	  dout(0) << m->get_source_inst() << " has older monmap epoch " << peermap->epoch
		  << " < my epoch " << mon->monmap->epoch
		  << dendl;
	}
	delete peermap;
      }

      switch (em->op) {
      case MMonElection::OP_PROPOSE:
	handle_propose(em);
	return;
      }

      if (em->epoch < epoch) {
	dout(5) << "old epoch, dropping" << dendl;
	delete em;
	break;
      }

      switch (em->op) {
      case MMonElection::OP_ACK:
	handle_ack(em);
	return;
      case MMonElection::OP_VICTORY:
	handle_victory(em);
	return;
      default:
	assert(0);
      }
    }
    break;

  default:
    assert(0);
  }
}

<|endoftext|>


<commit_before>#include <map>

#include "nameplacer.h"
#include "util/font.h"
#include "factory/font_factory.h"
#include "globals.h"

NamePlacer * NamePlacer::placer = NULL;
void NamePlacer::getPlacement( int & x, int & y, int & id ){

	if ( placer == NULL )
		placer = new NamePlacer();

	placer->doPlacement( x, y, id );
}

void NamePlacer::destroy(){
	if ( placer != NULL ){
		delete placer;
		placer = NULL;
	}
}

NamePlacer::NamePlacer(){
	cur_id = 0;
}

void NamePlacer::doPlacement( int & x, int & y, int & id ){

	if ( id == -1 || places[ id ] == 0 )
		id = cur_id++;

	for ( map< int, int >::iterator it = places.begin(); it != places.end(); it++ ){
		int & second = (*it).second;
		if ( second > 0 )
			second--;
	}

	int count = 0;
	for ( map<int,int>::iterator it = places.begin(); it != places.end() && it != places.find( id ); it++){
		if ( (*it).second > 0 )
			count++;
	}
	/* give the place some buffer room to go away */
	places[ id ] = 10;
	const Font & ft = Font::getFont( "data/fonts/arial.ttf" );
	x = 1 + (count&1) * 170;
	y = 1 + (count/2) * ft.getHeight();
}
<commit_msg>dont space out names to far<commit_after>#include <map>

#include "nameplacer.h"
#include "util/font.h"
#include "factory/font_factory.h"
#include "globals.h"

NamePlacer * NamePlacer::placer = NULL;
void NamePlacer::getPlacement( int & x, int & y, int & id ){

	if ( placer == NULL )
		placer = new NamePlacer();

	placer->doPlacement( x, y, id );
}

void NamePlacer::destroy(){
	if ( placer != NULL ){
		delete placer;
		placer = NULL;
	}
}

NamePlacer::NamePlacer(){
	cur_id = 0;
}

void NamePlacer::doPlacement( int & x, int & y, int & id ){

	if ( id == -1 || places[ id ] == 0 )
		id = cur_id++;

	for ( map< int, int >::iterator it = places.begin(); it != places.end(); it++ ){
		int & second = (*it).second;
		if ( second > 0 )
			second--;
	}

	int count = 0;
	for ( map<int,int>::iterator it = places.begin(); it != places.end() && it != places.find( id ); it++){
		if ( (*it).second > 0 )
			count++;
	}
	/* give the place some buffer room to go away */
	places[ id ] = 10;
	const Font & ft = Font::getFont( "data/fonts/arial.ttf" );
	x = 1 + (count&1) * 170;
	y = 1 + (count/2) * ft.getHeight() / 2;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2010, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

#include <object/symbols.hh>
#include <urbi/object/date.hh>
#include <urbi/object/duration.hh>
#include <urbi/object/global.hh>
#include <boost/date_time/posix_time/posix_time.hpp>

namespace urbi
{
  namespace object
  {
    /*---------------.
    | Construction.  |
    `---------------*/

    Date::Date()
      : time_(0)
    {
      proto_add(proto ? proto : Object::proto);
    }

    Date::Date(value_type t)
      : time_(t)
    {
      proto_add(proto ? proto : Object::proto);
    }

    Date::Date(rDate time)
      : time_(time->time_)
    {
      CAPTURE_GLOBAL(Orderable);
      proto_add(Orderable);
      proto_add(proto);
    }

    void
    Date::init(const objects_type& args)
    {
      check_arg_count(args.size(), 0, 1);

      if (args.empty())
      {
        time_ = 0;
        return;
      }

      if (rString str = args[0]->as<object::String>())
      {
        boost::posix_time::ptime t
          (boost::posix_time::time_from_string(str->value_get()));
        tm timeinfo = boost::posix_time::to_tm(t);
        time_ = mktime (&timeinfo);

        return;
      }

      time_ = from_urbi<unsigned>(args[0]);
    }

    /*-------------.
    | Comparison.  |
    `-------------*/

    bool
    Date::operator ==(rDate rhs) const
    {
      return time_ == rhs->time_;
    }

    bool
    Date::operator <(rDate rhs) const
    {
      return time_ < rhs->time_;
    }

    /*-------------.
    | Operations.  |
    `-------------*/

    rDuration
    Date::operator - (rDate rhs) const
    {
      return new Duration(time_ - rhs->time_);
    }

    Date&
    Date::operator += (rDuration rhs)
    {
      time_ += static_cast<value_type>(rhs->seconds());
      return *this;
    }

    rDate
    Date::operator + (rDuration rhs) const
    {
      rDate res = new Date(time_);
      *res += rhs;
      return res;
    }

    /*--------------.
    | Conversions.  |
    `--------------*/

    std::string
    Date::as_string() const
    {
      struct tm date;
      localtime_r(&time_, &date);
      return libport::format("%04s-%02s-%02s %02s:%02s:%02s",
                             1900 + date.tm_year,
                             date.tm_mon + 1,
                             date.tm_mday,
                             date.tm_hour,
                             date.tm_min,
                             date.tm_sec);
    }

    libport::ufloat
    Date::asFloat () const
    {
      return time_;
    }

    libport::ufloat
    Date::timestamp () const
    {
      return asFloat ();
    }

    /*--------.
    | Dates.  |
    `--------*/

    rDate
    Date::now ()
    {
      return new Date(time(0));
    }

    rDate
    Date::epoch ()
    {
      return new Date(0);
    }

    /*-----------------.
    | Binding system.  |
    `-----------------*/

    void
    Date::initialize(CxxObject::Binder<Date>& bind)
    {
      bind(SYMBOL(EQ_EQ), &Date::operator ==);
      bind(SYMBOL(LT), (bool (Date::*)(rDate rhs) const)&Date::operator <);
      bind(SYMBOL(MINUS), &Date::operator -);
      bind(SYMBOL(PLUS), &Date::operator +);
      bind(SYMBOL(asString), &Date::as_string);
      bind(SYMBOL(epoch), &Date::epoch);
      bind(SYMBOL(init), &Date::init);
      bind(SYMBOL(now), &Date::now);
      bind(SYMBOL(timestamp), &Date::timestamp);
    }

    URBI_CXX_OBJECT_REGISTER(Date)
      : time_(0)
    {}
  }
}
<commit_msg>date: fix.<commit_after>/*
 * Copyright (C) 2010, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

#include <object/symbols.hh>
#include <urbi/object/date.hh>
#include <urbi/object/duration.hh>
#include <urbi/object/global.hh>
#include <boost/date_time/posix_time/posix_time.hpp>

namespace urbi
{
  namespace object
  {
    /*---------------.
    | Construction.  |
    `---------------*/

    Date::Date()
      : time_(0)
    {
      proto_add(proto ? proto : Object::proto);
    }

    Date::Date(value_type t)
      : time_(t)
    {
      proto_add(proto ? proto : Object::proto);
    }

    Date::Date(rDate time)
      : time_(time->time_)
    {
      CAPTURE_GLOBAL(Orderable);
      proto_add(Orderable);
      proto_add(proto);
    }

    void
    Date::init(const objects_type& args)
    {
      check_arg_count(args.size(), 0, 1);

      if (args.empty())
      {
        time_ = 0;
        return;
      }

      if (rString str = args[0]->as<object::String>())
      {
        boost::posix_time::ptime t
          (boost::posix_time::time_from_string(str->value_get()));
        tm timeinfo = boost::posix_time::to_tm(t);
        time_ = mktime (&timeinfo);

        return;
      }

      time_ = from_urbi<unsigned>(args[0]);
    }

    /*-------------.
    | Comparison.  |
    `-------------*/

    bool
    Date::operator ==(rDate rhs) const
    {
      return time_ == rhs->time_;
    }

    bool
    Date::operator <(rDate rhs) const
    {
      return time_ < rhs->time_;
    }

    /*-------------.
    | Operations.  |
    `-------------*/

    rDuration
    Date::operator - (rDate rhs) const
    {
      return new Duration(time_ - rhs->time_);
    }

    Date&
    Date::operator += (rDuration rhs)
    {
      time_ += static_cast<value_type>(rhs->seconds());
      return *this;
    }

    rDate
    Date::operator + (rDuration rhs) const
    {
      rDate res = new Date(time_);
      *res += rhs;
      return res;
    }

    /*--------------.
    | Conversions.  |
    `--------------*/

    std::string
    Date::as_string() const
    {
      struct tm date;
      localtime_r(&time_, &date);
      return libport::format("%04s-%02s-%02s %02s:%02s:%02s",
                             1900 + date.tm_year,
                             date.tm_mon + 1,
                             date.tm_mday,
                             date.tm_hour,
                             date.tm_min,
                             date.tm_sec);
    }

    libport::ufloat
    Date::asFloat() const
    {
      return time_;
    }

    libport::ufloat
    Date::timestamp() const
    {
      return asFloat ();
    }

    /*--------.
    | Dates.  |
    `--------*/

    rDate
    Date::now ()
    {
      return new Date(time(0));
    }

    rDate
    Date::epoch ()
    {
      return new Date(0);
    }

    /*-----------------.
    | Binding system.  |
    `-----------------*/

    void
    Date::initialize(CxxObject::Binder<Date>& bind)
    {
      bind(SYMBOL(EQ_EQ), &Date::operator ==);
      bind(SYMBOL(LT), (bool (Date::*)(rDate rhs) const)&Date::operator <);
      bind(SYMBOL(MINUS), &Date::operator -);
      bind(SYMBOL(PLUS), &Date::operator +);
      bind(SYMBOL(asFloat), &Date::asFloat);
      bind(SYMBOL(asString), &Date::as_string);
      bind(SYMBOL(epoch), &Date::epoch);
      bind(SYMBOL(init), &Date::init);
      bind(SYMBOL(now), &Date::now);
      bind(SYMBOL(timestamp), &Date::timestamp);
    }

    URBI_CXX_OBJECT_REGISTER(Date)
      : time_(0)
    {}
  }
}
<|endoftext|>