<commit_before>//===-- X86Subtarget.cpp - X86 Subtarget Information ------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Nate Begeman and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the X86 specific subclass of TargetSubtarget.
//
//===----------------------------------------------------------------------===//

#include "X86Subtarget.h"
#include "llvm/Module.h"
#include "X86GenSubtarget.inc"
using namespace llvm;

#include "llvm/Support/CommandLine.h"
namespace {
  cl::opt<bool> DisableSSE("disable-x86-sse", cl::Hidden,
                          cl::desc("Disable sse on X86"));
}

/// GetCpuIDAndInfo - Execute the specified cpuid and return the 4 values in the
/// specified arguments.  If we can't run cpuid on the host, return true.
static bool GetCpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX,
                            unsigned *rECX, unsigned *rEDX) {
#if defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)
#if defined(__GNUC__)
  asm ("pushl\t%%ebx\n\t"
       "cpuid\n\t"
       "movl\t%%ebx, %%esi\n\t"
       "popl\t%%ebx"
       : "=a" (*rEAX),
         "=S" (*rEBX),
         "=c" (*rECX),
         "=d" (*rEDX)
       :  "a" (value));
  return false;
#elif defined(_MSC_VER)
  __asm {
    mov   eax,value
    cpuid
    mov   esi,rEAX
    mov   dword ptr [esi],eax
    mov   esi,rEBX
    mov   dword ptr [esi],ebx
    mov   esi,rECX
    mov   dword ptr [esi],ecx
    mov   esi,rEDX
    mov   dword ptr [esi],edx
  }
  return false;
#endif
#endif
  return true;
}

static const char *GetCurrentX86CPU() {
  unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
  if (GetCpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX))
    return "generic";
  unsigned Family  = (EAX & (0xffffffff >> (32 - 4)) << 8) >> 8; // Bits 8 - 11
  unsigned Model   = (EAX & (0xffffffff >> (32 - 4)) << 4) >> 4; // Bits 4 - 7
  GetCpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
  bool Em64T = EDX & (1 << 29);

  union {
    unsigned u[3];
    char     c[12];
  } text;

  GetCpuIDAndInfo(0, &EAX, text.u+0, text.u+2, text.u+1);
  if (memcmp(text.c, "GenuineIntel", 12) == 0) {
    switch (Family) {
      case 3:
        return "i386";
      case 4:
        return "i486";
      case 5:
        switch (Model) {
        case 4:  return "pentium-mmx";
        default: return "pentium";
        }
      case 6:
        switch (Model) {
        case 1:  return "pentiumpro";
        case 3:
        case 5:
        case 6:  return "pentium2";
        case 7:
        case 8:
        case 10:
        case 11: return "pentium3";
        case 9:
        case 13: return "pentium-m";
        case 14: return "yonah";
        default: return "i686";
        }
      case 15: {
        switch (Model) {
        case 3:
        case 4:
          return (Em64T) ? "nocona" : "prescott";
        default:
          return (Em64T) ? "x86-64" : "pentium4";
        }
      }

    default:
      return "generic";
    }
  } else if (memcmp(text.c, "AuthenticAMD", 12) == 0) {
    // FIXME: this poorly matches the generated SubtargetFeatureKV table.  There
    // appears to be no way to generate the wide variety of AMD-specific targets
    // from the information returned from CPUID.
    switch (Family) {
      case 4:
        return "i486";
      case 5:
        switch (Model) {
        case 6:
        case 7:  return "k6";
        case 8:  return "k6-2";
        case 9:
        case 13: return "k6-3";
        default: return "pentium";
        }
      case 6:
        switch (Model) {
        case 4:  return "athlon-tbird";
        case 6:
        case 7:
        case 8:  return "athlon-mp";
        case 10: return "athlon-xp";
        default: return "athlon";
        }
      case 15:
        switch (Model) {
        case 5:  return "athlon-fx"; // also opteron
        default: return "athlon64";
        }

    default:
      return "generic";
    }
  } else {
    return "generic";
  }
}

X86Subtarget::X86Subtarget(const Module &M, const std::string &FS) {
  stackAlignment = 8;
  indirectExternAndWeakGlobals = false;
  X86SSELevel = NoMMXSSE;
  X863DNowLevel = NoThreeDNow;
  Is64Bit = false;

  // Determine default and user specified characteristics
  std::string CPU = GetCurrentX86CPU();

  // Parse features string.
  ParseSubtargetFeatures(FS, CPU);

  // Default to ELF unless otherwise specified.
  TargetType = isELF;

  if (DisableSSE) {
    X86SSELevel = NoMMXSSE;
    X863DNowLevel = NoThreeDNow;
  }

  // Set the boolean corresponding to the current target triple, or the default
  // if one cannot be determined, to true.
  const std::string& TT = M.getTargetTriple();
  if (TT.length() > 5) {
    if (TT.find("cygwin") != std::string::npos ||
        TT.find("mingw")  != std::string::npos)
      TargetType = isCygwin;
    else if (TT.find("darwin") != std::string::npos)
      TargetType = isDarwin;
    else if (TT.find("win32") != std::string::npos)
      TargetType = isWindows;
  } else if (TT.empty()) {
#if defined(__CYGWIN__) || defined(__MINGW32__)
    TargetType = isCygwin;
#elif defined(__APPLE__)
    TargetType = isDarwin;
#elif defined(_WIN32)
    TargetType = isWindows;
#endif
  }

  if (TargetType == isDarwin) {
    stackAlignment = 16;
    indirectExternAndWeakGlobals = true;
  }
}
<commit_msg>Remove -disable-x86-sse<commit_after>//===-- X86Subtarget.cpp - X86 Subtarget Information ------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Nate Begeman and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the X86 specific subclass of TargetSubtarget.
//
//===----------------------------------------------------------------------===//

#include "X86Subtarget.h"
#include "llvm/Module.h"
#include "X86GenSubtarget.inc"
using namespace llvm;

/// GetCpuIDAndInfo - Execute the specified cpuid and return the 4 values in the
/// specified arguments.  If we can't run cpuid on the host, return true.
static bool GetCpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX,
                            unsigned *rECX, unsigned *rEDX) {
#if defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)
#if defined(__GNUC__)
  asm ("pushl\t%%ebx\n\t"
       "cpuid\n\t"
       "movl\t%%ebx, %%esi\n\t"
       "popl\t%%ebx"
       : "=a" (*rEAX),
         "=S" (*rEBX),
         "=c" (*rECX),
         "=d" (*rEDX)
       :  "a" (value));
  return false;
#elif defined(_MSC_VER)
  __asm {
    mov   eax,value
    cpuid
    mov   esi,rEAX
    mov   dword ptr [esi],eax
    mov   esi,rEBX
    mov   dword ptr [esi],ebx
    mov   esi,rECX
    mov   dword ptr [esi],ecx
    mov   esi,rEDX
    mov   dword ptr [esi],edx
  }
  return false;
#endif
#endif
  return true;
}

static const char *GetCurrentX86CPU() {
  unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
  if (GetCpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX))
    return "generic";
  unsigned Family  = (EAX & (0xffffffff >> (32 - 4)) << 8) >> 8; // Bits 8 - 11
  unsigned Model   = (EAX & (0xffffffff >> (32 - 4)) << 4) >> 4; // Bits 4 - 7
  GetCpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
  bool Em64T = EDX & (1 << 29);

  union {
    unsigned u[3];
    char     c[12];
  } text;

  GetCpuIDAndInfo(0, &EAX, text.u+0, text.u+2, text.u+1);
  if (memcmp(text.c, "GenuineIntel", 12) == 0) {
    switch (Family) {
      case 3:
        return "i386";
      case 4:
        return "i486";
      case 5:
        switch (Model) {
        case 4:  return "pentium-mmx";
        default: return "pentium";
        }
      case 6:
        switch (Model) {
        case 1:  return "pentiumpro";
        case 3:
        case 5:
        case 6:  return "pentium2";
        case 7:
        case 8:
        case 10:
        case 11: return "pentium3";
        case 9:
        case 13: return "pentium-m";
        case 14: return "yonah";
        default: return "i686";
        }
      case 15: {
        switch (Model) {
        case 3:
        case 4:
          return (Em64T) ? "nocona" : "prescott";
        default:
          return (Em64T) ? "x86-64" : "pentium4";
        }
      }

    default:
      return "generic";
    }
  } else if (memcmp(text.c, "AuthenticAMD", 12) == 0) {
    // FIXME: this poorly matches the generated SubtargetFeatureKV table.  There
    // appears to be no way to generate the wide variety of AMD-specific targets
    // from the information returned from CPUID.
    switch (Family) {
      case 4:
        return "i486";
      case 5:
        switch (Model) {
        case 6:
        case 7:  return "k6";
        case 8:  return "k6-2";
        case 9:
        case 13: return "k6-3";
        default: return "pentium";
        }
      case 6:
        switch (Model) {
        case 4:  return "athlon-tbird";
        case 6:
        case 7:
        case 8:  return "athlon-mp";
        case 10: return "athlon-xp";
        default: return "athlon";
        }
      case 15:
        switch (Model) {
        case 5:  return "athlon-fx"; // also opteron
        default: return "athlon64";
        }

    default:
      return "generic";
    }
  } else {
    return "generic";
  }
}

X86Subtarget::X86Subtarget(const Module &M, const std::string &FS) {
  stackAlignment = 8;
  indirectExternAndWeakGlobals = false;
  X86SSELevel = NoMMXSSE;
  X863DNowLevel = NoThreeDNow;
  Is64Bit = false;

  // Determine default and user specified characteristics
  std::string CPU = GetCurrentX86CPU();

  // Parse features string.
  ParseSubtargetFeatures(FS, CPU);

  // Default to ELF unless otherwise specified.
  TargetType = isELF;

  X86SSELevel = NoMMXSSE;
  X863DNowLevel = NoThreeDNow;

  // Set the boolean corresponding to the current target triple, or the default
  // if one cannot be determined, to true.
  const std::string& TT = M.getTargetTriple();
  if (TT.length() > 5) {
    if (TT.find("cygwin") != std::string::npos ||
        TT.find("mingw")  != std::string::npos)
      TargetType = isCygwin;
    else if (TT.find("darwin") != std::string::npos)
      TargetType = isDarwin;
    else if (TT.find("win32") != std::string::npos)
      TargetType = isWindows;
  } else if (TT.empty()) {
#if defined(__CYGWIN__) || defined(__MINGW32__)
    TargetType = isCygwin;
#elif defined(__APPLE__)
    TargetType = isDarwin;
#elif defined(_WIN32)
    TargetType = isWindows;
#endif
  }

  if (TargetType == isDarwin) {
    stackAlignment = 16;
    indirectExternAndWeakGlobals = true;
  }
}
<|endoftext|>


<commit_before>#include "../Intersection.h"
#include "../Ray.h"
#include "../Util.h"
#include "Model.h"

namespace SPTracer
{
	Model::Model()
	{
	}

	Model::~Model()
	{
	}

