<commit_before>#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <array>
#include <vector>
#include <set>
#include <map>
#include <random>
#include <chrono>
#include <functional>
#include <algorithm>

#include <cmath>

#define NUM_FIELDS 16

using Entry = std::array<double, NUM_FIELDS>;
using IntPair = std::pair<int, int>;

struct CompareSecond: std::binary_function<IntPair, IntPair, bool>
{
    bool operator()(const IntPair& a, const IntPair& b)
    {
        return a.second < b.second;
    }
};

int main(int argc, char** argv)
{
    // smoothing factor
    const double alpha = 1.0;
    // decision rule
    const int decision = 1;

    if (argc < 2)
        return 1;

    // preparing data
    int total = 0, correct = 0, totalClassified = 0;
    std::map<std::string, std::vector<Entry> > data;
    std::map<std::string, int> n;
    std::map<std::string, double> priors;
    std::map<std::string, std::vector<double> > multinomialLikelihoods;
    std::map<std::string, int> multinomialSums;
    std::map<std::string, Entry > sumX;
    std::map<std::string, std::vector<double> > means;
    std::map<std::string, std::vector<double> > variances;

    auto classify = [&](const std::string& label, const Entry& entry)
    {
        std::string predlabel;
        double maxlikelihood = 0.0;
        double denom = 0.0;
        std::vector<double> probs;
        for (auto it = priors.begin(); it != priors.end(); it++)
        {
            double numer = priors[it->first];
            const auto& firstMultinomialLikelihood = multinomialLikelihoods[it->first];
            const auto& firstMean = means[it->first];
            const auto& firstVariance = variances[it->first];
            for (int j = 0; j < NUM_FIELDS; j++)
                switch (decision)
                {
                    case 2:
                        // Multinomial
                        if (entry[j])
                            numer *= pow(firstMultinomialLikelihood[j], entry[j]);
                        break;

                    case 3:
                        // Bernoulli
                        numer *= pow(firstMean[j], entry[j]) * pow(1.0 - firstMean[j], 1.0 - entry[j]);
                        break;

                    default:
                        // Gaussian
                        numer *= 1 / sqrt(2 * M_PI * firstVariance[j]) * exp((-1 * (entry[j] - firstMean[j]) * (entry[j] -firstMean[j])) / (2 * firstVariance[j]));
                        break;
                }

            if (numer > maxlikelihood)
            {
                maxlikelihood = numer;
                predlabel = it->first;
            }
            denom += numer;
            probs.push_back(numer);
        }

        std::cout << predlabel << "\t" << std::setw(1) << std::setprecision(3) << maxlikelihood/denom << "\t";
        if ("" == label)
            std::cout << "<no label>" << std::endl;
        else if (predlabel == label)
        {
            std::cout << "correct" << std::endl;
            correct++;
        }
        else
            std::cout << "incorrect" << std::endl;

        totalClassified++;
    };

    auto readFromFile = [&](const char* filename, bool isClassification)
    {
        std::ifstream file(argv[1]);
        if (!file.is_open())
            return 1;

        while (!file.eof())
        {
            std::string line;
            std::getline(file, line);
            if ("" == line)
                continue;
            std::istringstream linein(std::move(line));
            std::string label;
            std::getline(linein, label, ',');
            Entry entry;
            auto setField = [&entry, &label, &sumX, &multinomialSums, isClassification](int i, const std::string& field)
            {
                switch (field[0])
                {
                    case 'y':
                        entry[i] = 1.0;
                        break;

                    case 'n':
                        entry[i] = 0.0;
                        break;

                    case '?':
                        entry[i] = 0.5;
                        break;
                }
                if (!isClassification)
                {
                    sumX[label][i] += entry[i];
                    multinomialSums[label] += entry[i];
                }
            };
            for (int i = 0; i < NUM_FIELDS; i++)
            {
                std::string field;
                std::getline(linein, field, ',');
                setField(i, field);
            }
            std::string field;
            std::getline(linein, field);
            setField(NUM_FIELDS - 1, field);
            if (!isClassification)
            {
                data[label].push_back(std::move(entry));
                n[label]++;
                total++;
            }
            else
                classify(label, entry);
        }

        return 0;
    };

    int errcode = readFromFile(argv[1], false);
    if (errcode)
        return errcode;

    for (auto it = sumX.begin(); it != sumX.end(); it++)
    {
        priors[it->first] = (double)n[it->first] / total;

        std::cout << "Class " << it->first << ", prior: " << std::setw(1) << std::setprecision(3) << priors[it->first] << std::endl;
        std::cout << "feature\tmean\tvar\tstddev\tmnl" << std::endl;

        // calculate means
        std::vector<double> featureMeans(NUM_FIELDS);
        for (int i = 0; i < NUM_FIELDS; i++)
            featureMeans[i] = sumX[it->first][i] / n[it->first];

        // calculate variances
        std::vector<double> featureVariances(NUM_FIELDS);
        const auto& firstData = data[it->first];
        for (int i = 0; i < (int)firstData.size(); i++)
            for (int j = 0; j < NUM_FIELDS; j++)
                featureVariances[j] += (firstData[i][j] - featureMeans[j]) * (firstData[i][j] - featureMeans[j]);
        for (int i = 0; i < NUM_FIELDS; i++)
            featureVariances[i] /= firstData.size();

        const auto& firstSumX = sumX[it->first];
        auto firstMultinomialSum = multinomialSums[it->first];
        auto& firstMultinomialLikelihood = multinomialLikelihoods[it->first];
        // calculate multinomial likelihoods
        for (int i = 0; i < NUM_FIELDS; i++)
        {
            double mnl = (firstSumX[i] + alpha) / (firstMultinomialSum + (alpha * featureMeans.size()));
            firstMultinomialLikelihood.push_back(mnl);
        }

        for (unsigned int i = 0; i < NUM_FIELDS; i++)
            printf("%i\t%2.3f\t%2.3f\t%2.3f\t%2.3f\n",i+1,featureMeans[i],featureVariances[i],sqrt(featureVariances[i]),firstMultinomialLikelihood[i]);

        means[it->first] = std::move(featureMeans);
        variances[it->first] = std::move(featureVariances);
    }

    // classify
    std::cout << "Classifying:" << std::endl;
    std::cout << "class\tprob\tresult" << std::endl;

    errcode = readFromFile(argv[2], true);
    if (errcode)
        return errcode;
    printf("Accuracy: %3.2f %% (%i/%i)\n", 100.0 * correct / totalClassified, correct, totalClassified);

    return 0;
}
<commit_msg>bayes: dropped some redundant types<commit_after>#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <array>
#include <vector>
#include <set>
#include <map>
#include <random>
#include <chrono>
#include <functional>
#include <algorithm>

#include <cmath>

#define NUM_FIELDS 16

using Entry = std::array<double, NUM_FIELDS>;

int main(int argc, char** argv)
{
    // smoothing factor
    const double alpha = 1.0;
    // decision rule
    const int decision = 1;

    if (argc < 2)
        return 1;

    // preparing data
    int total = 0, correct = 0, totalClassified = 0;
    std::map<std::string, std::vector<Entry> > data;
    std::map<std::string, int> n;
    std::map<std::string, double> priors;
    std::map<std::string, std::vector<double> > multinomialLikelihoods;
    std::map<std::string, int> multinomialSums;
    std::map<std::string, Entry > sumX;
    std::map<std::string, std::vector<double> > means;
    std::map<std::string, std::vector<double> > variances;

    auto classify = [&](const std::string& label, const Entry& entry)
    {
        std::string predlabel;
        double maxlikelihood = 0.0;
        double denom = 0.0;
        std::vector<double> probs;
        for (auto it = priors.begin(); it != priors.end(); it++)
        {
            double numer = priors[it->first];
            const auto& firstMultinomialLikelihood = multinomialLikelihoods[it->first];
            const auto& firstMean = means[it->first];
            const auto& firstVariance = variances[it->first];
            for (int j = 0; j < NUM_FIELDS; j++)
                switch (decision)
                {
                    case 2:
                        // Multinomial
                        if (entry[j])
                            numer *= pow(firstMultinomialLikelihood[j], entry[j]);
                        break;

                    case 3:
                        // Bernoulli
                        numer *= pow(firstMean[j], entry[j]) * pow(1.0 - firstMean[j], 1.0 - entry[j]);
                        break;

                    default:
                        // Gaussian
                        numer *= 1 / sqrt(2 * M_PI * firstVariance[j]) * exp((-1 * (entry[j] - firstMean[j]) * (entry[j] -firstMean[j])) / (2 * firstVariance[j]));
                        break;
                }

            if (numer > maxlikelihood)
            {
                maxlikelihood = numer;
                predlabel = it->first;
            }
            denom += numer;
            probs.push_back(numer);
        }

        std::cout << predlabel << "\t" << std::setw(1) << std::setprecision(3) << maxlikelihood/denom << "\t";
        if ("" == label)
            std::cout << "<no label>" << std::endl;
        else if (predlabel == label)
        {
            std::cout << "correct" << std::endl;
            correct++;
        }
        else
            std::cout << "incorrect" << std::endl;

        totalClassified++;
    };

    auto readFromFile = [&](const char* filename, bool isClassification)
    {
        std::ifstream file(argv[1]);
        if (!file.is_open())
            return 1;

        while (!file.eof())
        {
            std::string line;
            std::getline(file, line);
            if ("" == line)
                continue;
            std::istringstream linein(std::move(line));
            std::string label;
            std::getline(linein, label, ',');
            Entry entry;
            auto setField = [&entry, &label, &sumX, &multinomialSums, isClassification](int i, const std::string& field)
            {
                switch (field[0])
                {
                    case 'y':
                        entry[i] = 1.0;
                        break;

                    case 'n':
                        entry[i] = 0.0;
                        break;

                    case '?':
                        entry[i] = 0.5;
                        break;
                }
                if (!isClassification)
                {
                    sumX[label][i] += entry[i];
                    multinomialSums[label] += entry[i];
                }
            };
            for (int i = 0; i < NUM_FIELDS; i++)
            {
                std::string field;
                std::getline(linein, field, ',');
                setField(i, field);
            }
            std::string field;
            std::getline(linein, field);
            setField(NUM_FIELDS - 1, field);
            if (!isClassification)
            {
                data[label].push_back(std::move(entry));
                n[label]++;
                total++;
            }
            else
                classify(label, entry);
        }

        return 0;
    };

    int errcode = readFromFile(argv[1], false);
    if (errcode)
        return errcode;

    for (auto it = sumX.begin(); it != sumX.end(); it++)
    {
        priors[it->first] = (double)n[it->first] / total;

        std::cout << "Class " << it->first << ", prior: " << std::setw(1) << std::setprecision(3) << priors[it->first] << std::endl;
        std::cout << "feature\tmean\tvar\tstddev\tmnl" << std::endl;

        // calculate means
        std::vector<double> featureMeans(NUM_FIELDS);
        for (int i = 0; i < NUM_FIELDS; i++)
            featureMeans[i] = sumX[it->first][i] / n[it->first];

        // calculate variances
        std::vector<double> featureVariances(NUM_FIELDS);
        const auto& firstData = data[it->first];
        for (int i = 0; i < (int)firstData.size(); i++)
            for (int j = 0; j < NUM_FIELDS; j++)
                featureVariances[j] += (firstData[i][j] - featureMeans[j]) * (firstData[i][j] - featureMeans[j]);
        for (int i = 0; i < NUM_FIELDS; i++)
            featureVariances[i] /= firstData.size();

        const auto& firstSumX = sumX[it->first];
        auto firstMultinomialSum = multinomialSums[it->first];
        auto& firstMultinomialLikelihood = multinomialLikelihoods[it->first];
        // calculate multinomial likelihoods
        for (int i = 0; i < NUM_FIELDS; i++)
        {
            double mnl = (firstSumX[i] + alpha) / (firstMultinomialSum + (alpha * featureMeans.size()));
            firstMultinomialLikelihood.push_back(mnl);
        }

        for (unsigned int i = 0; i < NUM_FIELDS; i++)
            printf("%i\t%2.3f\t%2.3f\t%2.3f\t%2.3f\n",i+1,featureMeans[i],featureVariances[i],sqrt(featureVariances[i]),firstMultinomialLikelihood[i]);

        means[it->first] = std::move(featureMeans);
        variances[it->first] = std::move(featureVariances);
    }

    // classify
    std::cout << "Classifying:" << std::endl;
    std::cout << "class\tprob\tresult" << std::endl;

    errcode = readFromFile(argv[2], true);
    if (errcode)
        return errcode;
    printf("Accuracy: %3.2f %% (%i/%i)\n", 100.0 * correct / totalClassified, correct, totalClassified);

    return 0;
}
<|endoftext|>


<commit_before>#include "SerialController.h"
#include <utils/AnyCollection.h>

SerialController::SerialController(Robot& robot,const string& _servAddr,Real _writeRate)
  :RobotController(robot),servAddr(_servAddr),writeRate(_writeRate),lastWriteTime(0)
{
  if(!servAddr.empty())
    OpenConnection(servAddr);
}

void SerialController::PackSensorData(AnyCollection& data) const
{
  data["t"] = time;
  data["dt"] = 1.0/writeRate;
  for(size_t i=0;i<sensors->sensors.size();i++) {
    vector<double> values;
    sensors->sensors[i]->GetMeasurements(values);
    data[sensors->sensors[i]->name] = AnyCollection(values);
  }
}

void SerialController::Update(Real dt)
{
  RobotController::Update(dt);
#ifndef WIN32
  if(time >= lastWriteTime + 1.0/writeRate) {
    lastWriteTime += 1.0/writeRate;
    if(time >= lastWriteTime + 1.0/writeRate) {
      printf("Warning, next write time %g is less than controller update time %g\n",lastWriteTime+1.0/writeRate,time);
      lastWriteTime = time;
    }
    AnyCollection sensorData;
    PackSensorData(sensorData);
    stringstream ss;
    ss << sensorData;
    if(controllerPipe) {
      controllerPipe->SendMessage(ss.str());
    }
  }
  if(controllerPipe && controllerPipe->NewMessageCount() > 0) {
    string scmd = controllerPipe->NewestMessage();
    AnyCollection cmd;
    if(!cmd.read(scmd.c_str())) {
      fprintf(stderr,"SerialController: Unable to parse incoming message %s\n",scmd.c_str());
      return;
    }
    SmartPointer<AnyCollection> qcmdptr = cmd.find("qcmd");
    SmartPointer<AnyCollection> dqcmdptr = cmd.find("dqcmd");
    SmartPointer<AnyCollection> torquecmdptr = cmd.find("torquecmd");
    SmartPointer<AnyCollection> tcmdptr = cmd.find("tcmd");
    if(qcmdptr) {
      vector<Real> qcmd,dqcmd,torquecmd;
      if(!qcmdptr->asvector(qcmd)) {
	fprintf(stderr,"SerialController: qcmd not of proper type\n");
	return;
      }
      if(dqcmdptr) {
	if(!dqcmdptr->asvector(dqcmd)) {
	  fprintf(stderr,"SerialController: dqcmd not of proper type\n");
	  return;
	}
      }
      else
	dqcmd.resize(qcmd.size(),0);
      if(torquecmdptr) {
	if(!torquecmdptr->asvector(torquecmd)) {
	  fprintf(stderr,"SerialController: torquecmd not of proper type\n");
	  return;
	}
      }
      if(torquecmd.empty()) {
	SetPIDCommand(qcmd,dqcmd);
      }
      else
	SetFeedforwardPIDCommand(qcmd,dqcmd,torquecmd);
    }
    else if(dqcmdptr) {
      if(tcmdptr == NULL) {
	fprintf(stderr,"SerialController: dqcmd not given with tcmd\n");
	return;
      }
      FatalError("Velocity commands not implemented yet");
    }
    else if(torquecmdptr) {
      vector<Real> torquecmd;
      if(!torquecmdptr->asvector(torquecmd)) {
	fprintf(stderr,"SerialController: torquecmd not of proper type\n");
	return;
      }
      SetTorqueCommand(torquecmd);
    }
    else {
      fprintf(stderr,"SerialController: message doesn't contain proper command type\n");
      return;
    }
  }
#endif //WIN32
}

void SerialController::Reset()
{
  RobotController::Reset();
  lastWriteTime = 0;
}

map<string,string> SerialController::Settings() const
{
  map<string,string> settings;
  FILL_CONTROLLER_SETTING(settings,servAddr);
  FILL_CONTROLLER_SETTING(settings,writeRate);
  if(controllerPipe)
    settings["connected"]="1";
  else
    settings["connected"]="0";
  return settings;
}

bool SerialController::GetSetting(const string& name,string& str) const
{
  READ_CONTROLLER_SETTING(servAddr)
  READ_CONTROLLER_SETTING(writeRate)
  return false;
}

bool SerialController::SetSetting(const string& name,const string& str)
{
  if(name == "servAddr") {
    OpenConnection(str);
    return true;
  }
  WRITE_CONTROLLER_SETTING(writeRate)
  return false;
}

bool SerialController::OpenConnection(const string& addr)
{
  servAddr = addr;
  if(addr.empty()) {
    CloseConnection();
    return true;
  }
  controllerPipe = new SocketPipeWorker(addr.c_str(),true);
  if(!controllerPipe->Start()) {
    cout<<"Controller could not be opened on address "<<addr<<endl;
    return false;
  }
  return true;
}

bool SerialController::CloseConnection()
{
  if(controllerPipe) {
    controllerPipe->Stop();
    controllerPipe = NULL;
    return true;
  }
  return false;
}
<commit_msg>Doesn't queue up messages if no client is connected<commit_after>#include "SerialController.h"
#include <utils/AnyCollection.h>

SerialController::SerialController(Robot& robot,const string& _servAddr,Real _writeRate)
  :RobotController(robot),servAddr(_servAddr),writeRate(_writeRate),lastWriteTime(0)
{
  if(!servAddr.empty())
    OpenConnection(servAddr);
}

void SerialController::PackSensorData(AnyCollection& data) const
{
  data["t"] = time;
  data["dt"] = 1.0/writeRate;
  for(size_t i=0;i<sensors->sensors.size();i++) {
    vector<double> values;
    sensors->sensors[i]->GetMeasurements(values);
    data[sensors->sensors[i]->name] = AnyCollection(values);
  }
}