	bool Model::Intersect(const Ray& ray, Intersection& intersection) const
	{
		bool found = false;
		Intersection current;
		// bool foundEmissive = false;		// used for more complicated condition

		for (const auto& o : objects_)
		{
			bool success = o->Intersect(ray, current);

			// no intersection
			if (!success)
			{
				continue;
			}

			/////////////////////////////////////////////////////////////////////////////////////
			// NOTE: More complicated condition for badly positioned light sources.
			// This is more complicated condition. It can be used for models where light sourcse
			// have some surfaces behind them. Normally, there should be some distance between a
			// surface and light source, in which case a simplified condition can be used
			/////////////////////////////////////////////////////////////////////////////////////

			//// if some intersection was already found
			//if (found)
			//{
			//	// difference between distances
			//	float diff = std::abs(current.distance - intersection.distance);

			//	// distance to new intersection is different from distance to old intersection
			//	if (diff > Util::Eps)
			//	{
			//		// new intersection is not closer that the previous one
			//		if (current.distance > intersection.distance)
			//		{
			//			continue;
			//		}
			//	}
			//	else
			//	{
			//		// same distance to intersection
			//		if (foundEmissive)
			//		{
			//			// previous intersection was with emissive material, so it has higher priority
			//			continue;
			//		}
			//	}
			//}

			// new intersection is not closer
			if (found && (current.distance > intersection.distance))
			{
				continue;
			}

			found = true;
			intersection = current;
			intersection.object = o;
			// foundEmissive = o->IsEmissive();		// used for more complicated condition
		}

		return found;
	}

}
<commit_msg>Code cleanup<commit_after>#include <limits>
#include "../Intersection.h"
#include "../Ray.h"
#include "../Util.h"
#include "Model.h"

namespace SPTracer
{
	Model::Model()
	{
	}

	Model::~Model()
	{
	}

	bool Model::Intersect(const Ray& ray, Intersection& intersection) const
	{
		// set initial intersection distance to max possible,
		// so that any intersection will be closer than that
		intersection.distance = std::numeric_limits<float>::infinity();

		Intersection newIntersection;

		for (const auto& o : objects_)
		{
			// find new intersection
			bool success = o->Intersect(ray, newIntersection);

			// check if new intersection is closer
			if (success && (newIntersection.distance < intersection.distance))
			{
				intersection = newIntersection;
				intersection.object = o;
			}
		}

		return intersection.distance < std::numeric_limits<float>::infinity();
	}

}
<|endoftext|>


<commit_before>#include "cnn/nodes.h"
#include "cnn/cnn.h"
#include "cnn/training.h"
#include "cnn/timing.h"
#include "cnn/rnn.h"
#include "cnn/gru.h"
#include "cnn/lstm.h"
#include "cnn/dglstm.h"
#include "cnn/dict.h"
#include "cnn/expr.h"
#include "cnn/cnn-helper.h"
#include "cnn/expr-xtra.h"
#include <iostream>
#include <fstream>
#include <sstream>

#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/program_options/parsers.hpp>
#include <boost/program_options/variables_map.hpp>

using namespace std;
using namespace cnn;

unsigned int LAYERS = 2;
unsigned int INPUT_DIM = 8;  //256
unsigned int HIDDEN_DIM = 24;  // 1024
unsigned int VOCAB_SIZE = 0;

int verbose = 0;

cnn::Dict d;
int kSOS;
int kEOS;

template <class Builder>
struct RNNLanguageModel {
  LookupParameters* p_c;
  Parameters* p_R;
  Parameters* p_bias;
  Builder builder;
  explicit RNNLanguageModel(Model& model) : builder(LAYERS, INPUT_DIM, HIDDEN_DIM, &model) {
    p_c = model.add_lookup_parameters(VOCAB_SIZE, {INPUT_DIM});
	p_R = model.add_parameters({ VOCAB_SIZE, HIDDEN_DIM });
	p_bias = model.add_parameters({ VOCAB_SIZE });
  }

  // return Expression of total loss
  Expression BuildLMGraph(const vector<int>& sent, ComputationGraph& cg) {
    const unsigned slen = sent.size() - 1;
    builder.new_graph(cg);  // reset RNN builder for new graph
    builder.start_new_sequence();
    Expression i_R = parameter(cg, p_R); // hidden -> word rep parameter
    Expression i_bias = parameter(cg, p_bias);  // word bias
	if (verbose)
		display_value(i_R, cg, "IR at ");
	if (verbose)
		display_value(i_bias, cg, "ibias at ");
	vector<Expression> errs;
    for (unsigned t = 0; t < slen; ++t) {
      Expression i_x_t = lookup(cg, p_c, sent[t]);
      // y_t = RNN(x_t)
      Expression i_y_t = builder.add_input(i_x_t);
      Expression i_r_t =  i_bias + i_R * i_y_t;
	  if (verbose)
		  display_value(i_r_t, cg, "response at " + t);
      // we can easily look at intermidiate values
//      std::vector<cnn::real> r_t = as_vector(i_r_t.value());
  //    for (cnn::real f : r_t) cout << f << " "; cout << endl;
    //  cout << "[" << as_scalar(pick(i_r_t, sent[t+1]).value()) << "]" << endl;

      // LogSoftmax followed by PickElement can be written in one step
      // using PickNegLogSoftmax
#if 0
      Expression i_ydist = logsoftmax(i_r_t);
      errs.push_back(pick(i_ydist, sent[t+1]));
#if 0
      Expression i_ydist = softmax(i_r_t);
      i_ydist = log(i_ydist)
      errs.push_back(pick(i_ydist, sent[t+1]));
#endif
#else
      Expression i_err = pickneglogsoftmax(i_r_t, sent[t+1]);
      errs.push_back(i_err);
#endif
    }
    Expression i_nerr = sum(errs);
#if 0
    return -i_nerr;
#else
    return i_nerr;
#endif
  }

  // return Expression for total loss
  void RandomSample(int max_len = 150) {
    cerr << endl;
    ComputationGraph cg;
    builder.new_graph(cg);  // reset RNN builder for new graph
    builder.start_new_sequence();

    Expression i_R = parameter(cg, p_R);
    Expression i_bias = parameter(cg, p_bias);
    vector<Expression> errs;
    int len = 0;
    int cur = kSOS;
    while(len < max_len && cur != kEOS) {
      ++len;
      Expression i_x_t = lookup(cg, p_c, cur);
      // y_t = RNN(x_t)
      Expression i_y_t = builder.add_input(i_x_t);
      Expression i_r_t = i_bias + i_R * i_y_t;

      Expression ydist = softmax(i_r_t);

      unsigned w = 0;
      while (w == 0 || (int)w == kSOS) {
        auto dist = as_vector(cg.incremental_forward());
        cnn::real p = rand01();
        for (; w < dist.size(); ++w) {
          p -= dist[w];
          if (p < 0.0) { break; }
        }
        if (w == dist.size()) w = kEOS;
      }
      cerr << (len == 1 ? "" : " ") << d.Convert(w);
      cur = w;
    }
    cerr << endl;
  }
};

template <class LM_t>
void train(Model &model, LM_t &lm,
    const vector<vector<int>>& training,
    const vector<vector<int>>& dev,
    Trainer *sgd, const string& fname,
    bool randomSample)
{
    cnn::real best = 9e+99;
    unsigned report_every_i = 50;
    unsigned dev_every_i_reports = 500;
    unsigned si = training.size();
    vector<unsigned> order(training.size());
    for (unsigned i = 0; i < order.size(); ++i) order[i] = i;
    bool first = true;
    int report = 0;
    unsigned lines = 0;
    unsigned total_epoch = 40;

    ofstream out(fname, ofstream::out);
    boost::archive::text_oarchive oa(out);
    oa << model;
    out.close();

    size_t i_epoch = 0;
    while (sgd->epoch < total_epoch) {
        Timer iteration("completed in");
        cnn::real loss = 0;
        unsigned chars = 0;
        for (unsigned i = 0; i < report_every_i; ++i) {
            if (si == training.size()) {
                si = 0;
                if (first) { first = false; }
                else { sgd->update_epoch(); }
                cerr << "**SHUFFLE\n";
                shuffle(order.begin(), order.end(), *rndeng);
            }

            // build graph for this instance
            ComputationGraph cg;
            auto& sent = training[order[si]];
            chars += sent.size() - 1;
            ++si;
            lm.BuildLMGraph(sent, cg);
            loss += as_scalar(cg.forward());
            cg.backward();
            sgd->update();
            ++lines;
        }
        sgd->status();
        cerr << " report = " << report << " E = " << (loss / chars) << " ppl=" << exp(loss / chars) << ' ';

        if (randomSample)
            lm.RandomSample();

        // show score on dev data?
        report++;
        if (report % dev_every_i_reports == 0) {
            cnn::real dloss = 0;
            int dchars = 0;
            for (auto& sent : dev) {
                ComputationGraph cg;
                lm.BuildLMGraph(sent, cg);
                dloss += as_scalar(cg.forward());
                dchars += sent.size() - 1;
            }
            if (dloss < best) {
                best = dloss;
                ofstream out(fname, ofstream::out);
                boost::archive::text_oarchive oa(out);
                oa << model;
                out.close();
            }
            else{
                sgd->eta *= 0.5;
            }
            cerr << "\n***TEST E = " << (dloss / dchars) << " ppl=" << exp(dloss / dchars) << ' ';
        }

        i_epoch++;
    }
}

template <class LM_t>
void testcorpus(Model &model, LM_t &lm,
    const vector<vector<int>>& dev)
{
    unsigned lines = 0;
    cnn::real dloss = 0;
    int dchars = 0;
    for (auto& sent : dev) {
        ComputationGraph cg;
        lm.BuildLMGraph(sent, cg);
        dloss += as_scalar(cg.forward());
        dchars += sent.size() - 1;
    }

    cerr << "\n***DEV [epoch=" << (lines / (cnn::real)dev.size()) << "] E = " << (dloss / dchars) << " ppl=" << exp(dloss / dchars) << ' ';
}

void initialise(Model &model, const string &filename)
{
    cerr << "Initialising model parameters from file: " << filename << endl;
    ifstream in(filename, ifstream::in);
    boost::archive::text_iarchive ia(in);
    ia >> model;
}