void SerialController::Update(Real dt)
{
  RobotController::Update(dt);
#ifndef WIN32
  if(time >= lastWriteTime + 1.0/writeRate) {
    lastWriteTime += 1.0/writeRate;
    if(time >= lastWriteTime + 1.0/writeRate) {
      printf("Warning, next write time %g is less than controller update time %g\n",lastWriteTime+1.0/writeRate,time);
      lastWriteTime = time;
    }
    AnyCollection sensorData;
    PackSensorData(sensorData);
    stringstream ss;
    ss << sensorData;
    if(controllerPipe && controllerPipe->transport->WriteReady()) {
      controllerPipe->SendMessage(ss.str());
    }
  }
  if(controllerPipe && controllerPipe->NewMessageCount() > 0) {
    string scmd = controllerPipe->NewestMessage();
    AnyCollection cmd;
    if(!cmd.read(scmd.c_str())) {
      fprintf(stderr,"SerialController: Unable to parse incoming message %s\n",scmd.c_str());
      return;
    }
    SmartPointer<AnyCollection> qcmdptr = cmd.find("qcmd");
    SmartPointer<AnyCollection> dqcmdptr = cmd.find("dqcmd");
    SmartPointer<AnyCollection> torquecmdptr = cmd.find("torquecmd");
    SmartPointer<AnyCollection> tcmdptr = cmd.find("tcmd");
    if(qcmdptr) {
      vector<Real> qcmd,dqcmd,torquecmd;
      if(!qcmdptr->asvector(qcmd)) {
	fprintf(stderr,"SerialController: qcmd not of proper type\n");
	return;
      }
      if(dqcmdptr) {
	if(!dqcmdptr->asvector(dqcmd)) {
	  fprintf(stderr,"SerialController: dqcmd not of proper type\n");
	  return;
	}
      }
      else
	dqcmd.resize(qcmd.size(),0);
      if(torquecmdptr) {
	if(!torquecmdptr->asvector(torquecmd)) {
	  fprintf(stderr,"SerialController: torquecmd not of proper type\n");
	  return;
	}
      }
      if(torquecmd.empty()) {
	SetPIDCommand(qcmd,dqcmd);
      }
      else
	SetFeedforwardPIDCommand(qcmd,dqcmd,torquecmd);
    }
    else if(dqcmdptr) {
      if(tcmdptr == NULL) {
	fprintf(stderr,"SerialController: dqcmd not given with tcmd\n");
	return;
      }
      FatalError("Velocity commands not implemented yet");
    }
    else if(torquecmdptr) {
      vector<Real> torquecmd;
      if(!torquecmdptr->asvector(torquecmd)) {
	fprintf(stderr,"SerialController: torquecmd not of proper type\n");
	return;
      }
      SetTorqueCommand(torquecmd);
    }
    else {
      fprintf(stderr,"SerialController: message doesn't contain proper command type\n");
      return;
    }
  }
#endif //WIN32
}

void SerialController::Reset()
{
  RobotController::Reset();
  lastWriteTime = 0;
}

map<string,string> SerialController::Settings() const
{
  map<string,string> settings;
  FILL_CONTROLLER_SETTING(settings,servAddr);
  FILL_CONTROLLER_SETTING(settings,writeRate);
  if(controllerPipe)
    settings["connected"]="1";
  else
    settings["connected"]="0";
  return settings;
}

bool SerialController::GetSetting(const string& name,string& str) const
{
  READ_CONTROLLER_SETTING(servAddr)
  READ_CONTROLLER_SETTING(writeRate)
  if(name=="connected") {
    if(controllerPipe)
      str = "1";
    else
      str = "0";
  }
  return false;
}

bool SerialController::SetSetting(const string& name,const string& str)
{
  if(name == "servAddr") {
    OpenConnection(str);
    return true;
  }
  WRITE_CONTROLLER_SETTING(writeRate)
  return false;
}

bool SerialController::OpenConnection(const string& addr)
{
  servAddr = addr;
  if(addr.empty()) {
    CloseConnection();
    return true;
  }
  controllerPipe = new SocketPipeWorker(addr.c_str(),true);
  if(!controllerPipe->Start()) {
    cout<<"Controller could not be opened on address "<<addr<<endl;
    return false;
  }
  return true;
}

bool SerialController::CloseConnection()
{
  if(controllerPipe) {
    controllerPipe->Stop();
    controllerPipe = NULL;
    return true;
  }
  return false;
}
<|endoftext|>


<commit_before>#ifndef SURFACE_H
#define SURFACE_H
#include "scene.hpp"
#include "ray.hpp"

#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
#include <cairo/cairo.h>
#include <cairo/cairo-xlib.h>

#include <vector>

class Surface {
    Scene& scene;
    int width;
    int height;
    bool rendered;
    cairo_surface_t* cairo_surface;
    cairo_t* cr;
    Display *dsp;
    std::vector<std::vector<Color> > buffer;

public:
    Ray get_ray(int x, int y) {
        return scene.get_ray((x - width/2.0) / width, (y - height/2.0) / width);
    }

    std::pair<int, int> get_coord(Point p) {
        auto pair = scene.get_coord(p);
        return {(pair.first*width + width)/2, (pair.second*width + height)/2};
    }

    void draw_pixel(int x, int y, Color c) {
        cairo_set_source_rgb(cr, c.x, c.y, c.z);
        cairo_rectangle(cr, x, y, 1, 1);
        cairo_fill(cr);
    }

    void enchance_balance() {
        double factor = -INFINITY;
        for (int x = 0; x < width; ++x) {
            for (int y = 0; y < height; ++y) {
                for (int comp = 0; comp < 3; ++comp) {
                    double cur = buffer[x][y].coord[comp];
                    if (cur > factor) {
                        factor = cur;
                    }
                }
            }
        }
        if (almost_zero(factor)) {
            return;
        }
        for (int x = 0; x < width; ++x) {
            for (int y = 0; y < height; ++y) {
                buffer[x][y] /= factor;
            }
        }
    };

    void render() {
        if (width == 0 || rendered) {
            printf("skip");
            return;
        }
        printf("(%i %i)\n", width, height);
        buffer = std::vector<std::vector<Color> >(width, std::vector<Color>(height));
        for (int x = 0; x < width; ++x) {
            for (int y = 0; y < height; ++y) {
                Color c = scene.trace_ray(get_ray(x, y));
                buffer[x][y] = c;
            }
        }
        enchance_balance();
        rendered = true;
    }

    void draw() {
        printf("draw");
        for (int x = 0; x < width; ++x) {
            for (int y = 0; y < height; ++y) {
                draw_pixel(x, y, buffer[x][y]);
            }
        }
    }

    Surface(Scene& scene, int width = 0, int height = 0) : scene(scene), width(width), height(height), rendered(false) {
        Drawable da;
        Screen *scr;
        int screen;
        cairo_surface_t *sfc;

        if ((dsp = XOpenDisplay(NULL)) == NULL) {
            exit(1);
        }
        screen = DefaultScreen(dsp);
        scr = DefaultScreenOfDisplay(dsp);
        width = WidthOfScreen(scr), height = HeightOfScreen(scr);
        da = XCreateSimpleWindow(dsp, DefaultRootWindow(dsp), 0, 0, width, height, 0, 0, 0);
        XSelectInput(dsp, da, ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask);
        XMapWindow(dsp, da);
        sfc = cairo_xlib_surface_create(dsp, da, DefaultVisual(dsp, screen), width, height);
        cairo_xlib_surface_set_size(sfc, width, height);

        cairo_surface = sfc;
        cr = cairo_create(sfc);
        render();
    }

    void event_loop() {
        double angle = 0;
        while (1)  {
            XEvent report;
            XNextEvent(dsp, &report);
            switch  (report.type) {
                case Expose:
                    if (report.xexpose.count != 0) {
                        break;
                    }
                    render();
                    draw();
                    break;
                case ConfigureNotify:
                    /* Window has been resized; change width
                     * and height to send to place_text and
                     * place_graphics in next Expose */
                    if (width == report.xconfigure.width && height == report.xconfigure.height) {
                        break;
                    }
                    width = report.xconfigure.width;
                    height = report.xconfigure.height;
                    render();
                    draw();
                    break;
                case ButtonPress:
                case KeyPress:
                    printf("ok");
                    switch (report.xkey.keycode) {
                        case 113:
                            angle += 0.6;
                            break;
                        case 114:
                            angle -= 0.6;
                            break;
                        default:
                            continue;
                    }
                    scene.find_best_view(angle);
                    rendered = false;
                    render();
                    draw();
                default:
                    /* All events selected by StructureNotifyMask
                     * except ConfigureNotify are thrown away here,
                     * since nothing is done with them */
                    break;
            } /* End switch */
        }
    }

    ~Surface() {
        cairo_destroy(cr);
        cairo_surface_destroy(cairo_surface);
        XCloseDisplay(dsp);
    }
};
#endif
<commit_msg>add debug printfs<commit_after>#ifndef SURFACE_H
#define SURFACE_H
#include "scene.hpp"
#include "ray.hpp"

#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
#include <cairo/cairo.h>
#include <cairo/cairo-xlib.h>

#include <vector>

class Surface {
    Scene& scene;
    int width;
    int height;
    bool rendered;
    cairo_surface_t* cairo_surface;
    cairo_t* cr;
    Display *dsp;
    std::vector<std::vector<Color> > buffer;

public:
    Ray get_ray(int x, int y) {
        return scene.get_ray((x - width/2.0) / width, (y - height/2.0) / width);
    }

    std::pair<int, int> get_coord(Point p) {
        auto pair = scene.get_coord(p);
        return {(pair.first*width + width)/2, (pair.second*width + height)/2};
    }

    void draw_pixel(int x, int y, Color c) {
        cairo_set_source_rgb(cr, c.x, c.y, c.z);
        cairo_rectangle(cr, x, y, 1, 1);
        cairo_fill(cr);
    }

    void enchance_balance() {
        double factor = -INFINITY;
        for (int x = 0; x < width; ++x) {
            for (int y = 0; y < height; ++y) {
                for (int comp = 0; comp < 3; ++comp) {
                    double cur = buffer[x][y].coord[comp];
                    if (cur > factor) {
                        factor = cur;
                    }
                }
            }
        }
        if (almost_zero(factor)) {
            return;
        }
        for (int x = 0; x < width; ++x) {
            for (int y = 0; y < height; ++y) {
                buffer[x][y] /= factor;
            }
        }
    };

    void render() {
        if (width == 0 || rendered) {
            return;
        }
        buffer = std::vector<std::vector<Color> >(width, std::vector<Color>(height));
        for (int x = 0; x < width; ++x) {
            for (int y = 0; y < height; ++y) {
                Color c = scene.trace_ray(get_ray(x, y));
                buffer[x][y] = c;
            }
        }
        enchance_balance();
        rendered = true;
    }

    void draw() {
        for (int x = 0; x < width; ++x) {
            for (int y = 0; y < height; ++y) {
                draw_pixel(x, y, buffer[x][y]);
            }
        }
    }