int main(int argc, char** argv) {
  cnn::Initialize(argc, argv);

  // command line processing
  using namespace boost::program_options;
  variables_map vm;
  options_description opts("Allowed options");
  opts.add_options()
      ("help", "print help message")
      ("seed,s", value<int>()->default_value(217), "random seed number")
      ("train,t", value<string>(), "file containing training sentences")
      ("devel,d", value<string>(), "file containing development sentences.")
      ("test,T", value<string>(), "file containing testing source sentences")
      ("initialise,i", value<string>(), "load initial parameters from file")
      ("parameters,p", value<string>(), "save best parameters to this file")
      ("layers,l", value<int>()->default_value(LAYERS), "use <num> layers for RNN components")
      ("hidden,h", value<int>()->default_value(HIDDEN_DIM), "use <num> dimensions for recurrent hidden states")
      ("gru", "use Gated Recurrent Unit (GRU) for recurrent structure; default RNN")
      ("lstm", "use Long Short Term Memory (GRU) for recurrent structure; default RNN")
      ("dglstm", "use depth-gated LSTM for recurrent structure; default RNN")
      ("verbose,v", "be extremely chatty")
      ("generate,g", value<bool>()->default_value(false), "generate random samples")
      ;
  store(parse_command_line(argc, argv, opts), vm);

  string flavour;
  if (vm.count("gru"))	flavour = "gru";
  else if (vm.count("lstm"))	flavour = "lstm";
  else if (vm.count("rnnem"))	flavour = "rnnem";
  else if (vm.count("dglstm")) flavour = "dglstm";
  else if (vm.count("nmn")) flavour = "nmn";
  else			flavour = "rnn";

  LAYERS = vm["layers"].as<int>();
  HIDDEN_DIM = vm["hidden"].as<int>();

  bool generateSample = false;
  generateSample = vm["generate"].as<bool>();

  string fname;
  if (vm.count("parameters")) {
      fname = vm["parameters"].as<string>();
  }
  else {
      ostringstream os;
      os << "lm"
          << '_' << LAYERS
          << '_' << HIDDEN_DIM
          << '_' << flavour
          << "-pid" << getpid() << ".params";
      fname = os.str();
  }

  cerr << "Parameters will be written to: " << fname << endl;

  if (vm.count("help") || vm.count("train") != 1 || (vm.count("devel") != 1 && vm.count("test") != 1)) {
      cout << opts << "\n";
      return 1;
  }

  kSOS = d.Convert("<s>");
  kEOS = d.Convert("</s>");
  vector<vector<int>> training, dev, test;
  string line;
  int tlc = 0;
  int ttoks = 0;

  string infile = vm["train"].as<string>();
  cerr << "Reading training data from " << infile << "...\n";

  {
    ifstream in(infile);
    assert(in);
    while(getline(in, line)) {
      ++tlc;
      training.push_back(ReadSentence(line, &d));
      ttoks += training.back().size();
      if (training.back().front() != kSOS && training.back().back() != kEOS) {
		  throw("Training sentence in %s : %d didnt start or end with <s>, </s>", infile.c_str(), tlc );
      }
    }
    cerr << tlc << " lines, " << ttoks << " tokens, " << d.size() << " types\n";
  }
  d.Freeze(); // no new word types allowed
  VOCAB_SIZE = d.size();

  if (vm.count("devel") > 0)
  {
      int dlc = 0;
      int dtoks = 0;
      string devfile = vm["devel"].as<string>();
      cerr << "Reading training data from " << devfile << "...\n";
      {
          ifstream in(devfile);
          assert(in);
          while (getline(in, line)) {
              ++dlc;
              dev.push_back(ReadSentence(line, &d));
              dtoks += dev.back().size();
			  if (dev.back().front() != kSOS && dev.back().back() != kEOS) {
				  throw("Dev sentence in %s : %d didn't start or end with <s>, </s> ", devfile.c_str(), tlc);
			  }
          }
          cerr << dlc << " lines, " << dtoks << " tokens\n";
      }
  }

  Model model;
  bool use_momentum = false;
  Trainer* sgd = nullptr;
  if (use_momentum)
    sgd = new MomentumSGDTrainer(&model);
  else
    sgd = new SimpleSGDTrainer(&model);

  if (vm.count("test") == 0)
  {
      if (vm.count("lstm")) {
          cerr << "%% Using LSTM recurrent units" << endl;
          RNNLanguageModel<LSTMBuilder> lm(model);
          train(model, lm, training, dev, sgd, fname, generateSample);
      }
      else if (vm.count("dglstm")) {
          cerr << "%% Using DGLSTM recurrent units" << endl;
          RNNLanguageModel<DGLSTMBuilder> lm(model);
          train(model, lm, training, dev, sgd, fname, generateSample);
      }
  }
  else
  {
      string testfile = vm["test"].as<string>();
      int dlc = 0;
      int dtoks = 0;
      cerr << "Reading training data from " << testfile << "...\n";
      {
          ifstream in(testfile);
          assert(in);
          while (getline(in, line)) {
              ++dlc;
              test.push_back(ReadSentence(line, &d));
              dtoks += test.back().size();
			  if (test.back().front() != kSOS && test.back().back() != kEOS) {
				  throw("Dev sentence in %s : %d didnt start or end with <s>, </s> ", testfile.c_str(), tlc);
			  }
          }
          cerr << dlc << " lines, " << dtoks << " tokens\n";
      }

      if (vm.count("test"))
      {
          if (vm.count("lstm")){
              cerr << "%% using LSTM recurrent units" << endl;
              RNNLanguageModel<LSTMBuilder> lm(model);
              if (vm.count("initialise"))
                  initialise(model, vm["initialise"].as<string>());
              testcorpus(model, lm, test);
          }
          if (vm.count("dglstm")){
              cerr << "%% using DGLSTM recurrent units" << endl;
              RNNLanguageModel<DGLSTMBuilder> lm(model);
              if (vm.count("initialise"))
                  initialise(model, vm["initialise"].as<string>());
              testcorpus(model, lm, test);
          }
      }
  }

  //RNNLanguageModel<SimpleRNNBuilder> lm(model);
  if (argc == 4) {
    string fname = argv[3];
    ifstream in(fname);
    boost::archive::text_iarchive ia(in);
    ia >> model;
  }

  delete sgd;
}

<commit_msg>use log_softmax for rnnlm2<commit_after>#include "cnn/nodes.h"
#include "cnn/cnn.h"
#include "cnn/training.h"
#include "cnn/timing.h"
#include "cnn/rnn.h"
#include "cnn/gru.h"
#include "cnn/lstm.h"
#include "cnn/dglstm.h"
#include "cnn/dict.h"
#include "cnn/expr.h"
#include "cnn/cnn-helper.h"
#include "cnn/expr-xtra.h"
#include <iostream>
#include <fstream>
#include <sstream>

#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/program_options/parsers.hpp>
#include <boost/program_options/variables_map.hpp>

using namespace std;
using namespace cnn;

unsigned int LAYERS = 2;
unsigned int INPUT_DIM = 8;  //256
unsigned int HIDDEN_DIM = 24;  // 1024
unsigned int VOCAB_SIZE = 0;

int verbose = 0;

cnn::Dict d;
int kSOS;
int kEOS;

template <class Builder>
struct RNNLanguageModel {
  LookupParameters* p_c;
  Parameters* p_R;
  Parameters* p_bias;
  Builder builder;
  explicit RNNLanguageModel(Model& model) : builder(LAYERS, INPUT_DIM, HIDDEN_DIM, &model) {
    p_c = model.add_lookup_parameters(VOCAB_SIZE, {INPUT_DIM});
	p_R = model.add_parameters({ VOCAB_SIZE, HIDDEN_DIM });
	p_bias = model.add_parameters({ VOCAB_SIZE });
  }

  // return Expression of total loss
  Expression BuildLMGraph(const vector<int>& sent, ComputationGraph& cg) {
    const unsigned slen = sent.size() - 1;
    builder.new_graph(cg);  // reset RNN builder for new graph
    builder.start_new_sequence();
    Expression i_R = parameter(cg, p_R); // hidden -> word rep parameter
    Expression i_bias = parameter(cg, p_bias);  // word bias
	if (verbose)
		display_value(i_R, cg, "IR at ");
	if (verbose)
		display_value(i_bias, cg, "ibias at ");
	vector<Expression> errs;
    for (unsigned t = 0; t < slen; ++t) {
      Expression i_x_t = lookup(cg, p_c, sent[t]);
      // y_t = RNN(x_t)
      Expression i_y_t = builder.add_input(i_x_t);
      Expression i_r_t =  i_bias + i_R * i_y_t;
	  if (verbose)
		  display_value(i_r_t, cg, "response at " + t);
      // we can easily look at intermidiate values
//      std::vector<cnn::real> r_t = as_vector(i_r_t.value());
  //    for (cnn::real f : r_t) cout << f << " "; cout << endl;
    //  cout << "[" << as_scalar(pick(i_r_t, sent[t+1]).value()) << "]" << endl;

      // LogSoftmax followed by PickElement can be written in one step
      // using PickNegLogSoftmax
#if 1
      Expression i_ydist = log_softmax(i_r_t);
      errs.push_back(pick(i_ydist, sent[t+1]));
#if 0
      Expression i_ydist = softmax(i_r_t);
      i_ydist = log(i_ydist)
      errs.push_back(pick(i_ydist, sent[t+1]));
#endif
#else
      Expression i_err = pickneglogsoftmax(i_r_t, sent[t+1]);
      errs.push_back(i_err);
#endif
    }
    Expression i_nerr = sum(errs);
#if 1
    return -i_nerr;
#else
    return i_nerr;
#endif
  }

  // return Expression for total loss
  void RandomSample(int max_len = 150) {
    cerr << endl;
    ComputationGraph cg;
    builder.new_graph(cg);  // reset RNN builder for new graph
    builder.start_new_sequence();

    Expression i_R = parameter(cg, p_R);
    Expression i_bias = parameter(cg, p_bias);
    vector<Expression> errs;
    int len = 0;
    int cur = kSOS;
    while(len < max_len && cur != kEOS) {
      ++len;
      Expression i_x_t = lookup(cg, p_c, cur);
      // y_t = RNN(x_t)
      Expression i_y_t = builder.add_input(i_x_t);
      Expression i_r_t = i_bias + i_R * i_y_t;

      Expression ydist = softmax(i_r_t);

      unsigned w = 0;
      while (w == 0 || (int)w == kSOS) {
        auto dist = as_vector(cg.incremental_forward());
        cnn::real p = rand01();
        for (; w < dist.size(); ++w) {
          p -= dist[w];
          if (p < 0.0) { break; }
        }
        if (w == dist.size()) w = kEOS;
      }
      cerr << (len == 1 ? "" : " ") << d.Convert(w);
      cur = w;
    }
    cerr << endl;
  }
};

template <class LM_t>
void train(Model &model, LM_t &lm,
    const vector<vector<int>>& training,
    const vector<vector<int>>& dev,
    Trainer *sgd, const string& fname,
    bool randomSample)
{
    cnn::real best = 9e+99;
    unsigned report_every_i = 50;
    unsigned dev_every_i_reports = 500;
    unsigned si = training.size();
    vector<unsigned> order(training.size());
    for (unsigned i = 0; i < order.size(); ++i) order[i] = i;
    bool first = true;
    int report = 0;
    unsigned lines = 0;
    unsigned total_epoch = 40;

    ofstream out(fname, ofstream::out);
    boost::archive::text_oarchive oa(out);
    oa << model;
    out.close();

    size_t i_epoch = 0;
    while (sgd->epoch < total_epoch) {
        Timer iteration("completed in");
        cnn::real loss = 0;
        unsigned chars = 0;
        for (unsigned i = 0; i < report_every_i; ++i) {
            if (si == training.size()) {
                si = 0;
                if (first) { first = false; }
                else { sgd->update_epoch(); }
                cerr << "**SHUFFLE\n";
                shuffle(order.begin(), order.end(), *rndeng);
            }

            // build graph for this instance
            ComputationGraph cg;
            auto& sent = training[order[si]];
            chars += sent.size() - 1;
            ++si;
            lm.BuildLMGraph(sent, cg);
            loss += as_scalar(cg.forward());
            cg.backward();
            sgd->update();
            ++lines;
        }
        sgd->status();
        cerr << " report = " << report << " E = " << (loss / chars) << " ppl=" << exp(loss / chars) << ' ';

        if (randomSample)
            lm.RandomSample();

        // show score on dev data?
        report++;
        if (report % dev_every_i_reports == 0) {
            cnn::real dloss = 0;
            int dchars = 0;
            for (auto& sent : dev) {
                ComputationGraph cg;
                lm.BuildLMGraph(sent, cg);
                dloss += as_scalar(cg.forward());
                dchars += sent.size() - 1;
            }
            if (dloss < best) {
                best = dloss;
                ofstream out(fname, ofstream::out);
                boost::archive::text_oarchive oa(out);
                oa << model;
                out.close();
            }
            else{
                sgd->eta *= 0.5;
            }
            cerr << "\n***TEST E = " << (dloss / dchars) << " ppl=" << exp(dloss / dchars) << ' ';
        }

        i_epoch++;
    }
}

template <class LM_t>
void testcorpus(Model &model, LM_t &lm,
    const vector<vector<int>>& dev)
{
    unsigned lines = 0;
    cnn::real dloss = 0;
    int dchars = 0;
    for (auto& sent : dev) {
        ComputationGraph cg;
        lm.BuildLMGraph(sent, cg);
        dloss += as_scalar(cg.forward());
        dchars += sent.size() - 1;
    }

    cerr << "\n***DEV [epoch=" << (lines / (cnn::real)dev.size()) << "] E = " << (dloss / dchars) << " ppl=" << exp(dloss / dchars) << ' ';
}

void initialise(Model &model, const string &filename)
{
    cerr << "Initialising model parameters from file: " << filename << endl;
    ifstream in(filename, ifstream::in);
    boost::archive::text_iarchive ia(in);
    ia >> model;
}

int main(int argc, char** argv) {
  cnn::Initialize(argc, argv);

  // command line processing
  using namespace boost::program_options;
  variables_map vm;
  options_description opts("Allowed options");
  opts.add_options()
      ("help", "print help message")
      ("seed,s", value<int>()->default_value(217), "random seed number")
      ("train,t", value<string>(), "file containing training sentences")
      ("devel,d", value<string>(), "file containing development sentences.")
      ("test,T", value<string>(), "file containing testing source sentences")
      ("initialise,i", value<string>(), "load initial parameters from file")
      ("parameters,p", value<string>(), "save best parameters to this file")
      ("layers,l", value<int>()->default_value(LAYERS), "use <num> layers for RNN components")
      ("hidden,h", value<int>()->default_value(HIDDEN_DIM), "use <num> dimensions for recurrent hidden states")
      ("gru", "use Gated Recurrent Unit (GRU) for recurrent structure; default RNN")
      ("lstm", "use Long Short Term Memory (GRU) for recurrent structure; default RNN")
      ("dglstm", "use depth-gated LSTM for recurrent structure; default RNN")
      ("verbose,v", "be extremely chatty")
      ("generate,g", value<bool>()->default_value(false), "generate random samples")
      ;
  store(parse_command_line(argc, argv, opts), vm);

  string flavour;
  if (vm.count("gru"))	flavour = "gru";
  else if (vm.count("lstm"))	flavour = "lstm";
  else if (vm.count("rnnem"))	flavour = "rnnem";
  else if (vm.count("dglstm")) flavour = "dglstm";
  else if (vm.count("nmn")) flavour = "nmn";
  else			flavour = "rnn";

  LAYERS = vm["layers"].as<int>();
  HIDDEN_DIM = vm["hidden"].as<int>();

  bool generateSample = false;
  generateSample = vm["generate"].as<bool>();

  string fname;
  if (vm.count("parameters")) {
      fname = vm["parameters"].as<string>();
  }
  else {
      ostringstream os;
      os << "lm"
          << '_' << LAYERS
          << '_' << HIDDEN_DIM
          << '_' << flavour
          << "-pid" << getpid() << ".params";
      fname = os.str();
  }

  cerr << "Parameters will be written to: " << fname << endl;

  if (vm.count("help") || vm.count("train") != 1 || (vm.count("devel") != 1 && vm.count("test") != 1)) {
      cout << opts << "\n";
      return 1;
  }

  kSOS = d.Convert("<s>");
  kEOS = d.Convert("</s>");
  vector<vector<int>> training, dev, test;
  string line;
  int tlc = 0;
  int ttoks = 0;

  string infile = vm["train"].as<string>();
  cerr << "Reading training data from " << infile << "...\n";

  {
    ifstream in(infile);
    assert(in);
    while(getline(in, line)) {
      ++tlc;
      training.push_back(ReadSentence(line, &d));
      ttoks += training.back().size();
      if (training.back().front() != kSOS && training.back().back() != kEOS) {
		  throw("Training sentence in %s : %d didnt start or end with <s>, </s>", infile.c_str(), tlc );
      }
    }
    cerr << tlc << " lines, " << ttoks << " tokens, " << d.size() << " types\n";
  }
  d.Freeze(); // no new word types allowed
  VOCAB_SIZE = d.size();

  if (vm.count("devel") > 0)
  {
      int dlc = 0;
      int dtoks = 0;
      string devfile = vm["devel"].as<string>();
      cerr << "Reading training data from " << devfile << "...\n";
      {
          ifstream in(devfile);
          assert(in);
          while (getline(in, line)) {
              ++dlc;
              dev.push_back(ReadSentence(line, &d));
              dtoks += dev.back().size();
			  if (dev.back().front() != kSOS && dev.back().back() != kEOS) {
				  throw("Dev sentence in %s : %d didn't start or end with <s>, </s> ", devfile.c_str(), tlc);
			  }
          }
          cerr << dlc << " lines, " << dtoks << " tokens\n";
      }
  }

  Model model;
  bool use_momentum = false;
  Trainer* sgd = nullptr;
  if (use_momentum)
    sgd = new MomentumSGDTrainer(&model);
  else
    sgd = new SimpleSGDTrainer(&model);

  if (vm.count("test") == 0)
  {
      if (vm.count("lstm")) {
          cerr << "%% Using LSTM recurrent units" << endl;
          RNNLanguageModel<LSTMBuilder> lm(model);
          train(model, lm, training, dev, sgd, fname, generateSample);
      }
      else if (vm.count("dglstm")) {
          cerr << "%% Using DGLSTM recurrent units" << endl;
          RNNLanguageModel<DGLSTMBuilder> lm(model);
          train(model, lm, training, dev, sgd, fname, generateSample);
      }
  }
  else
  {
      string testfile = vm["test"].as<string>();
      int dlc = 0;
      int dtoks = 0;
      cerr << "Reading training data from " << testfile << "...\n";
      {
          ifstream in(testfile);
          assert(in);
          while (getline(in, line)) {
              ++dlc;
              test.push_back(ReadSentence(line, &d));
              dtoks += test.back().size();
			  if (test.back().front() != kSOS && test.back().back() != kEOS) {
				  throw("Dev sentence in %s : %d didnt start or end with <s>, </s> ", testfile.c_str(), tlc);
			  }
          }
          cerr << dlc << " lines, " << dtoks << " tokens\n";
      }

      if (vm.count("test"))
      {
          if (vm.count("lstm")){
              cerr << "%% using LSTM recurrent units" << endl;
              RNNLanguageModel<LSTMBuilder> lm(model);
              if (vm.count("initialise"))
                  initialise(model, vm["initialise"].as<string>());
              testcorpus(model, lm, test);
          }
          if (vm.count("dglstm")){
              cerr << "%% using DGLSTM recurrent units" << endl;
              RNNLanguageModel<DGLSTMBuilder> lm(model);
              if (vm.count("initialise"))
                  initialise(model, vm["initialise"].as<string>());
              testcorpus(model, lm, test);
          }
      }
  }

  //RNNLanguageModel<SimpleRNNBuilder> lm(model);
  if (argc == 4) {
    string fname = argv[3];
    ifstream in(fname);
    boost::archive::text_iarchive ia(in);
    ia >> model;
  }

  delete sgd;
}

<|endoftext|>


<commit_before>/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkRefCnt.h"
#include "SkThreadUtils.h"
#include "SkTypes.h"
#include "SkWeakRefCnt.h"
#include "Test.h"

static void bounce_ref(void* data) {
    SkRefCnt* ref = static_cast<SkRefCnt*>(data);
    for (int i = 0; i < 100000; ++i) {
        ref->ref();
        ref->unref();
    }
}

static void test_refCnt(skiatest::Reporter* reporter) {
    SkRefCnt* ref = new SkRefCnt();

    SkThread thing1(bounce_ref, ref);
    SkThread thing2(bounce_ref, ref);

    SkASSERT(thing1.start());
    SkASSERT(thing2.start());

    thing1.join();
    thing2.join();

    REPORTER_ASSERT(reporter, ref->unique());
    ref->unref();
}

static void bounce_weak_ref(void* data) {
    SkWeakRefCnt* ref = static_cast<SkWeakRefCnt*>(data);
    for (int i = 0; i < 100000; ++i) {
        if (ref->try_ref()) {
            ref->unref();
        }
    }
}

static void bounce_weak_weak_ref(void* data) {
    SkWeakRefCnt* ref = static_cast<SkWeakRefCnt*>(data);
    for (int i = 0; i < 100000; ++i) {
        ref->weak_ref();
        ref->weak_unref();
    }
}

static void test_weakRefCnt(skiatest::Reporter* reporter) {
    SkWeakRefCnt* ref = new SkWeakRefCnt();

    SkThread thing1(bounce_ref, ref);
    SkThread thing2(bounce_ref, ref);
    SkThread thing3(bounce_weak_ref, ref);
    SkThread thing4(bounce_weak_weak_ref, ref);

    SkASSERT(thing1.start());
    SkASSERT(thing2.start());
    SkASSERT(thing3.start());
    SkASSERT(thing4.start());

    thing1.join();
    thing2.join();
    thing3.join();
    thing4.join();

    REPORTER_ASSERT(reporter, ref->unique());
    SkDEBUGCODE(REPORTER_ASSERT(reporter, ref->getWeakCnt() == 1));
    ref->unref();
}

DEF_TEST(RefCnt, reporter) {
    test_refCnt(reporter);
    test_weakRefCnt(reporter);
}

///////////////////////////////////////////////////////////////////////////////////////////////////

static int gRefCounter;
static int gUnrefCounter;
static int gNewCounter;
static int gDeleteCounter;

#define check(reporter, ref, unref, make, kill)             \
    REPORTER_ASSERT(reporter, gRefCounter == ref);          \
    REPORTER_ASSERT(reporter, gUnrefCounter == unref);      \
    REPORTER_ASSERT(reporter, gNewCounter == make);         \
    REPORTER_ASSERT(reporter, gDeleteCounter == kill);

class Effect {
public:
    Effect() : fRefCnt(1) {
        gNewCounter += 1;
    }
    virtual ~Effect() {}

    int fRefCnt;

    void ref() {
        gRefCounter += 1;
        fRefCnt += 1;
    }
    void unref() {
        gUnrefCounter += 1;

        SkASSERT(fRefCnt > 0);
        if (0 == --fRefCnt) {
            gDeleteCounter += 1;
            delete this;
        }
    }

    int* method() const { return new int; }
};

static sk_sp<Effect> Create() {
    return sk_make_sp<Effect>();
}

class Paint {
public:
    sk_sp<Effect> fEffect;

    const sk_sp<Effect>& get() const { return fEffect; }

    void set(sk_sp<Effect> value) {
        fEffect = std::move(value);
    }
};

struct EffectImpl : public Effect {
    ~EffectImpl() override {}

    static sk_sp<EffectImpl> Create() {
        return sk_sp<EffectImpl>(new EffectImpl);
    }
    int fValue;
};
static sk_sp<Effect> make_effect() {
    auto foo = EffectImpl::Create();
    foo->fValue = 42;
    return std::move(foo);
}