    Surface(Scene& scene, int width = 0, int height = 0) : scene(scene), width(width), height(height), rendered(false) {
        Drawable da;
        Screen *scr;
        int screen;
        cairo_surface_t *sfc;

        if ((dsp = XOpenDisplay(NULL)) == NULL) {
            exit(1);
        }
        screen = DefaultScreen(dsp);
        scr = DefaultScreenOfDisplay(dsp);
        width = WidthOfScreen(scr), height = HeightOfScreen(scr);
        da = XCreateSimpleWindow(dsp, DefaultRootWindow(dsp), 0, 0, width, height, 0, 0, 0);
        XSelectInput(dsp, da, ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask);
        XMapWindow(dsp, da);
        sfc = cairo_xlib_surface_create(dsp, da, DefaultVisual(dsp, screen), width, height);
        cairo_xlib_surface_set_size(sfc, width, height);

        cairo_surface = sfc;
        cr = cairo_create(sfc);
        render();
    }

    void event_loop() {
        double angle = 0;
        while (1)  {
            XEvent report;
            XNextEvent(dsp, &report);
            switch  (report.type) {
                case Expose:
                    if (report.xexpose.count != 0) {
                        break;
                    }
                    render();
                    draw();
                    break;
                case ConfigureNotify:
                    /* Window has been resized; change width
                     * and height to send to place_text and
                     * place_graphics in next Expose */
                    if (width == report.xconfigure.width && height == report.xconfigure.height) {
                        break;
                    }
                    width = report.xconfigure.width;
                    height = report.xconfigure.height;
                    render();
                    draw();
                    break;
                case ButtonPress:
                case KeyPress:
                    switch (report.xkey.keycode) {
                        case 113:
                            angle += 0.6;
                            break;
                        case 114:
                            angle -= 0.6;
                            break;
                        default:
                            continue;
                    }
                    scene.find_best_view(angle);
                    rendered = false;
                    render();
                    draw();
                default:
                    /* All events selected by StructureNotifyMask
                     * except ConfigureNotify are thrown away here,
                     * since nothing is done with them */
                    break;
            } /* End switch */
        }
    }

    ~Surface() {
        cairo_destroy(cr);
        cairo_surface_destroy(cairo_surface);
        XCloseDisplay(dsp);
    }
};
#endif
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2016 ArangoDB GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
////////////////////////////////////////////////////////////////////////////////

#include "SupervisorFeature.h"

#include "ApplicationFeatures/DaemonFeature.h"
#include "Basics/ArangoGlobalContext.h"
#include "Logger/LoggerFeature.h"
#include "ProgramOptions/ProgramOptions.h"
#include "ProgramOptions/Section.h"

using namespace arangodb;
using namespace arangodb::application_features;
using namespace arangodb::basics;
using namespace arangodb::options;

static bool DONE = false;
static int CLIENT_PID = false;

static void StopHandler(int) {
  LOG_TOPIC(INFO, Logger::STARTUP) << "received SIGINT for supervisor; commanding client [" << CLIENT_PID << "] to shut down.";
  int rc = kill(CLIENT_PID, SIGTERM);
  if (rc < 0) {
    LOG_TOPIC(ERR, Logger::STARTUP) << "commanding client [" << CLIENT_PID << "] to shut down failed: [" << errno << "] " << strerror(errno);
  }
  DONE = true;
}

SupervisorFeature::SupervisorFeature(
    application_features::ApplicationServer* server)
    : ApplicationFeature(server, "Supervisor"), _supervisor(false), _clientPid(0) {
  setOptional(true);
  requiresElevatedPrivileges(false);
  startsAfter("Daemon");
  startsAfter("Logger");
  startsAfter("WorkMonitor");
}

void SupervisorFeature::collectOptions(
    std::shared_ptr<ProgramOptions> options) {
  options->addHiddenOption("--supervisor",
                           "background the server, starts a supervisor",
                           new BooleanParameter(&_supervisor));
}

void SupervisorFeature::validateOptions(
    std::shared_ptr<ProgramOptions> options) {
  if (_supervisor) {
    try {
      DaemonFeature* daemon = ApplicationServer::getFeature<DaemonFeature>("Daemon");

      // force daemon mode
      daemon->setDaemon(true);

      // revalidate options
      daemon->validateOptions(options);
    } catch (...) {
      LOG(FATAL) << "daemon mode not available, cannot start supervisor";
      FATAL_ERROR_EXIT();
    }
  }
}

void SupervisorFeature::daemonize() {
  static time_t const MIN_TIME_ALIVE_IN_SEC = 30;

  if (!_supervisor) {
    return;
  }

  time_t startTime = time(0);
  time_t t;
  bool done = false;
  int result = EXIT_SUCCESS;

  // will be reseted in SchedulerFeature
  ArangoGlobalContext::CONTEXT->unmaskStandardSignals();

  LoggerFeature* logger = nullptr;

  try {
    logger = ApplicationServer::getFeature<LoggerFeature>("Logger");
  } catch (...) {
    LOG_TOPIC(FATAL, Logger::STARTUP)
      << "unknown feature 'Logger', giving up";
    FATAL_ERROR_EXIT();
  }

  logger->setSupervisor(true);
  logger->prepare();

  LOG_TOPIC(DEBUG, Logger::STARTUP) << "starting supervisor loop";

  while (!done) {
    logger->setSupervisor(false);

    signal(SIGINT, SIG_DFL);
    signal(SIGTERM, SIG_DFL);

    LOG_TOPIC(DEBUG, Logger::STARTUP) << "supervisor will now try to fork a new child process";

    // fork of the server
    _clientPid = fork();

    if (_clientPid < 0) {
      LOG_TOPIC(FATAL, Logger::STARTUP) << "fork failed, giving up";
      FATAL_ERROR_EXIT();
    }

    // parent (supervisor)
    if (0 < _clientPid) {
      signal(SIGINT, StopHandler);
      signal(SIGTERM, StopHandler);

      LOG_TOPIC(INFO, Logger::STARTUP) << "supervisor has forked a child process with pid " << _clientPid;

      TRI_SetProcessTitle("arangodb [supervisor]");

      LOG_TOPIC(DEBUG, Logger::STARTUP) << "supervisor mode: within parent";

      CLIENT_PID = _clientPid;
      DONE = false;

      int status;
      int res = waitpid(_clientPid, &status, 0);
      bool horrible = true;

      LOG_TOPIC(INFO, Logger::STARTUP) << "waitpid woke up with return value "
                                       << res << " and status " << status
                                       << " and DONE = " << (DONE ? "true" : "false");

      if (DONE) {
        // signal handler for SIGINT or SIGTERM was invoked
        done = true;
        horrible = false;
      }
      else {
        TRI_ASSERT(horrible);

        if (WIFEXITED(status)) {
          // give information about cause of death
          if (WEXITSTATUS(status) == 0) {
            LOG_TOPIC(INFO, Logger::STARTUP) << "child " << _clientPid
                                             << " died of natural causes";
            done = true;
            horrible = false;
          } else {
            t = time(0) - startTime;

            LOG_TOPIC(ERR, Logger::STARTUP)
                << "child " << _clientPid
                << " died a horrible death, exit status " << WEXITSTATUS(status);

            if (t < MIN_TIME_ALIVE_IN_SEC) {
              LOG_TOPIC(ERR, Logger::STARTUP)
                  << "child only survived for " << t
                  << " seconds, this will not work - please fix the error "
                     "first";
              done = true;
            } else {
              done = false;
            }
          }
        } else if (WIFSIGNALED(status)) {
          switch (WTERMSIG(status)) {
            case 2: // SIGINT
            case 9: // SIGKILL
            case 15: // SIGTERM
              LOG_TOPIC(INFO, Logger::STARTUP)
                  << "child " << _clientPid
                  << " died of natural causes, exit status " << WTERMSIG(status);
              done = true;
              horrible = false;
              break;

            default:
              TRI_ASSERT(horrible);
              t = time(0) - startTime;

              LOG_TOPIC(ERR, Logger::STARTUP) << "child " << _clientPid
                                              << " died a horrible death, signal "
                                              << WTERMSIG(status);

              if (t < MIN_TIME_ALIVE_IN_SEC) {
                LOG_TOPIC(ERR, Logger::STARTUP)
                    << "child only survived for " << t
                    << " seconds, this will not work - please fix the "
                       "error first";
                done = true;

#ifdef WCOREDUMP
                if (WCOREDUMP(status)) {
                  LOG_TOPIC(WARN, Logger::STARTUP) << "child process "
                                                   << _clientPid
                                                   << " produced a core dump";
                }
#endif
              } else {
                done = false;
              }

              break;
          }
        } else {
          LOG_TOPIC(ERR, Logger::STARTUP)
              << "child " << _clientPid
              << " died a horrible death, unknown cause";
          done = false;
        }
      }

      if (horrible) {
        result = EXIT_FAILURE;
      } else {
        result = EXIT_SUCCESS;
      }
    }

    // child - run the normal boot sequence
    else {
      Logger::shutdown();

      LOG_TOPIC(DEBUG, Logger::STARTUP) << "supervisor mode: within child";
      TRI_SetProcessTitle("arangodb [server]");

#ifdef TRI_HAVE_PRCTL
      // force child to stop if supervisor dies
      prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0);
#endif

      try {
        DaemonFeature* daemon = ApplicationServer::getFeature<DaemonFeature>("Daemon");

        // disable daemon mode
        daemon->setDaemon(false);
      } catch (...) {
      }

      return;
    }
  }

  LOG_TOPIC(DEBUG, Logger::STARTUP) << "supervisor mode: finished";

  Logger::flush();
  Logger::shutdown();

  exit(result);
}
<commit_msg>forward SIG_HUP from supervisor<commit_after>////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2016 ArangoDB GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
////////////////////////////////////////////////////////////////////////////////

#include "SupervisorFeature.h"