static void reset_counters() {
    gRefCounter = 0;
    gUnrefCounter = 0;
    gNewCounter = 0;
    gDeleteCounter = 0;
}
DEF_TEST(sk_sp, reporter) {
    reset_counters();

    Paint paint;
    REPORTER_ASSERT(reporter, paint.fEffect.get() == nullptr);
    REPORTER_ASSERT(reporter, !paint.get());
    check(reporter, 0, 0, 0, 0);

    paint.set(Create());
    check(reporter, 0, 0, 1, 0);
    REPORTER_ASSERT(reporter, paint.fEffect.get()->fRefCnt == 1);

    if (paint.get()) {
        REPORTER_ASSERT(reporter, true);
    } else {
        REPORTER_ASSERT(reporter, false);
    }
    if (!paint.get()) {
        REPORTER_ASSERT(reporter, false);
    } else {
        REPORTER_ASSERT(reporter, true);
    }

    paint.set(nullptr);
    check(reporter, 0, 1, 1, 1);

    if (paint.get()) {
        REPORTER_ASSERT(reporter, false);
    } else {
        REPORTER_ASSERT(reporter, true);
    }
    if (!paint.get()) {
        REPORTER_ASSERT(reporter, true);
    } else {
        REPORTER_ASSERT(reporter, false);
    }

    auto e = Create();
    REPORTER_ASSERT(reporter, sizeof(e) == sizeof(void*));

    check(reporter, 0, 1, 2, 1);
    paint.set(e);
    check(reporter, 1, 1, 2, 1);
    REPORTER_ASSERT(reporter, paint.fEffect.get()->fRefCnt == 2);

    Paint paint2;
    paint2.set(paint.get());
    check(reporter, 2, 1, 2, 1);
    REPORTER_ASSERT(reporter, paint.fEffect.get()->fRefCnt == 3);

    // Test sk_sp::operator->
    delete paint.get()->method();
    check(reporter, 2, 1, 2, 1);

    // Test sk_sp::operator*
    delete (*paint.get()).method();
    check(reporter, 2, 1, 2, 1);

    paint.set(nullptr);
    e = nullptr;
    paint2.set(nullptr);
    check(reporter, 2, 4, 2, 2);

    reset_counters();
    {
        // Test convertible sk_sp assignment.
        check(reporter, 0, 0, 0, 0);
        sk_sp<Effect> foo(nullptr);
        REPORTER_ASSERT(reporter, !foo);
        foo = make_effect();
        REPORTER_ASSERT(reporter, foo);
        check(reporter, 0, 0, 1, 0);
    }
    check(reporter, 0, 1, 1, 1);

    // Test passing convertible rvalue into funtion.
    reset_counters();
    paint.set(EffectImpl::Create());
    check(reporter, 0, 0, 1, 0);
    paint.set(nullptr);
    check(reporter, 0, 1, 1, 1);

    reset_counters();
    auto baz = EffectImpl::Create();
    check(reporter, 0, 0, 1, 0);
    paint.set(std::move(baz));
    check(reporter, 0, 0, 1, 0);
    REPORTER_ASSERT(reporter, !baz);
    paint.set(nullptr);
    check(reporter, 0, 1, 1, 1);

    reset_counters();
    {
        // test comparison operator with convertible type.
        sk_sp<EffectImpl> bar1 = EffectImpl::Create();
        sk_sp<Effect> bar2(bar1);  // convertible copy constructor
        check(reporter, 1, 0, 1, 0);
        REPORTER_ASSERT(reporter, bar1);
        REPORTER_ASSERT(reporter, bar2);
        REPORTER_ASSERT(reporter, bar1 == bar2);
        REPORTER_ASSERT(reporter, bar2 == bar1);
        REPORTER_ASSERT(reporter, !(bar1 != bar2));
        REPORTER_ASSERT(reporter, !(bar2 != bar1));
        sk_sp<Effect> bar3(nullptr);
        bar3 = bar1;  // convertible copy assignment
        check(reporter, 2, 0, 1, 0);

    }
    check(reporter, 2, 3, 1, 1);

    // test passing convertible copy into funtion.
    reset_counters();
    baz = EffectImpl::Create();
    check(reporter, 0, 0, 1, 0);
    paint.set(baz);
    check(reporter, 1, 0, 1, 0);
    baz = nullptr;
    check(reporter, 1, 1, 1, 0);
    paint.set(nullptr);
    check(reporter, 1, 2, 1, 1);

    {
        sk_sp<SkRefCnt> empty;
        sk_sp<SkRefCnt> notEmpty = sk_make_sp<SkRefCnt>();
        REPORTER_ASSERT(reporter, empty == sk_sp<SkRefCnt>());

        REPORTER_ASSERT(reporter, notEmpty != empty);
        REPORTER_ASSERT(reporter, empty != notEmpty);

        REPORTER_ASSERT(reporter, nullptr == empty);
        REPORTER_ASSERT(reporter, empty == nullptr);
        REPORTER_ASSERT(reporter, empty == empty);

        REPORTER_ASSERT(reporter, nullptr <= empty);
        REPORTER_ASSERT(reporter, empty <= nullptr);
        REPORTER_ASSERT(reporter, empty <= empty);

        REPORTER_ASSERT(reporter, nullptr >= empty);
        REPORTER_ASSERT(reporter, empty >= nullptr);
        REPORTER_ASSERT(reporter, empty >= empty);
    }

    {
        sk_sp<SkRefCnt> a = sk_make_sp<SkRefCnt>();
        sk_sp<SkRefCnt> b = sk_make_sp<SkRefCnt>();
        REPORTER_ASSERT(reporter, a != b);
        REPORTER_ASSERT(reporter, (a < b) != (b < a));
        REPORTER_ASSERT(reporter, (b > a) != (a > b));
        REPORTER_ASSERT(reporter, (a <= b) != (b <= a));
        REPORTER_ASSERT(reporter, (b >= a) != (a >= b));

        REPORTER_ASSERT(reporter, a == a);
        REPORTER_ASSERT(reporter, a <= a);
        REPORTER_ASSERT(reporter, a >= a);
    }

    // http://wg21.cmeerw.net/lwg/issue998
    {
        class foo : public SkRefCnt {
        public:
            foo() : bar(this) {}
            void reset() { bar.reset(); }
        private:
            sk_sp<foo> bar;
        };
        // The following should properly delete the object and not cause undefined behavior.
        // This is an ugly example, but the same issue can arise in more subtle ways.
        (new foo)->reset();
    }

    // https://crrev.com/0d4ef2583a6f19c3e61be04d36eb1a60b133832c
    {
        struct StructB;
        struct StructA : public SkRefCnt {
            sk_sp<StructB> b;
        };

        struct StructB : public SkRefCnt {
            sk_sp<StructA> a;
            ~StructB() override {} // Some clang versions don't emit this implicitly.
        };

        // Create a reference cycle.
        StructA* a = new StructA;
        a->b.reset(new StructB);
        a->b->a.reset(a);

        // Break the cycle by calling reset(). This will cause |a| (and hence, |a.b|)
        // to be deleted before the call to reset() returns. This tests that the
        // implementation of sk_sp::reset() doesn't access |this| after it
        // deletes the underlying pointer. This behaviour is consistent with the
        // definition of unique_ptr::reset in C++11.
        a->b.reset();
    }
}

namespace {
struct FooAbstract : public SkRefCnt {
    virtual void f() = 0;
};
struct FooConcrete : public FooAbstract {
    void f() override {}
};
}
static sk_sp<FooAbstract> make_foo() {
    // can not cast FooConcrete to FooAbstract.
    // can cast FooConcrete* to FooAbstract*.
    return sk_make_sp<FooConcrete>();
}
DEF_TEST(sk_make_sp, r) {
    auto x = make_foo();
}

// Test that reset() "adopts" ownership from the caller, even if we are given the same ptr twice
//
DEF_TEST(sk_sp_reset, r) {
    SkRefCnt* rc = new SkRefCnt;
    REPORTER_ASSERT(r, rc->unique());

    sk_sp<SkRefCnt> sp;
    sp.reset(rc);
    // We have transfered our ownership over to sp
    REPORTER_ASSERT(r, rc->unique());

    rc->ref();  // now "rc" is also an owner
    REPORTER_ASSERT(r, !rc->unique());

    sp.reset(rc);   // this should transfer our ownership over to sp
    REPORTER_ASSERT(r, rc->unique());
}

DEF_TEST(sk_sp_ref, r) {
    SkRefCnt* rc = new SkRefCnt;
    REPORTER_ASSERT(r, rc->unique());

    {
        sk_sp<SkRefCnt> sp = sk_ref_sp(rc);
        REPORTER_ASSERT(r, !rc->unique());
    }

    REPORTER_ASSERT(r, rc->unique());
    rc->unref();
}
<commit_msg>Actually test our ref-counting in release builds<commit_after>/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkRefCnt.h"
#include "SkThreadUtils.h"
#include "SkTypes.h"
#include "SkWeakRefCnt.h"
#include "Test.h"

static void bounce_ref(void* data) {
    SkRefCnt* ref = static_cast<SkRefCnt*>(data);
    for (int i = 0; i < 100000; ++i) {
        ref->ref();
        ref->unref();
    }
}

static void test_refCnt(skiatest::Reporter* reporter) {
    SkRefCnt* ref = new SkRefCnt();

    SkThread thing1(bounce_ref, ref);
    SkThread thing2(bounce_ref, ref);

    SkAssertResult(thing1.start());
    SkAssertResult(thing2.start());

    thing1.join();
    thing2.join();

    REPORTER_ASSERT(reporter, ref->unique());
    ref->unref();
}

static void bounce_weak_ref(void* data) {
    SkWeakRefCnt* ref = static_cast<SkWeakRefCnt*>(data);
    for (int i = 0; i < 100000; ++i) {
        if (ref->try_ref()) {
            ref->unref();
        }
    }
}

static void bounce_weak_weak_ref(void* data) {
    SkWeakRefCnt* ref = static_cast<SkWeakRefCnt*>(data);
    for (int i = 0; i < 100000; ++i) {
        ref->weak_ref();
        ref->weak_unref();
    }
}

static void test_weakRefCnt(skiatest::Reporter* reporter) {
    SkWeakRefCnt* ref = new SkWeakRefCnt();

    SkThread thing1(bounce_ref, ref);
    SkThread thing2(bounce_ref, ref);
    SkThread thing3(bounce_weak_ref, ref);
    SkThread thing4(bounce_weak_weak_ref, ref);

    SkAssertResult(thing1.start());
    SkAssertResult(thing2.start());
    SkAssertResult(thing3.start());
    SkAssertResult(thing4.start());

    thing1.join();
    thing2.join();
    thing3.join();
    thing4.join();

    REPORTER_ASSERT(reporter, ref->unique());
    SkDEBUGCODE(REPORTER_ASSERT(reporter, ref->getWeakCnt() == 1));
    ref->unref();
}

DEF_TEST(RefCnt, reporter) {
    test_refCnt(reporter);
    test_weakRefCnt(reporter);
}

///////////////////////////////////////////////////////////////////////////////////////////////////

static int gRefCounter;
static int gUnrefCounter;
static int gNewCounter;
static int gDeleteCounter;

#define check(reporter, ref, unref, make, kill)             \
    REPORTER_ASSERT(reporter, gRefCounter == ref);          \
    REPORTER_ASSERT(reporter, gUnrefCounter == unref);      \
    REPORTER_ASSERT(reporter, gNewCounter == make);         \
    REPORTER_ASSERT(reporter, gDeleteCounter == kill);

class Effect {
public:
    Effect() : fRefCnt(1) {
        gNewCounter += 1;
    }
    virtual ~Effect() {}

    int fRefCnt;

    void ref() {
        gRefCounter += 1;
        fRefCnt += 1;
    }
    void unref() {
        gUnrefCounter += 1;

        SkASSERT(fRefCnt > 0);
        if (0 == --fRefCnt) {
            gDeleteCounter += 1;
            delete this;
        }
    }

    int* method() const { return new int; }
};

static sk_sp<Effect> Create() {
    return sk_make_sp<Effect>();
}

class Paint {
public:
    sk_sp<Effect> fEffect;

    const sk_sp<Effect>& get() const { return fEffect; }

    void set(sk_sp<Effect> value) {
        fEffect = std::move(value);
    }
};

struct EffectImpl : public Effect {
    ~EffectImpl() override {}