#include "ApplicationFeatures/DaemonFeature.h"
#include "Basics/ArangoGlobalContext.h"
#include "Logger/LoggerFeature.h"
#include "ProgramOptions/ProgramOptions.h"
#include "ProgramOptions/Section.h"

using namespace arangodb;
using namespace arangodb::application_features;
using namespace arangodb::basics;
using namespace arangodb::options;

static bool DONE = false;
static int CLIENT_PID = false;

static void StopHandler(int) {
  LOG_TOPIC(INFO, Logger::STARTUP) << "received SIGINT for supervisor; commanding client [" << CLIENT_PID << "] to shut down.";
  int rc = kill(CLIENT_PID, SIGTERM);
  if (rc < 0) {
    LOG_TOPIC(ERR, Logger::STARTUP) << "commanding client [" << CLIENT_PID << "] to shut down failed: [" << errno << "] " << strerror(errno);
  }
  DONE = true;
}

static void HUPHandler(int) {
  LOG_TOPIC(INFO, Logger::STARTUP) << "received SIGHUP for supervisor; commanding client [" << CLIENT_PID << "] to logrotate.";
  int rc = kill(CLIENT_PID, SIGHUP);
  if (rc < 0) {
    LOG_TOPIC(ERR, Logger::STARTUP) << "commanding client [" << CLIENT_PID << "] to logrotate failed: [" << errno << "] " << strerror(errno);
  }
}

SupervisorFeature::SupervisorFeature(
    application_features::ApplicationServer* server)
    : ApplicationFeature(server, "Supervisor"), _supervisor(false), _clientPid(0) {
  setOptional(true);
  requiresElevatedPrivileges(false);
  startsAfter("Daemon");
  startsAfter("Logger");
  startsAfter("WorkMonitor");
}

void SupervisorFeature::collectOptions(
    std::shared_ptr<ProgramOptions> options) {
  options->addHiddenOption("--supervisor",
                           "background the server, starts a supervisor",
                           new BooleanParameter(&_supervisor));
}

void SupervisorFeature::validateOptions(
    std::shared_ptr<ProgramOptions> options) {
  if (_supervisor) {
    try {
      DaemonFeature* daemon = ApplicationServer::getFeature<DaemonFeature>("Daemon");

      // force daemon mode
      daemon->setDaemon(true);

      // revalidate options
      daemon->validateOptions(options);
    } catch (...) {
      LOG(FATAL) << "daemon mode not available, cannot start supervisor";
      FATAL_ERROR_EXIT();
    }
  }
}

void SupervisorFeature::daemonize() {
  static time_t const MIN_TIME_ALIVE_IN_SEC = 30;

  if (!_supervisor) {
    return;
  }

  time_t startTime = time(0);
  time_t t;
  bool done = false;
  int result = EXIT_SUCCESS;

  // will be reseted in SchedulerFeature
  ArangoGlobalContext::CONTEXT->unmaskStandardSignals();

  LoggerFeature* logger = nullptr;

  try {
    logger = ApplicationServer::getFeature<LoggerFeature>("Logger");
  } catch (...) {
    LOG_TOPIC(FATAL, Logger::STARTUP)
      << "unknown feature 'Logger', giving up";
    FATAL_ERROR_EXIT();
  }

  logger->setSupervisor(true);
  logger->prepare();

  LOG_TOPIC(DEBUG, Logger::STARTUP) << "starting supervisor loop";

  while (!done) {
    logger->setSupervisor(false);

    signal(SIGINT, SIG_DFL);
    signal(SIGTERM, SIG_DFL);

    LOG_TOPIC(DEBUG, Logger::STARTUP) << "supervisor will now try to fork a new child process";

    // fork of the server
    _clientPid = fork();

    if (_clientPid < 0) {
      LOG_TOPIC(FATAL, Logger::STARTUP) << "fork failed, giving up";
      FATAL_ERROR_EXIT();
    }

    // parent (supervisor)
    if (0 < _clientPid) {
      signal(SIGINT, StopHandler);
      signal(SIGTERM, StopHandler);
      signal(SIGHUP, HUPHandler);

      LOG_TOPIC(INFO, Logger::STARTUP) << "supervisor has forked a child process with pid " << _clientPid;

      TRI_SetProcessTitle("arangodb [supervisor]");

      LOG_TOPIC(DEBUG, Logger::STARTUP) << "supervisor mode: within parent";

      CLIENT_PID = _clientPid;
      DONE = false;

      int status;
      int res = waitpid(_clientPid, &status, 0);
      bool horrible = true;

      LOG_TOPIC(INFO, Logger::STARTUP) << "waitpid woke up with return value "
                                       << res << " and status " << status
                                       << " and DONE = " << (DONE ? "true" : "false");

      if (DONE) {
        // signal handler for SIGINT or SIGTERM was invoked
        done = true;
        horrible = false;
      }
      else {
        TRI_ASSERT(horrible);

        if (WIFEXITED(status)) {
          // give information about cause of death
          if (WEXITSTATUS(status) == 0) {
            LOG_TOPIC(INFO, Logger::STARTUP) << "child " << _clientPid
                                             << " died of natural causes";
            done = true;
            horrible = false;
          } else {
            t = time(0) - startTime;

            LOG_TOPIC(ERR, Logger::STARTUP)
                << "child " << _clientPid
                << " died a horrible death, exit status " << WEXITSTATUS(status);

            if (t < MIN_TIME_ALIVE_IN_SEC) {
              LOG_TOPIC(ERR, Logger::STARTUP)
                  << "child only survived for " << t
                  << " seconds, this will not work - please fix the error "
                     "first";
              done = true;
            } else {
              done = false;
            }
          }
        } else if (WIFSIGNALED(status)) {
          switch (WTERMSIG(status)) {
            case 2: // SIGINT
            case 9: // SIGKILL
            case 15: // SIGTERM
              LOG_TOPIC(INFO, Logger::STARTUP)
                  << "child " << _clientPid
                  << " died of natural causes, exit status " << WTERMSIG(status);
              done = true;
              horrible = false;
              break;

            default:
              TRI_ASSERT(horrible);
              t = time(0) - startTime;

              LOG_TOPIC(ERR, Logger::STARTUP) << "child " << _clientPid
                                              << " died a horrible death, signal "
                                              << WTERMSIG(status);

              if (t < MIN_TIME_ALIVE_IN_SEC) {
                LOG_TOPIC(ERR, Logger::STARTUP)
                    << "child only survived for " << t
                    << " seconds, this will not work - please fix the "
                       "error first";
                done = true;

#ifdef WCOREDUMP
                if (WCOREDUMP(status)) {
                  LOG_TOPIC(WARN, Logger::STARTUP) << "child process "
                                                   << _clientPid
                                                   << " produced a core dump";
                }
#endif
              } else {
                done = false;
              }

              break;
          }
        } else {
          LOG_TOPIC(ERR, Logger::STARTUP)
              << "child " << _clientPid
              << " died a horrible death, unknown cause";
          done = false;
        }
      }

      if (horrible) {
        result = EXIT_FAILURE;
      } else {
        result = EXIT_SUCCESS;
      }
    }

    // child - run the normal boot sequence
    else {
      Logger::shutdown();

      LOG_TOPIC(DEBUG, Logger::STARTUP) << "supervisor mode: within child";
      TRI_SetProcessTitle("arangodb [server]");

#ifdef TRI_HAVE_PRCTL
      // force child to stop if supervisor dies
      prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0);
#endif

      try {
        DaemonFeature* daemon = ApplicationServer::getFeature<DaemonFeature>("Daemon");

        // disable daemon mode
        daemon->setDaemon(false);
      } catch (...) {
      }

      return;
    }
  }

  LOG_TOPIC(DEBUG, Logger::STARTUP) << "supervisor mode: finished";

  Logger::flush();
  Logger::shutdown();

  exit(result);
}
<|endoftext|>


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

//_________________________________________________________________________________________________________________
//  includes
//_________________________________________________________________________________________________________________

#include "workingsetoptions.hxx"

#ifndef _UTL_CONFIGMGR_HXX_
#include <unotools/configmgr.hxx>
#endif

#ifndef _UTL_CONFIGITEM_HXX_
#include <unotools/configitem.hxx>
#endif

#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif

#ifndef _COM_SUN_STAR_UNO_ANY_HXX_
#include <com/sun/star/uno/Any.hxx>
#endif

#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#include <com/sun/star/uno/Sequence.hxx>
#endif

#include <itemholder1.hxx>

//_________________________________________________________________________________________________________________
//  namespaces
//_________________________________________________________________________________________________________________

using namespace ::utl                   ;
using namespace ::rtl                   ;
using namespace ::osl                   ;
using namespace ::com::sun::star::uno   ;

//_________________________________________________________________________________________________________________
//  const
//_________________________________________________________________________________________________________________

#define ROOTNODE_WORKINGSET             OUString(RTL_CONSTASCII_USTRINGPARAM("Office.Common/WorkingSet"))
#define DEFAULT_WINDOWLIST              Sequence< OUString >()

#define PROPERTYNAME_WINDOWLIST         OUString(RTL_CONSTASCII_USTRINGPARAM("WindowList"       ))

#define PROPERTYHANDLE_WINDOWLIST       0

#define PROPERTYCOUNT                   1

//_________________________________________________________________________________________________________________
//  private declarations!
//_________________________________________________________________________________________________________________

class SvtWorkingSetOptions_Impl : public ConfigItem
{
    //-------------------------------------------------------------------------------------------------------------
    //  public methods
    //-------------------------------------------------------------------------------------------------------------

    public:

        //---------------------------------------------------------------------------------------------------------
        //  constructor / destructor
        //---------------------------------------------------------------------------------------------------------

         SvtWorkingSetOptions_Impl();
        ~SvtWorkingSetOptions_Impl();

        //---------------------------------------------------------------------------------------------------------
        //  overloaded methods of baseclass
        //---------------------------------------------------------------------------------------------------------

        /*-****************************************************************************************************//**
            @short      called for notify of configmanager
            @descr      These method is called from the ConfigManager before application ends or from the
                         PropertyChangeListener if the sub tree broadcasts changes. You must update your
                        internal values.

            @seealso    baseclass ConfigItem

            @param      "seqPropertyNames" is the list of properties which should be updated.
            @return     -

            @onerror    -
        *//*-*****************************************************************************************************/

        virtual void Notify( const Sequence< OUString >& seqPropertyNames );

        /*-****************************************************************************************************//**
            @short      write changes to configuration
            @descr      These method writes the changed values into the sub tree
                        and should always called in our destructor to guarantee consistency of config data.

            @seealso    baseclass ConfigItem

            @param      -
            @return     -

            @onerror    -
        *//*-*****************************************************************************************************/

        virtual void Commit();

        //---------------------------------------------------------------------------------------------------------
        //  public interface
        //---------------------------------------------------------------------------------------------------------

        /*-****************************************************************************************************//**
            @short      access method to get internal values
            @descr      These method give us a chance to regulate acces to ouer internal values.
                        It's not used in the moment - but it's possible for the feature!

            @seealso    -

            @param      -
            @return     -

            @onerror    -
        *//*-*****************************************************************************************************/

        Sequence< OUString >    GetWindowList(                                              ) const ;
        void                    SetWindowList( const Sequence< OUString >&  seqWindowList   )       ;

    //-------------------------------------------------------------------------------------------------------------
    //  private methods
    //-------------------------------------------------------------------------------------------------------------

    private:

        /*-****************************************************************************************************//**
            @short      return list of key names of ouer configuration management which represent oue module tree
            @descr      These methods return a static const list of key names. We need it to get needed values from our
                        configuration management.

            @seealso    -

            @param      -
            @return     A list of needed configuration keys is returned.

            @onerror    -
        *//*-*****************************************************************************************************/

        static Sequence< OUString > GetPropertyNames();

    //-------------------------------------------------------------------------------------------------------------
    //  private member
    //-------------------------------------------------------------------------------------------------------------

    private:

        Sequence< OUString >    m_seqWindowList     ;
};

//_________________________________________________________________________________________________________________
//  definitions
//_________________________________________________________________________________________________________________

//*****************************************************************************************************************
//  constructor
//*****************************************************************************************************************
SvtWorkingSetOptions_Impl::SvtWorkingSetOptions_Impl()
    // Init baseclasses first
    :   ConfigItem          ( ROOTNODE_WORKINGSET   )
    // Init member then.
    ,   m_seqWindowList     ( DEFAULT_WINDOWLIST    )
{
    // Use our static list of configuration keys to get his values.
    Sequence< OUString >    seqNames    = GetPropertyNames  (           );
    Sequence< Any >         seqValues   = GetProperties     ( seqNames  );

    // Safe impossible cases.
    // We need values from ALL configuration keys.
    // Follow assignment use order of values in relation to our list of key names!
    DBG_ASSERT( !(seqNames.getLength()!=seqValues.getLength()), "SvtWorkingSetOptions_Impl::SvtWorkingSetOptions_Impl()\nI miss some values of configuration keys!\n" );

    // Copy values from list in right order to ouer internal member.
    sal_Int32 nPropertyCount = seqValues.getLength();
    for( sal_Int32 nProperty=0; nProperty<nPropertyCount; ++nProperty )
    {
        // Safe impossible cases.
        // Check any for valid value.
        DBG_ASSERT( !(seqValues[nProperty].hasValue()==sal_False), "SvtWorkingSetOptions_Impl::SvtWorkingSetOptions_Impl()\nInvalid property value detected!\n" );
        switch( nProperty )
        {
            case PROPERTYHANDLE_WINDOWLIST      :   {
                                                        DBG_ASSERT(!(seqValues[nProperty].getValueTypeClass()!=TypeClass_SEQUENCE), "SvtWorkingSetOptions_Impl::SvtWorkingSetOptions_Impl()\nWho has changed the value type of \"Office.Common\\WorkingSet\\WindowList\"?" );
                                                        seqValues[nProperty] >>= m_seqWindowList;
                                                    }
                                                    break;
        }
    }

    // Enable notification mechanism of ouer baseclass.
    // We need it to get information about changes outside these class on ouer used configuration keys!
    EnableNotification( seqNames );
}

//*****************************************************************************************************************
//  destructor
//*****************************************************************************************************************
SvtWorkingSetOptions_Impl::~SvtWorkingSetOptions_Impl()
{
    // We must save our current values .. if user forget it!
    if( IsModified() == sal_True )
    {
        Commit();
    }
}

//*****************************************************************************************************************
//  public method
//*****************************************************************************************************************
void SvtWorkingSetOptions_Impl::Notify( const Sequence< OUString >& seqPropertyNames )
{
    // Use given list of updated properties to get his values from configuration directly!
    Sequence< Any > seqValues = GetProperties( seqPropertyNames );
    // Safe impossible cases.
    // We need values from ALL notified configuration keys.
    DBG_ASSERT( !(seqPropertyNames.getLength()!=seqValues.getLength()), "SvtWorkingSetOptions_Impl::Notify()\nI miss some values of configuration keys!\n" );
    // Step over list of property names and get right value from coreesponding value list to set it on internal members!
    sal_Int32 nCount = seqPropertyNames.getLength();
    for( sal_Int32 nProperty=0; nProperty<nCount; ++nProperty )
    {
        if( seqPropertyNames[nProperty] == PROPERTYNAME_WINDOWLIST )
        {
            DBG_ASSERT(!(seqValues[nProperty].getValueTypeClass()!=TypeClass_SEQUENCE), "SvtWorkingSetOptions_Impl::Notify()\nWho has changed the value type of \"Office.Common\\WorkingSet\\WindowList\"?" );
            seqValues[nProperty] >>= m_seqWindowList;
        }
        #if OSL_DEBUG_LEVEL > 1
        else DBG_ASSERT( sal_False, "SvtWorkingSetOptions_Impl::Notify()\nUnkown property detected ... I can't handle these!\n" );
        #endif
    }
}

//*****************************************************************************************************************
//  public method
//*****************************************************************************************************************
void SvtWorkingSetOptions_Impl::Commit()
{
    // Get names of supported properties, create a list for values and copy current values to it.
    Sequence< OUString >    seqNames    = GetPropertyNames  ();
    sal_Int32               nCount      = seqNames.getLength();
    Sequence< Any >         seqValues   ( nCount );
    for( sal_Int32 nProperty=0; nProperty<nCount; ++nProperty )
    {
        switch( nProperty )
        {
            case PROPERTYHANDLE_WINDOWLIST      :   {
                                                        seqValues[nProperty] <<= m_seqWindowList;
                                                    }
                                                    break;
        }
    }
    // Set properties in configuration.
    PutProperties( seqNames, seqValues );
}

//*****************************************************************************************************************
//  public method
//*****************************************************************************************************************
Sequence< OUString > SvtWorkingSetOptions_Impl::GetWindowList() const
{
    return m_seqWindowList;
}

//*****************************************************************************************************************
//  public method
//*****************************************************************************************************************
void SvtWorkingSetOptions_Impl::SetWindowList( const Sequence< OUString >& seqWindowList )
{
    m_seqWindowList = seqWindowList;
    SetModified();
}

//*****************************************************************************************************************
//  private method
//*****************************************************************************************************************
Sequence< OUString > SvtWorkingSetOptions_Impl::GetPropertyNames()
{
    // Build static list of configuration key names.
    static const OUString pProperties[] =
    {
        PROPERTYNAME_WINDOWLIST ,
    };
    // Initialize return sequence with these list ...
    static const Sequence< OUString > seqPropertyNames( pProperties, PROPERTYCOUNT );
    // ... and return it.
    return seqPropertyNames;
}

//*****************************************************************************************************************
//  initialize static member
//  DON'T DO IT IN YOUR HEADER!
//  see definition for further informations
//*****************************************************************************************************************
SvtWorkingSetOptions_Impl*  SvtWorkingSetOptions::m_pDataContainer  = NULL  ;
sal_Int32                   SvtWorkingSetOptions::m_nRefCount       = 0     ;

//*****************************************************************************************************************
//  constructor
//*****************************************************************************************************************
SvtWorkingSetOptions::SvtWorkingSetOptions()
{
    // Global access, must be guarded (multithreading!).
    MutexGuard aGuard( GetOwnStaticMutex() );
    // Increase ouer refcount ...
    ++m_nRefCount;
    // ... and initialize ouer data container only if it not already exist!
    if( m_pDataContainer == NULL )
    {
        m_pDataContainer = new SvtWorkingSetOptions_Impl;
        ItemHolder1::holdConfigItem(E_WORKINGSETOPTIONS);
    }
}

//*****************************************************************************************************************
//  destructor
//*****************************************************************************************************************
SvtWorkingSetOptions::~SvtWorkingSetOptions()
{
    // Global access, must be guarded (multithreading!)
    MutexGuard aGuard( GetOwnStaticMutex() );
    // Decrease ouer refcount.
    --m_nRefCount;
    // If last instance was deleted ...
    // we must destroy ouer static data container!
    if( m_nRefCount <= 0 )
    {
        delete m_pDataContainer;
        m_pDataContainer = NULL;
    }
}

//*****************************************************************************************************************
//  public method
//*****************************************************************************************************************
Sequence< OUString > SvtWorkingSetOptions::GetWindowList() const
{
    MutexGuard aGuard( GetOwnStaticMutex() );
    return m_pDataContainer->GetWindowList();
}

//*****************************************************************************************************************
//  public method
//*****************************************************************************************************************
void SvtWorkingSetOptions::SetWindowList( const Sequence< OUString >& seqWindowList )
{
    MutexGuard aGuard( GetOwnStaticMutex() );
    m_pDataContainer->SetWindowList( seqWindowList );
}