    static sk_sp<EffectImpl> Create() {
        return sk_sp<EffectImpl>(new EffectImpl);
    }
    int fValue;
};
static sk_sp<Effect> make_effect() {
    auto foo = EffectImpl::Create();
    foo->fValue = 42;
    return std::move(foo);
}

static void reset_counters() {
    gRefCounter = 0;
    gUnrefCounter = 0;
    gNewCounter = 0;
    gDeleteCounter = 0;
}
DEF_TEST(sk_sp, reporter) {
    reset_counters();

    Paint paint;
    REPORTER_ASSERT(reporter, paint.fEffect.get() == nullptr);
    REPORTER_ASSERT(reporter, !paint.get());
    check(reporter, 0, 0, 0, 0);

    paint.set(Create());
    check(reporter, 0, 0, 1, 0);
    REPORTER_ASSERT(reporter, paint.fEffect.get()->fRefCnt == 1);

    if (paint.get()) {
        REPORTER_ASSERT(reporter, true);
    } else {
        REPORTER_ASSERT(reporter, false);
    }
    if (!paint.get()) {
        REPORTER_ASSERT(reporter, false);
    } else {
        REPORTER_ASSERT(reporter, true);
    }

    paint.set(nullptr);
    check(reporter, 0, 1, 1, 1);

    if (paint.get()) {
        REPORTER_ASSERT(reporter, false);
    } else {
        REPORTER_ASSERT(reporter, true);
    }
    if (!paint.get()) {
        REPORTER_ASSERT(reporter, true);
    } else {
        REPORTER_ASSERT(reporter, false);
    }

    auto e = Create();
    REPORTER_ASSERT(reporter, sizeof(e) == sizeof(void*));

    check(reporter, 0, 1, 2, 1);
    paint.set(e);
    check(reporter, 1, 1, 2, 1);
    REPORTER_ASSERT(reporter, paint.fEffect.get()->fRefCnt == 2);

    Paint paint2;
    paint2.set(paint.get());
    check(reporter, 2, 1, 2, 1);
    REPORTER_ASSERT(reporter, paint.fEffect.get()->fRefCnt == 3);

    // Test sk_sp::operator->
    delete paint.get()->method();
    check(reporter, 2, 1, 2, 1);

    // Test sk_sp::operator*
    delete (*paint.get()).method();
    check(reporter, 2, 1, 2, 1);

    paint.set(nullptr);
    e = nullptr;
    paint2.set(nullptr);
    check(reporter, 2, 4, 2, 2);

    reset_counters();
    {
        // Test convertible sk_sp assignment.
        check(reporter, 0, 0, 0, 0);
        sk_sp<Effect> foo(nullptr);
        REPORTER_ASSERT(reporter, !foo);
        foo = make_effect();
        REPORTER_ASSERT(reporter, foo);
        check(reporter, 0, 0, 1, 0);
    }
    check(reporter, 0, 1, 1, 1);

    // Test passing convertible rvalue into funtion.
    reset_counters();
    paint.set(EffectImpl::Create());
    check(reporter, 0, 0, 1, 0);
    paint.set(nullptr);
    check(reporter, 0, 1, 1, 1);

    reset_counters();
    auto baz = EffectImpl::Create();
    check(reporter, 0, 0, 1, 0);
    paint.set(std::move(baz));
    check(reporter, 0, 0, 1, 0);
    REPORTER_ASSERT(reporter, !baz);
    paint.set(nullptr);
    check(reporter, 0, 1, 1, 1);

    reset_counters();
    {
        // test comparison operator with convertible type.
        sk_sp<EffectImpl> bar1 = EffectImpl::Create();
        sk_sp<Effect> bar2(bar1);  // convertible copy constructor
        check(reporter, 1, 0, 1, 0);
        REPORTER_ASSERT(reporter, bar1);
        REPORTER_ASSERT(reporter, bar2);
        REPORTER_ASSERT(reporter, bar1 == bar2);
        REPORTER_ASSERT(reporter, bar2 == bar1);
        REPORTER_ASSERT(reporter, !(bar1 != bar2));
        REPORTER_ASSERT(reporter, !(bar2 != bar1));
        sk_sp<Effect> bar3(nullptr);
        bar3 = bar1;  // convertible copy assignment
        check(reporter, 2, 0, 1, 0);

    }
    check(reporter, 2, 3, 1, 1);

    // test passing convertible copy into funtion.
    reset_counters();
    baz = EffectImpl::Create();
    check(reporter, 0, 0, 1, 0);
    paint.set(baz);
    check(reporter, 1, 0, 1, 0);
    baz = nullptr;
    check(reporter, 1, 1, 1, 0);
    paint.set(nullptr);
    check(reporter, 1, 2, 1, 1);

    {
        sk_sp<SkRefCnt> empty;
        sk_sp<SkRefCnt> notEmpty = sk_make_sp<SkRefCnt>();
        REPORTER_ASSERT(reporter, empty == sk_sp<SkRefCnt>());

        REPORTER_ASSERT(reporter, notEmpty != empty);
        REPORTER_ASSERT(reporter, empty != notEmpty);

        REPORTER_ASSERT(reporter, nullptr == empty);
        REPORTER_ASSERT(reporter, empty == nullptr);
        REPORTER_ASSERT(reporter, empty == empty);

        REPORTER_ASSERT(reporter, nullptr <= empty);
        REPORTER_ASSERT(reporter, empty <= nullptr);
        REPORTER_ASSERT(reporter, empty <= empty);

        REPORTER_ASSERT(reporter, nullptr >= empty);
        REPORTER_ASSERT(reporter, empty >= nullptr);
        REPORTER_ASSERT(reporter, empty >= empty);
    }

    {
        sk_sp<SkRefCnt> a = sk_make_sp<SkRefCnt>();
        sk_sp<SkRefCnt> b = sk_make_sp<SkRefCnt>();
        REPORTER_ASSERT(reporter, a != b);
        REPORTER_ASSERT(reporter, (a < b) != (b < a));
        REPORTER_ASSERT(reporter, (b > a) != (a > b));
        REPORTER_ASSERT(reporter, (a <= b) != (b <= a));
        REPORTER_ASSERT(reporter, (b >= a) != (a >= b));

        REPORTER_ASSERT(reporter, a == a);
        REPORTER_ASSERT(reporter, a <= a);
        REPORTER_ASSERT(reporter, a >= a);
    }

    // http://wg21.cmeerw.net/lwg/issue998
    {
        class foo : public SkRefCnt {
        public:
            foo() : bar(this) {}
            void reset() { bar.reset(); }
        private:
            sk_sp<foo> bar;
        };
        // The following should properly delete the object and not cause undefined behavior.
        // This is an ugly example, but the same issue can arise in more subtle ways.
        (new foo)->reset();
    }

    // https://crrev.com/0d4ef2583a6f19c3e61be04d36eb1a60b133832c
    {
        struct StructB;
        struct StructA : public SkRefCnt {
            sk_sp<StructB> b;
        };

        struct StructB : public SkRefCnt {
            sk_sp<StructA> a;
            ~StructB() override {} // Some clang versions don't emit this implicitly.
        };

        // Create a reference cycle.
        StructA* a = new StructA;
        a->b.reset(new StructB);
        a->b->a.reset(a);

        // Break the cycle by calling reset(). This will cause |a| (and hence, |a.b|)
        // to be deleted before the call to reset() returns. This tests that the
        // implementation of sk_sp::reset() doesn't access |this| after it
        // deletes the underlying pointer. This behaviour is consistent with the
        // definition of unique_ptr::reset in C++11.
        a->b.reset();
    }
}

namespace {
struct FooAbstract : public SkRefCnt {
    virtual void f() = 0;
};
struct FooConcrete : public FooAbstract {
    void f() override {}
};
}
static sk_sp<FooAbstract> make_foo() {
    // can not cast FooConcrete to FooAbstract.
    // can cast FooConcrete* to FooAbstract*.
    return sk_make_sp<FooConcrete>();
}
DEF_TEST(sk_make_sp, r) {
    auto x = make_foo();
}

// Test that reset() "adopts" ownership from the caller, even if we are given the same ptr twice
//
DEF_TEST(sk_sp_reset, r) {
    SkRefCnt* rc = new SkRefCnt;
    REPORTER_ASSERT(r, rc->unique());

    sk_sp<SkRefCnt> sp;
    sp.reset(rc);
    // We have transfered our ownership over to sp
    REPORTER_ASSERT(r, rc->unique());

    rc->ref();  // now "rc" is also an owner
    REPORTER_ASSERT(r, !rc->unique());

    sp.reset(rc);   // this should transfer our ownership over to sp
    REPORTER_ASSERT(r, rc->unique());
}

DEF_TEST(sk_sp_ref, r) {
    SkRefCnt* rc = new SkRefCnt;
    REPORTER_ASSERT(r, rc->unique());

    {
        sk_sp<SkRefCnt> sp = sk_ref_sp(rc);
        REPORTER_ASSERT(r, !rc->unique());
    }

    REPORTER_ASSERT(r, rc->unique());
    rc->unref();
}
<|endoftext|>


<commit_before>#include <gtest/gtest.h>
#include <SharedMemory.hpp>

//////////////////////////////////////////////////////////////////
TEST(ShMem, test_001)
{
     using namespace linux;
     posix::Name n("/ShMem_test");
     posix::OpenOptions f;
     ASSERT_EQ(00644, f.get_mode().get());
}

TEST(ShMem, test_002)
{
     using namespace linux;
     posix::Name n("/ShMem_test");
     posix::OpenOptions f;
     ASSERT_EQ(O_CREAT | O_RDWR, f.get_oflag().get());
}

TEST(ShMem, test_003)
{
     using namespace linux;
     posix::Name n("/ShMem_test");
     posix::Mode m;
     posix::OpenOptions f(m);
     ASSERT_EQ(O_CREAT | O_RDWR, f.get_oflag().get());
     ASSERT_EQ(00644, f.get_mode().get());
}

TEST(ShMem, test_004)
{
     using namespace linux;
     posix::Name n("/ShMem_test");
     posix::OFlag m;
     posix::OpenOptions f(m);
     ASSERT_EQ(O_CREAT | O_RDWR, f.get_oflag().get());
     ASSERT_EQ(00644, f.get_mode().get());
}

TEST(ShMem, test_005)
{
     using namespace linux;
     posix::Name n("/ShMem_test");
     posix::OFlag m1;
     posix::Mode m2;
     posix::OpenOptions f(m1, m2);
     ASSERT_EQ(O_CREAT | O_RDWR, f.get_oflag().get());
     ASSERT_EQ(00644, f.get_mode().get());
}

TEST(ShMem, test_006)
{
     using namespace linux;
     posix::Name n("/ShMem_test");
     posix::OFlag m1;
     posix::Mode m2;
     posix::OpenOptions f(m2, m1);
     ASSERT_EQ(O_CREAT | O_RDWR, f.get_oflag().get());
     ASSERT_EQ(00644, f.get_mode().get());
}

TEST(ShMem, test_007)
{
     using namespace linux;
     posix::Name n("/ShMem_test");
     posix::OpenOptions f;
     posix::SharedMemory sm1(n, f, true);
     posix::SharedMemory sm2(n, f, false);
     posix::SharedMemory sm3(n, f);
     //ASSERT_EQ(00644, f.get_mode().get());
}
//////////////////////////////////////////////////////////////////
<commit_msg>add some unit tests for SharedMemory.open<commit_after>#include <gtest/gtest.h>
#include <SharedMemory.hpp>