//*****************************************************************************************************************
//  private method
//*****************************************************************************************************************
Mutex& SvtWorkingSetOptions::GetOwnStaticMutex()
{
    // Initialize static mutex only for one time!
    static Mutex* pMutex = NULL;
    // If these method first called (Mutex not already exist!) ...
    if( pMutex == NULL )
    {
        // ... we must create a new one. Protect follow code with the global mutex -
        // It must be - we create a static variable!
        MutexGuard aGuard( Mutex::getGlobalMutex() );
        // We must check our pointer again - because it can be that another instance of ouer class will be fastr then these!
        if( pMutex == NULL )
        {
            // Create the new mutex and set it for return on static variable.
            static Mutex aMutex;
            pMutex = &aMutex;
        }
    }
    // Return new created or already existing mutex object.
    return *pMutex;
}
<commit_msg>INTEGRATION: CWS pchfix02 (1.7.276); FILE MERGED 2006/09/01 17:42:51 kaib 1.7.276.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: workingsetoptions.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 14:31:20 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svtools.hxx"
#ifndef GCC
#endif

//_________________________________________________________________________________________________________________
//  includes
//_________________________________________________________________________________________________________________

#include "workingsetoptions.hxx"

#ifndef _UTL_CONFIGMGR_HXX_
#include <unotools/configmgr.hxx>
#endif

#ifndef _UTL_CONFIGITEM_HXX_
#include <unotools/configitem.hxx>
#endif

#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif

#ifndef _COM_SUN_STAR_UNO_ANY_HXX_
#include <com/sun/star/uno/Any.hxx>
#endif

#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#include <com/sun/star/uno/Sequence.hxx>
#endif

#include <itemholder1.hxx>

//_________________________________________________________________________________________________________________
//  namespaces
//_________________________________________________________________________________________________________________

using namespace ::utl                   ;
using namespace ::rtl                   ;
using namespace ::osl                   ;
using namespace ::com::sun::star::uno   ;

//_________________________________________________________________________________________________________________
//  const
//_________________________________________________________________________________________________________________

#define ROOTNODE_WORKINGSET             OUString(RTL_CONSTASCII_USTRINGPARAM("Office.Common/WorkingSet"))
#define DEFAULT_WINDOWLIST              Sequence< OUString >()

#define PROPERTYNAME_WINDOWLIST         OUString(RTL_CONSTASCII_USTRINGPARAM("WindowList"       ))

#define PROPERTYHANDLE_WINDOWLIST       0

#define PROPERTYCOUNT                   1

//_________________________________________________________________________________________________________________
//  private declarations!
//_________________________________________________________________________________________________________________

class SvtWorkingSetOptions_Impl : public ConfigItem
{
    //-------------------------------------------------------------------------------------------------------------
    //  public methods
    //-------------------------------------------------------------------------------------------------------------

    public:

        //---------------------------------------------------------------------------------------------------------
        //  constructor / destructor
        //---------------------------------------------------------------------------------------------------------

         SvtWorkingSetOptions_Impl();
        ~SvtWorkingSetOptions_Impl();

        //---------------------------------------------------------------------------------------------------------
        //  overloaded methods of baseclass
        //---------------------------------------------------------------------------------------------------------

        /*-****************************************************************************************************//**
            @short      called for notify of configmanager
            @descr      These method is called from the ConfigManager before application ends or from the
                         PropertyChangeListener if the sub tree broadcasts changes. You must update your
                        internal values.

            @seealso    baseclass ConfigItem

            @param      "seqPropertyNames" is the list of properties which should be updated.
            @return     -

            @onerror    -
        *//*-*****************************************************************************************************/

        virtual void Notify( const Sequence< OUString >& seqPropertyNames );

        /*-****************************************************************************************************//**
            @short      write changes to configuration
            @descr      These method writes the changed values into the sub tree
                        and should always called in our destructor to guarantee consistency of config data.

            @seealso    baseclass ConfigItem

            @param      -
            @return     -

            @onerror    -
        *//*-*****************************************************************************************************/

        virtual void Commit();

        //---------------------------------------------------------------------------------------------------------
        //  public interface
        //---------------------------------------------------------------------------------------------------------

        /*-****************************************************************************************************//**
            @short      access method to get internal values
            @descr      These method give us a chance to regulate acces to ouer internal values.
                        It's not used in the moment - but it's possible for the feature!

            @seealso    -

            @param      -
            @return     -

            @onerror    -
        *//*-*****************************************************************************************************/

        Sequence< OUString >    GetWindowList(                                              ) const ;
        void                    SetWindowList( const Sequence< OUString >&  seqWindowList   )       ;

    //-------------------------------------------------------------------------------------------------------------
    //  private methods
    //-------------------------------------------------------------------------------------------------------------

    private:

        /*-****************************************************************************************************//**
            @short      return list of key names of ouer configuration management which represent oue module tree
            @descr      These methods return a static const list of key names. We need it to get needed values from our
                        configuration management.

            @seealso    -

            @param      -
            @return     A list of needed configuration keys is returned.

            @onerror    -
        *//*-*****************************************************************************************************/

        static Sequence< OUString > GetPropertyNames();

    //-------------------------------------------------------------------------------------------------------------
    //  private member
    //-------------------------------------------------------------------------------------------------------------

    private:

        Sequence< OUString >    m_seqWindowList     ;
};

//_________________________________________________________________________________________________________________
//  definitions
//_________________________________________________________________________________________________________________

//*****************************************************************************************************************
//  constructor
//*****************************************************************************************************************
SvtWorkingSetOptions_Impl::SvtWorkingSetOptions_Impl()
    // Init baseclasses first
    :   ConfigItem          ( ROOTNODE_WORKINGSET   )
    // Init member then.
    ,   m_seqWindowList     ( DEFAULT_WINDOWLIST    )
{
    // Use our static list of configuration keys to get his values.
    Sequence< OUString >    seqNames    = GetPropertyNames  (           );
    Sequence< Any >         seqValues   = GetProperties     ( seqNames  );

    // Safe impossible cases.
    // We need values from ALL configuration keys.
    // Follow assignment use order of values in relation to our list of key names!
    DBG_ASSERT( !(seqNames.getLength()!=seqValues.getLength()), "SvtWorkingSetOptions_Impl::SvtWorkingSetOptions_Impl()\nI miss some values of configuration keys!\n" );

    // Copy values from list in right order to ouer internal member.
    sal_Int32 nPropertyCount = seqValues.getLength();
    for( sal_Int32 nProperty=0; nProperty<nPropertyCount; ++nProperty )
    {
        // Safe impossible cases.
        // Check any for valid value.
        DBG_ASSERT( !(seqValues[nProperty].hasValue()==sal_False), "SvtWorkingSetOptions_Impl::SvtWorkingSetOptions_Impl()\nInvalid property value detected!\n" );
        switch( nProperty )
        {
            case PROPERTYHANDLE_WINDOWLIST      :   {
                                                        DBG_ASSERT(!(seqValues[nProperty].getValueTypeClass()!=TypeClass_SEQUENCE), "SvtWorkingSetOptions_Impl::SvtWorkingSetOptions_Impl()\nWho has changed the value type of \"Office.Common\\WorkingSet\\WindowList\"?" );
                                                        seqValues[nProperty] >>= m_seqWindowList;
                                                    }
                                                    break;
        }
    }

    // Enable notification mechanism of ouer baseclass.
    // We need it to get information about changes outside these class on ouer used configuration keys!
    EnableNotification( seqNames );
}

//*****************************************************************************************************************
//  destructor
//*****************************************************************************************************************
SvtWorkingSetOptions_Impl::~SvtWorkingSetOptions_Impl()
{
    // We must save our current values .. if user forget it!
    if( IsModified() == sal_True )
    {
        Commit();
    }
}

//*****************************************************************************************************************
//  public method
//*****************************************************************************************************************
void SvtWorkingSetOptions_Impl::Notify( const Sequence< OUString >& seqPropertyNames )
{
    // Use given list of updated properties to get his values from configuration directly!
    Sequence< Any > seqValues = GetProperties( seqPropertyNames );
    // Safe impossible cases.
    // We need values from ALL notified configuration keys.
    DBG_ASSERT( !(seqPropertyNames.getLength()!=seqValues.getLength()), "SvtWorkingSetOptions_Impl::Notify()\nI miss some values of configuration keys!\n" );
    // Step over list of property names and get right value from coreesponding value list to set it on internal members!
    sal_Int32 nCount = seqPropertyNames.getLength();
    for( sal_Int32 nProperty=0; nProperty<nCount; ++nProperty )
    {
        if( seqPropertyNames[nProperty] == PROPERTYNAME_WINDOWLIST )
        {
            DBG_ASSERT(!(seqValues[nProperty].getValueTypeClass()!=TypeClass_SEQUENCE), "SvtWorkingSetOptions_Impl::Notify()\nWho has changed the value type of \"Office.Common\\WorkingSet\\WindowList\"?" );
            seqValues[nProperty] >>= m_seqWindowList;
        }
        #if OSL_DEBUG_LEVEL > 1
        else DBG_ASSERT( sal_False, "SvtWorkingSetOptions_Impl::Notify()\nUnkown property detected ... I can't handle these!\n" );
        #endif
    }
}

//*****************************************************************************************************************
//  public method
//*****************************************************************************************************************
void SvtWorkingSetOptions_Impl::Commit()
{
    // Get names of supported properties, create a list for values and copy current values to it.
    Sequence< OUString >    seqNames    = GetPropertyNames  ();
    sal_Int32               nCount      = seqNames.getLength();
    Sequence< Any >         seqValues   ( nCount );
    for( sal_Int32 nProperty=0; nProperty<nCount; ++nProperty )
    {
        switch( nProperty )
        {
            case PROPERTYHANDLE_WINDOWLIST      :   {
                                                        seqValues[nProperty] <<= m_seqWindowList;
                                                    }
                                                    break;
        }
    }
    // Set properties in configuration.
    PutProperties( seqNames, seqValues );
}