//////////////////////////////////////////////////////////////////
TEST(ShMem, test_001)
{
     using namespace linux;
     posix::Name n("/ShMem_test");
     posix::OpenOptions f;
     ASSERT_EQ(00644, f.get_mode().get());
}

TEST(ShMem, test_002)
{
     using namespace linux;
     posix::Name n("/ShMem_test");
     posix::OpenOptions f;
     ASSERT_EQ(O_CREAT | O_RDWR, f.get_oflag().get());
}

TEST(ShMem, test_003)
{
     using namespace linux;
     posix::Name n("/ShMem_test");
     posix::Mode m;
     posix::OpenOptions f(m);
     ASSERT_EQ(O_CREAT | O_RDWR, f.get_oflag().get());
     ASSERT_EQ(00644, f.get_mode().get());
}

TEST(ShMem, test_004)
{
     using namespace linux;
     posix::Name n("/ShMem_test");
     posix::OFlag m;
     posix::OpenOptions f(m);
     ASSERT_EQ(O_CREAT | O_RDWR, f.get_oflag().get());
     ASSERT_EQ(00644, f.get_mode().get());
}

TEST(ShMem, test_005)
{
     using namespace linux;
     posix::Name n("/ShMem_test");
     posix::OFlag m1;
     posix::Mode m2;
     posix::OpenOptions f(m1, m2);
     ASSERT_EQ(O_CREAT | O_RDWR, f.get_oflag().get());
     ASSERT_EQ(00644, f.get_mode().get());
}

TEST(ShMem, test_006)
{
     using namespace linux;
     posix::Name n("/ShMem_test");
     posix::OFlag m1;
     posix::Mode m2;
     posix::OpenOptions f(m2, m1);
     ASSERT_EQ(O_CREAT | O_RDWR, f.get_oflag().get());
     ASSERT_EQ(00644, f.get_mode().get());
}

TEST(ShMem, test_007)
{
     using namespace linux;
     posix::Name n("/ShMem_test");
     posix::OpenOptions f;
     //posix::SharedMemory sm1(n, f, true);
     //posix::SharedMemory sm2(n, f, false);
     posix::SharedMemory sm3(n, f);
     //ASSERT_EQ(00644, f.get_mode().get());
}

TEST(ShMem, test_008)
{
     using namespace linux;
     posix::Name n("");
     posix::OpenOptions f;
     posix::SharedMemory sm3(n);
     try {
	  sm3.open();

     } catch (...) {
	  ASSERT_TRUE(true);
	  return;
     }
     ASSERT_TRUE(false);
}

TEST(ShMem, test_009)
{
     using namespace linux;
     posix::Name n("/ARTA");
     posix::OpenOptions f;
     posix::SharedMemory sm3(n, f, false);
     try {
	  sm3.open();

     } catch (...) {
	  ASSERT_TRUE(false);
	  return;
     }
     ASSERT_TRUE(true);
}
//////////////////////////////////////////////////////////////////
<|endoftext|>


<commit_before>/*
  This file is part of Ingen.
  Copyright 2007-2012 David Robillard <http://drobilla.net/>

  Ingen is free software: you can redistribute it and/or modify it under the
  terms of the GNU Affero General Public License as published by the Free
  Software Foundation, either version 3 of the License, or any later version.

  Ingen 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 Affero General Public License for details.

  You should have received a copy of the GNU Affero General Public License
  along with Ingen.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <signal.h>
#include <stdlib.h>

#include <iostream>
#include <string>

#include <boost/optional.hpp>

#include <glibmm/convert.h>
#include <glibmm/miscutils.h>
#include <glibmm/thread.h>
#include <glibmm/timer.h>

#include "raul/Path.hpp"
#include "raul/Thread.hpp"

#include "serd/serd.h"
#include "sord/sordmm.hpp"
#include "sratom/sratom.h"

#include "ingen_config.h"

#include "ingen/AtomReader.hpp"
#include "ingen/AtomWriter.hpp"
#include "ingen/Configuration.hpp"
#include "ingen/Configuration.hpp"
#include "ingen/EngineBase.hpp"
#include "ingen/Interface.hpp"
#include "ingen/URIMap.hpp"
#include "ingen/World.hpp"
#include "ingen/client/ThreadedSigClientInterface.hpp"
#include "ingen/runtime_paths.hpp"
#include "ingen/serialisation/Parser.hpp"
#include "ingen/types.hpp"
#ifdef WITH_BINDINGS
#include "bindings/ingen_bindings.hpp"
#endif

using namespace std;
using namespace Ingen;

World* world = NULL;

/*
class TestClient : public AtomSink {
	void write(const LV2_Atom* msg) {
	}
};
*/
class TestClient : public Interface
{
public:
	explicit TestClient(Log& log) : _log(log) {}
	~TestClient() {}

	Raul::URI uri() const { return Raul::URI("ingen:testClient"); }

	void bundle_begin() {}

	void bundle_end() {}

	void put(const Raul::URI&            uri,
	         const Resource::Properties& properties,
	         Resource::Graph             ctx = Resource::Graph::DEFAULT) {}

	void delta(const Raul::URI&            uri,
	           const Resource::Properties& remove,
	           const Resource::Properties& add) {}

	void move(const Raul::Path& old_path,
	          const Raul::Path& new_path) {}

	void del(const Raul::URI& uri) {}

	void connect(const Raul::Path& tail,
	             const Raul::Path& head) {}

	void disconnect(const Raul::Path& tail,
	                const Raul::Path& head) {}

	void disconnect_all(const Raul::Path& parent_patch_path,
	                    const Raul::Path& path) {}

	void set_property(const Raul::URI&  subject,
	                  const Raul::URI&  predicate,
	                  const Raul::Atom& value) {}

	void set_response_id(int32_t id) {}

	void get(const Raul::URI& uri) {}

	void response(int32_t id, Status status, const std::string& subject) {
		if (status != Status::SUCCESS) {
			_log.error(Raul::fmt("error on message %1%: %2% (%3%)\n")
			           % id % ingen_status_string(status) % subject);
			exit(EXIT_FAILURE);
		}
	}

	void error(const std::string& msg) {
		_log.error(Raul::fmt("error: %1%\n") % msg);
		exit(EXIT_FAILURE);
	}

private:
	Log& _log;
};

static void
ingen_try(bool cond, const char* msg)
{
	if (!cond) {
		cerr << "ingen: Error: " << msg << endl;
		delete world;
		exit(EXIT_FAILURE);
	}
}

int
main(int argc, char** argv)
{
	Glib::thread_init();
	set_bundle_path_from_code((void*)&main);

	if (argc != 3) {
		cerr << "Usage: ingen_test START_PATCH COMMANDS_FILE" << endl;
		return EXIT_FAILURE;
	}

	// Create world
	try {
		world = new World(argc, argv, NULL, NULL, NULL);
	} catch (std::exception& e) {
		cout << "ingen: " << e.what() << endl;
		return EXIT_FAILURE;
	}

	// Load modules
	ingen_try(world->load_module("server_profiled"),
	          "Unable to load server module");

	ingen_try(world->load_module("serialisation_profiled"),
	          "Unable to load serialisation module");

	// Initialise engine
	ingen_try(world->engine(),
	          "Unable to create engine");
	world->engine()->init(48000.0, 4096);
	world->engine()->activate();

	// Load patch
	world->parser()->parse_file(world, world->interface().get(), argv[1]);
	while (world->engine()->pending_events()) {
		world->engine()->run(4096);
		world->engine()->main_iteration();
		g_usleep(1000);
	}

	// Read commands

	SerdChunk     out    = { NULL, 0 };
	LV2_URID_Map* map    = &world->uri_map().urid_map_feature()->urid_map;
	Sratom*       sratom = sratom_new(map);

	sratom_set_object_mode(sratom, SRATOM_OBJECT_MODE_BLANK_SUBJECT);

	LV2_Atom_Forge forge;
	lv2_atom_forge_init(&forge, map);
	lv2_atom_forge_set_sink(&forge, sratom_forge_sink, sratom_forge_deref, &out);

	const std::string cmds_file_path = argv[2];

	// AtomReader to read commands from a file and send them to engine
	AtomReader atom_reader(world->uri_map(),
	                       world->uris(),
	                       world->log(),
	                       world->forge(),
	                       *world->interface().get());

	// AtomWriter to serialise responses from the engine
	/*
	TestClient client;
	SPtr<AtomWriter> atom_writer(
		new AtomWriter(world->uri_map(), world->uris(), client));
	*/
	SPtr<Interface> client(new TestClient(world->log()));

	world->interface()->set_respondee(client);
	world->engine()->register_client(Raul::URI("ingen:/clients/test"),
	                                 client);

	SerdURI cmds_base;
	SerdNode cmds_file_uri = serd_node_new_file_uri(
		(const uint8_t*)cmds_file_path.c_str(),
		NULL, &cmds_base, false);
	Sord::Model* cmds = new Sord::Model(*world->rdf_world(),
	                                    (const char*)cmds_file_uri.buf);
	SerdEnv* env = serd_env_new(&cmds_file_uri);
	cmds->load_file(env, SERD_TURTLE, cmds_file_path);
	Sord::Node nil;
	for (int i = 0; ; ++i) {
		std::string subject_str = (Raul::fmt("msg%1%") % i).str();
		Sord::URI subject(*world->rdf_world(), subject_str,
		                  (const char*)cmds_file_uri.buf);
		Sord::Iter iter = cmds->find(subject, nil, nil);
		if (iter.end()) {
			break;
		}

		out.len = 0;
		sratom_read(sratom, &forge, world->rdf_world()->c_obj(),
		            cmds->c_obj(), subject.c_obj());

		/*
		cerr << "READ " << out.len << " BYTES" << endl;
		LV2_Atom* atom = (LV2_Atom*)out.buf;
		cerr << sratom_to_turtle(
			sratom,
			&world->uri_map().urid_unmap_feature()->urid_unmap,
			(const char*)cmds_file_uri.buf,
			NULL, NULL, atom->type, atom->size, LV2_ATOM_BODY(atom)) << endl;
		*/

		if (!atom_reader.write((LV2_Atom*)out.buf)) {
			return EXIT_FAILURE;
		}

		while (world->engine()->pending_events()) {
			world->engine()->run(4096);
			world->engine()->main_iteration();
			g_usleep(1000);
		}
	}
	free((void*)out.buf);
	serd_env_free(env);
	sratom_free(sratom);
	serd_node_free(&cmds_file_uri);
	delete cmds;

	// Shut down
	world->engine()->deactivate();

	delete world;
	return 0;
}

<commit_msg>Fix compilation with --test.<commit_after>/*
  This file is part of Ingen.
  Copyright 2007-2012 David Robillard <http://drobilla.net/>

  Ingen is free software: you can redistribute it and/or modify it under the
  terms of the GNU Affero General Public License as published by the Free
  Software Foundation, either version 3 of the License, or any later version.

  Ingen 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 Affero General Public License for details.

  You should have received a copy of the GNU Affero General Public License
  along with Ingen.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <signal.h>
#include <stdlib.h>

#include <iostream>
#include <string>

#include <boost/optional.hpp>

#include <glibmm/convert.h>
#include <glibmm/miscutils.h>
#include <glibmm/thread.h>
#include <glibmm/timer.h>

#include "raul/Path.hpp"
#include "raul/Thread.hpp"

#include "serd/serd.h"
#include "sord/sordmm.hpp"
#include "sratom/sratom.h"

#include "ingen_config.h"

#include "ingen/AtomReader.hpp"
#include "ingen/AtomWriter.hpp"
#include "ingen/Configuration.hpp"
#include "ingen/Configuration.hpp"
#include "ingen/EngineBase.hpp"
#include "ingen/Interface.hpp"
#include "ingen/URIMap.hpp"
#include "ingen/World.hpp"
#include "ingen/client/ThreadedSigClientInterface.hpp"
#include "ingen/runtime_paths.hpp"
#include "ingen/serialisation/Parser.hpp"
#include "ingen/types.hpp"
#ifdef WITH_BINDINGS
#include "bindings/ingen_bindings.hpp"
#endif

using namespace std;
using namespace Ingen;

World* world = NULL;

/*
class TestClient : public AtomSink {
	void write(const LV2_Atom* msg) {
	}
};
*/
class TestClient : public Interface
{
public:
	explicit TestClient(Log& log) : _log(log) {}
	~TestClient() {}