//*****************************************************************************************************************
//  public method
//*****************************************************************************************************************
Sequence< OUString > SvtWorkingSetOptions_Impl::GetWindowList() const
{
    return m_seqWindowList;
}

//*****************************************************************************************************************
//  public method
//*****************************************************************************************************************
void SvtWorkingSetOptions_Impl::SetWindowList( const Sequence< OUString >& seqWindowList )
{
    m_seqWindowList = seqWindowList;
    SetModified();
}

//*****************************************************************************************************************
//  private method
//*****************************************************************************************************************
Sequence< OUString > SvtWorkingSetOptions_Impl::GetPropertyNames()
{
    // Build static list of configuration key names.
    static const OUString pProperties[] =
    {
        PROPERTYNAME_WINDOWLIST ,
    };
    // Initialize return sequence with these list ...
    static const Sequence< OUString > seqPropertyNames( pProperties, PROPERTYCOUNT );
    // ... and return it.
    return seqPropertyNames;
}

//*****************************************************************************************************************
//  initialize static member
//  DON'T DO IT IN YOUR HEADER!
//  see definition for further informations
//*****************************************************************************************************************
SvtWorkingSetOptions_Impl*  SvtWorkingSetOptions::m_pDataContainer  = NULL  ;
sal_Int32                   SvtWorkingSetOptions::m_nRefCount       = 0     ;

//*****************************************************************************************************************
//  constructor
//*****************************************************************************************************************
SvtWorkingSetOptions::SvtWorkingSetOptions()
{
    // Global access, must be guarded (multithreading!).
    MutexGuard aGuard( GetOwnStaticMutex() );
    // Increase ouer refcount ...
    ++m_nRefCount;
    // ... and initialize ouer data container only if it not already exist!
    if( m_pDataContainer == NULL )
    {
        m_pDataContainer = new SvtWorkingSetOptions_Impl;
        ItemHolder1::holdConfigItem(E_WORKINGSETOPTIONS);
    }
}

//*****************************************************************************************************************
//  destructor
//*****************************************************************************************************************
SvtWorkingSetOptions::~SvtWorkingSetOptions()
{
    // Global access, must be guarded (multithreading!)
    MutexGuard aGuard( GetOwnStaticMutex() );
    // Decrease ouer refcount.
    --m_nRefCount;
    // If last instance was deleted ...
    // we must destroy ouer static data container!
    if( m_nRefCount <= 0 )
    {
        delete m_pDataContainer;
        m_pDataContainer = NULL;
    }
}

//*****************************************************************************************************************
//  public method
//*****************************************************************************************************************
Sequence< OUString > SvtWorkingSetOptions::GetWindowList() const
{
    MutexGuard aGuard( GetOwnStaticMutex() );
    return m_pDataContainer->GetWindowList();
}

//*****************************************************************************************************************
//  public method
//*****************************************************************************************************************
void SvtWorkingSetOptions::SetWindowList( const Sequence< OUString >& seqWindowList )
{
    MutexGuard aGuard( GetOwnStaticMutex() );
    m_pDataContainer->SetWindowList( seqWindowList );
}

//*****************************************************************************************************************
//  private method
//*****************************************************************************************************************
Mutex& SvtWorkingSetOptions::GetOwnStaticMutex()
{
    // Initialize static mutex only for one time!
    static Mutex* pMutex = NULL;
    // If these method first called (Mutex not already exist!) ...
    if( pMutex == NULL )
    {
        // ... we must create a new one. Protect follow code with the global mutex -
        // It must be - we create a static variable!
        MutexGuard aGuard( Mutex::getGlobalMutex() );
        // We must check our pointer again - because it can be that another instance of ouer class will be fastr then these!
        if( pMutex == NULL )
        {
            // Create the new mutex and set it for return on static variable.
            static Mutex aMutex;
            pMutex = &aMutex;
        }
    }
    // Return new created or already existing mutex object.
    return *pMutex;
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <iostream>
#include <boost/program_options.hpp>
#include <llvm/ADT/STLExtras.h>
#include <llvm/Bitcode/ReaderWriter.h>
#include "AST.h"
#include "Error.h"
#include "BuiltinFunctions.h"
#include <llvm/Support/FileSystem.h>
#include <llvm/Support/raw_ostream.h>
#include <llvm/Transforms/IPO.h>

namespace po = boost::program_options;
using namespace Helen;
using namespace std;

int yyparse(AST*& ast);
extern FILE* yyin;

int main(int argc, char** argv)
{
    // Boost Program Options setup
    po::options_description desc("Compiler options");
    desc.add_options()
    ("help,h", "display this help")
    ("version,v", "display version")
    ("input-file", po::value<string>(), "input file")
    ;
    po::positional_options_description p;
    p.add("input-file", -1);
    po::variables_map vm;
    po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
    po::notify(vm);
    if (vm.count("help") || vm.empty()) {
        cout << desc << "\n";
        return 1;
    }
    AST::module = llvm::make_unique<Module>("__helenmodule__", getGlobalContext());
    AST::fpm = llvm::make_unique<legacy::FunctionPassManager>(AST::module.get());
    AST::dataLayout = llvm::make_unique<DataLayout>(AST::module.get());
    AST::fpm->add(createBasicAliasAnalysisPass());
    AST::fpm->add(createPromoteMemoryToRegisterPass());
    AST::fpm->add(createInstructionCombiningPass());
    AST::fpm->add(createReassociatePass());
    AST::fpm->add(createGVNPass());
    AST::fpm->add(createCFGSimplificationPass());
    //AST::fpm->add(createFunctionInliningPass());
    legacy::PassManager pm;
    pm.add(createAlwaysInlinerPass());
    AST::fpm->doInitialization();
    yyin = fopen(vm["input-file"].as<string>().c_str(), "r");
    AST::isMainModule = false;
    AST* result;
    yyparse(result);
    if (Error::errorFlag) { // don't even try to compile if syntax errors present
        fprintf(stderr, "Fatal errors detected: translation terminated\n");
        return 1;
    }
    BuiltinFunctions::createMainFunction(AST::isMainModule);
    result->codegen();
    if (Error::errorFlag) {
        fprintf(stderr, "Fatal errors detected: translation terminated\n");
        return 1;
    }
    AST::builder.CreateRet(ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 0));
    pm.run(*(AST::module.get()));
    AST::module->dump();
    //TODO: Add output file to program options
    string filename = (argc >= 3) ? argv[2] : (argv[1] + string(".bc"));
    std::error_code ec;
    raw_fd_ostream fdos(filename, ec, sys::fs::OpenFlags::F_None);
    WriteBitcodeToFile(AST::module.get(), fdos);
    return 0;
}
<commit_msg>added include paths options<commit_after>#include <stdio.h>
#include <iostream>
#include <boost/program_options.hpp>
#include <llvm/ADT/STLExtras.h>
#include <llvm/Bitcode/ReaderWriter.h>
#include "AST.h"
#include "Error.h"
#include "BuiltinFunctions.h"
#include <llvm/Support/FileSystem.h>
#include <llvm/Support/raw_ostream.h>
#include <llvm/Transforms/IPO.h>

namespace po = boost::program_options;
using namespace Helen;
using namespace std;

vector<string> includePaths;

int yyparse(AST*& ast);
extern FILE* yyin;

int main(int argc, char** argv)
{
    // Boost Program Options setup
    po::options_description desc("Compiler options");
    desc.add_options()
    ("help,h", "display this help")
    ("version,v", "display version")
    ("input-file", po::value<string>(), "input file")
    ("include-path,I", po::value<vector<string> >(), "path to include files")
    ;
    po::positional_options_description p;
    p.add("input-file", -1);
    po::variables_map vm;
    po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
    po::notify(vm);
    if (vm.count("help") || vm.empty()) {
        cout << desc << "\n";
        return 1;
    }
    if(vm.count("include-path"))
        includePaths = vm["include-path"].as<vector<string> >();
    includePaths.push_back(".");
    //TODO: add stdlib dirs to include paths
    AST::module = llvm::make_unique<Module>("__helenmodule__", getGlobalContext());
    AST::fpm = llvm::make_unique<legacy::FunctionPassManager>(AST::module.get());
    AST::dataLayout = llvm::make_unique<DataLayout>(AST::module.get());
    AST::fpm->add(createBasicAliasAnalysisPass());
    AST::fpm->add(createPromoteMemoryToRegisterPass());
    AST::fpm->add(createInstructionCombiningPass());
    AST::fpm->add(createReassociatePass());
    AST::fpm->add(createGVNPass());
    AST::fpm->add(createCFGSimplificationPass());
    //AST::fpm->add(createFunctionInliningPass());
    legacy::PassManager pm;
    pm.add(createAlwaysInlinerPass());
    AST::fpm->doInitialization();
    yyin = fopen(vm["input-file"].as<string>().c_str(), "r");
    AST::isMainModule = false;
    AST* result;
    yyparse(result);
    if (Error::errorFlag) { // don't even try to compile if syntax errors present
        fprintf(stderr, "Fatal errors detected: translation terminated\n");
        return 1;
    }
    BuiltinFunctions::createMainFunction(AST::isMainModule);
    result->codegen();
    if (Error::errorFlag) {
        fprintf(stderr, "Fatal errors detected: translation terminated\n");
        return 1;
    }
    AST::builder.CreateRet(ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 0));
    pm.run(*(AST::module.get()));
    AST::module->dump();
    //TODO: Add output file to program options
    string filename = (argc >= 3) ? argv[2] : (argv[1] + string(".bc"));
    std::error_code ec;
    raw_fd_ostream fdos(filename, ec, sys::fs::OpenFlags::F_None);
    WriteBitcodeToFile(AST::module.get(), fdos);
    return 0;
}
<|endoftext|>