	Raul::URI uri() const { return Raul::URI("ingen:testClient"); }

	void bundle_begin() {}

	void bundle_end() {}

	void put(const Raul::URI&            uri,
	         const Resource::Properties& properties,
	         Resource::Graph             ctx = Resource::Graph::DEFAULT) {}

	void delta(const Raul::URI&            uri,
	           const Resource::Properties& remove,
	           const Resource::Properties& add) {}

	void move(const Raul::Path& old_path,
	          const Raul::Path& new_path) {}

	void del(const Raul::URI& uri) {}

	void connect(const Raul::Path& tail,
	             const Raul::Path& head) {}

	void disconnect(const Raul::Path& tail,
	                const Raul::Path& head) {}

	void disconnect_all(const Raul::Path& parent_patch_path,
	                    const Raul::Path& path) {}

	void set_property(const Raul::URI&  subject,
	                  const Raul::URI&  predicate,
	                  const Raul::Atom& value) {}

	void set_response_id(int32_t id) {}

	void get(const Raul::URI& uri) {}

	void response(int32_t id, Status status, const std::string& subject) {
		if (status != Status::SUCCESS) {
			_log.error(Raul::fmt("error on message %1%: %2% (%3%)\n")
			           % id % ingen_status_string(status) % subject);
			exit(EXIT_FAILURE);
		}
	}

	void error(const std::string& msg) {
		_log.error(Raul::fmt("error: %1%\n") % msg);
		exit(EXIT_FAILURE);
	}

private:
	Log& _log;
};

static void
ingen_try(bool cond, const char* msg)
{
	if (!cond) {
		cerr << "ingen: Error: " << msg << endl;
		delete world;
		exit(EXIT_FAILURE);
	}
}

int
main(int argc, char** argv)
{
	Glib::thread_init();
	set_bundle_path_from_code((void*)&main);

	if (argc != 3) {
		cerr << "Usage: ingen_test START_PATCH COMMANDS_FILE" << endl;
		return EXIT_FAILURE;
	}

	// Create world
	try {
		world = new World(argc, argv, NULL, NULL, NULL);
	} catch (std::exception& e) {
		cout << "ingen: " << e.what() << endl;
		return EXIT_FAILURE;
	}

	// Load modules
	ingen_try(world->load_module("server_profiled"),
	          "Unable to load server module");

	ingen_try(world->load_module("serialisation_profiled"),
	          "Unable to load serialisation module");

	// Initialise engine
	ingen_try(bool(world->engine()),
	          "Unable to create engine");
	world->engine()->init(48000.0, 4096);
	world->engine()->activate();

	// Load patch
	world->parser()->parse_file(world, world->interface().get(), argv[1]);
	while (world->engine()->pending_events()) {
		world->engine()->run(4096);
		world->engine()->main_iteration();
		g_usleep(1000);
	}

	// Read commands

	SerdChunk     out    = { NULL, 0 };
	LV2_URID_Map* map    = &world->uri_map().urid_map_feature()->urid_map;
	Sratom*       sratom = sratom_new(map);

	sratom_set_object_mode(sratom, SRATOM_OBJECT_MODE_BLANK_SUBJECT);

	LV2_Atom_Forge forge;
	lv2_atom_forge_init(&forge, map);
	lv2_atom_forge_set_sink(&forge, sratom_forge_sink, sratom_forge_deref, &out);

	const std::string cmds_file_path = argv[2];

	// AtomReader to read commands from a file and send them to engine
	AtomReader atom_reader(world->uri_map(),
	                       world->uris(),
	                       world->log(),
	                       world->forge(),
	                       *world->interface().get());

	// AtomWriter to serialise responses from the engine
	/*
	TestClient client;
	SPtr<AtomWriter> atom_writer(
		new AtomWriter(world->uri_map(), world->uris(), client));
	*/
	SPtr<Interface> client(new TestClient(world->log()));

	world->interface()->set_respondee(client);
	world->engine()->register_client(Raul::URI("ingen:/clients/test"),
	                                 client);

	SerdURI cmds_base;
	SerdNode cmds_file_uri = serd_node_new_file_uri(
		(const uint8_t*)cmds_file_path.c_str(),
		NULL, &cmds_base, false);
	Sord::Model* cmds = new Sord::Model(*world->rdf_world(),
	                                    (const char*)cmds_file_uri.buf);
	SerdEnv* env = serd_env_new(&cmds_file_uri);
	cmds->load_file(env, SERD_TURTLE, cmds_file_path);
	Sord::Node nil;
	for (int i = 0; ; ++i) {
		std::string subject_str = (Raul::fmt("msg%1%") % i).str();
		Sord::URI subject(*world->rdf_world(), subject_str,
		                  (const char*)cmds_file_uri.buf);
		Sord::Iter iter = cmds->find(subject, nil, nil);
		if (iter.end()) {
			break;
		}

		out.len = 0;
		sratom_read(sratom, &forge, world->rdf_world()->c_obj(),
		            cmds->c_obj(), subject.c_obj());

		/*
		cerr << "READ " << out.len << " BYTES" << endl;
		LV2_Atom* atom = (LV2_Atom*)out.buf;
		cerr << sratom_to_turtle(
			sratom,
			&world->uri_map().urid_unmap_feature()->urid_unmap,
			(const char*)cmds_file_uri.buf,
			NULL, NULL, atom->type, atom->size, LV2_ATOM_BODY(atom)) << endl;
		*/

		if (!atom_reader.write((LV2_Atom*)out.buf)) {
			return EXIT_FAILURE;
		}

		while (world->engine()->pending_events()) {
			world->engine()->run(4096);
			world->engine()->main_iteration();
			g_usleep(1000);
		}
	}
	free((void*)out.buf);
	serd_env_free(env);
	sratom_free(sratom);
	serd_node_free(&cmds_file_uri);
	delete cmds;

	// Shut down
	world->engine()->deactivate();

	delete world;
	return 0;
}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2013-2016 Alexander Saprykin <xelfium@gmail.com>
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * 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, see <http://www.gnu.org/licenses/>.
 */

#ifndef PLIBSYS_TESTS_STATIC
#  define BOOST_TEST_DYN_LINK
#endif

#define BOOST_TEST_MODULE pmain_test

#include "plibsys.h"

#include <stdlib.h>
#include <string.h>

#ifdef PLIBSYS_TESTS_STATIC
#  include <boost/test/included/unit_test.hpp>
#else
#  include <boost/test/unit_test.hpp>
#endif

static pint alloc_counter   = 0;
static pint realloc_counter = 0;
static pint free_counter    = 0;

extern "C" ppointer pmem_alloc (psize nbytes)
{
	++alloc_counter;
	return (ppointer) malloc (nbytes);
}

extern "C" ppointer pmem_realloc (ppointer block, psize nbytes)
{
	++realloc_counter;
	return (ppointer) realloc (block, nbytes);
}

extern "C" void pmem_free (ppointer block)
{
	++free_counter;
	free (block);
}

BOOST_AUTO_TEST_SUITE (BOOST_TEST_MODULE)

BOOST_AUTO_TEST_CASE (pmain_general_test)
{
	p_libsys_init ();
	p_libsys_shutdown ();
}

BOOST_AUTO_TEST_CASE (pmain_double_test)
{
	p_libsys_init_full (NULL);
	p_libsys_init ();
	p_libsys_shutdown ();
	p_libsys_shutdown ();
}

BOOST_AUTO_TEST_CASE (pmain_vtable_test)
{
	PMemVTable	vtable;

	vtable.free    = pmem_free;
	vtable.malloc  = pmem_alloc;
	vtable.realloc = pmem_realloc;

	p_libsys_init_full (&vtable);

	alloc_counter   = 0;
	realloc_counter = 0;
	free_counter    = 0;

	pchar *buf = (pchar *) p_malloc0 (10);
	pchar *new_buf = (pchar *) p_realloc ((ppointer) buf, 20);

	BOOST_REQUIRE (new_buf != NULL);

	buf = new_buf;

	p_free (buf);

	BOOST_CHECK (alloc_counter > 0);
	BOOST_CHECK (realloc_counter > 0);
	BOOST_CHECK (free_counter > 0);

	BOOST_CHECK (strcmp (p_libsys_version (), PLIBSYS_VERSION_STR) == 0);

	p_libsys_shutdown ();
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>tests: Move main init/shutdown functions on new testing macros<commit_after>/*
 * Copyright (C) 2013-2017 Alexander Saprykin <xelfium@gmail.com>
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * 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, see <http://www.gnu.org/licenses/>.
 */

#include "plibsys.h"
#include "ptestmacros.h"

#include <stdlib.h>
#include <string.h>

P_TEST_MODULE_INIT ();

static pint alloc_counter   = 0;
static pint realloc_counter = 0;
static pint free_counter    = 0;

extern "C" ppointer pmem_alloc (psize nbytes)
{
	++alloc_counter;
	return (ppointer) malloc (nbytes);
}

extern "C" ppointer pmem_realloc (ppointer block, psize nbytes)
{
	++realloc_counter;
	return (ppointer) realloc (block, nbytes);
}

extern "C" void pmem_free (ppointer block)
{
	++free_counter;
	free (block);
}

P_TEST_CASE_BEGIN (pmain_general_test)
{
	p_libsys_init ();
	p_libsys_shutdown ();
}
P_TEST_CASE_END ()

P_TEST_CASE_BEGIN (pmain_double_test)
{
	p_libsys_init_full (NULL);
	p_libsys_init ();
	p_libsys_shutdown ();
	p_libsys_shutdown ();
}
P_TEST_CASE_END ()

P_TEST_CASE_BEGIN (pmain_vtable_test)
{
	PMemVTable	vtable;

	vtable.free    = pmem_free;
	vtable.malloc  = pmem_alloc;
	vtable.realloc = pmem_realloc;

	p_libsys_init_full (&vtable);

	alloc_counter   = 0;
	realloc_counter = 0;
	free_counter    = 0;

	pchar *buf = (pchar *) p_malloc0 (10);
	pchar *new_buf = (pchar *) p_realloc ((ppointer) buf, 20);

	P_TEST_REQUIRE (new_buf != NULL);

	buf = new_buf;

	p_free (buf);

	P_TEST_CHECK (alloc_counter > 0);
	P_TEST_CHECK (realloc_counter > 0);
	P_TEST_CHECK (free_counter > 0);

	P_TEST_CHECK (strcmp (p_libsys_version (), PLIBSYS_VERSION_STR) == 0);

	p_libsys_shutdown ();
}
P_TEST_CASE_END ()

P_TEST_SUITE_BEGIN()
{
	P_TEST_SUITE_RUN_CASE (pmain_general_test);
	P_TEST_SUITE_RUN_CASE (pmain_double_test);
	P_TEST_SUITE_RUN_CASE (pmain_vtable_test);
}
P_TEST_SUITE_END()
<|endoftext|>