<commit_before>#include "quering.hh"

unsigned char * read_binary_file(const char * filename, size_t filesize)
{
  //Get filesize
  int fd;
  unsigned char * map;

  fd = open(filename, O_RDONLY);

  if (fd == -1) {
    perror("Error opening file for reading");
    exit(EXIT_FAILURE);
  }

  map = (unsigned char *)mmap(0, filesize, PROT_READ, MAP_SHARED, fd, 0);
  if (map == MAP_FAILED) {
    close(fd);
    perror("Error mmapping the file");
    exit(EXIT_FAILURE);
  }

  return map;
}

QueryEngine::QueryEngine(const char * filepath) : decoder(filepath)
{

  //Create filepaths
  std::string basepath(filepath);
  std::string path_to_hashtable = basepath + "/probing_hash.dat";
  std::string path_to_data_bin = basepath + "/binfile.dat";
  std::string path_to_source_vocabid = basepath + "/source_vocabids";

  ///Source phrase vocabids
  read_map(&source_vocabids, path_to_source_vocabid.c_str());

  //Target phrase vocabIDs
  vocabids = decoder.get_target_lookup_map();

  //Read config file
  std::string line;
  std::ifstream config ((basepath + "/config").c_str());
  //Check API version:
  getline(config, line);
  if (atoi(line.c_str()) != API_VERSION) {
    std::cerr << "The ProbingPT API has changed, please rebinarize your phrase tables." << std::endl;
    exit(EXIT_FAILURE);
  }
  //Get tablesize.
  getline(config, line);
  int tablesize = atoi(line.c_str());
  //Number of scores
  getline(config, line);
  num_scores = atoi(line.c_str());
  //do we have a reordering table
  getline(config, line);
  std::transform(line.begin(), line.end(), line.begin(), ::tolower); //Get the boolean in lowercase
  is_reordering = false;
  if (line == "true") {
    is_reordering = true;
    std::cerr << "WARNING. REORDERING TABLES NOT SUPPORTED YET." << std::endl;
  }
  config.close();

  //Mmap binary table
  struct stat filestatus;
  stat(path_to_data_bin.c_str(), &filestatus);
  binary_filesize = filestatus.st_size;
  binary_mmaped = read_binary_file(path_to_data_bin.c_str(), binary_filesize);

  //Read hashtable
  size_t table_filesize = Table::Size(tablesize, 1.2);
  mem = readTable(path_to_hashtable.c_str(), table_filesize);
  Table table_init(mem, table_filesize);
  table = table_init;

  std::cerr << "Initialized successfully! " << std::endl;
}

QueryEngine::~QueryEngine()
{
  //Clear mmap content from memory.
  munmap(binary_mmaped, binary_filesize);
  munmap(mem, table_filesize);

}

std::pair<bool, std::vector<target_text> > QueryEngine::query(std::vector<uint64_t> source_phrase)
{
  bool found;
  std::vector<target_text> translation_entries;
  const Entry * entry;
  //TOO SLOW
  //uint64_t key = util::MurmurHashNative(&source_phrase[0], source_phrase.size());
  uint64_t key = 0;
  for (int i = 0; i < source_phrase.size(); i++) {
    key += (source_phrase[i] << i);
  }

  found = table.Find(key, entry);

  if (found) {
    //The phrase that was searched for was found! We need to get the translation entries.
    //We will read the largest entry in bytes and then filter the unnecesarry with functions
    //from line_splitter
    uint64_t initial_index = entry -> GetValue();
    unsigned int bytes_toread = entry -> bytes_toread;

    //ASK HIEU FOR MORE EFFICIENT WAY TO DO THIS!
    std::vector<unsigned char> encoded_text; //Assign to the vector the relevant portion of the array.
    encoded_text.reserve(bytes_toread);
    for (int i = 0; i < bytes_toread; i++) {
      encoded_text.push_back(binary_mmaped[i+initial_index]);
    }

    //Get only the translation entries necessary
    translation_entries = decoder.full_decode_line(encoded_text, num_scores);

  }

  std::pair<bool, std::vector<target_text> > output (found, translation_entries);

  return output;

}

std::pair<bool, std::vector<target_text> > QueryEngine::query(StringPiece source_phrase)
{
  bool found;
  std::vector<target_text> translation_entries;
  const Entry * entry;
  //Convert source frase to VID
  std::vector<uint64_t> source_phrase_vid = getVocabIDs(source_phrase);
  //TOO SLOW
  //uint64_t key = util::MurmurHashNative(&source_phrase_vid[0], source_phrase_vid.size());
  uint64_t key = 0;
  for (int i = 0; i < source_phrase_vid.size(); i++) {
    key += (source_phrase_vid[i] << i);
  }

  found = table.Find(key, entry);

  if (found) {
    //The phrase that was searched for was found! We need to get the translation entries.
    //We will read the largest entry in bytes and then filter the unnecesarry with functions
    //from line_splitter
    uint64_t initial_index = entry -> GetValue();
    unsigned int bytes_toread = entry -> bytes_toread;
    //At the end of the file we can't readd + largest_entry cause we get a segfault.
    std::cerr << "Entry size is bytes is: " << bytes_toread << std::endl;

    //ASK HIEU FOR MORE EFFICIENT WAY TO DO THIS!
    std::vector<unsigned char> encoded_text; //Assign to the vector the relevant portion of the array.
    encoded_text.reserve(bytes_toread);
    for (int i = 0; i < bytes_toread; i++) {
      encoded_text.push_back(binary_mmaped[i+initial_index]);
    }

    //Get only the translation entries necessary
    translation_entries = decoder.full_decode_line(encoded_text, num_scores);

  }

  std::pair<bool, std::vector<target_text> > output (found, translation_entries);

  return output;

}

void QueryEngine::printTargetInfo(std::vector<target_text> target_phrases)
{
  int entries = target_phrases.size();

  for (int i = 0; i<entries; i++) {
    std::cout << "Entry " << i+1 << " of " << entries << ":" << std::endl;
    //Print text
    std::cout << getTargetWordsFromIDs(target_phrases[i].target_phrase, &vocabids) << "\t";

    //Print probabilities:
    for (int j = 0; j<target_phrases[i].prob.size(); j++) {
      std::cout << target_phrases[i].prob[j] << " ";
    }
    std::cout << "\t";

    //Print word_all1
    for (int j = 0; j<target_phrases[i].word_all1.size(); j++) {
      if (j%2 == 0) {
        std::cout << (short)target_phrases[i].word_all1[j] << "-";
      } else {
        std::cout << (short)target_phrases[i].word_all1[j] << " ";
      }
    }
    std::cout << std::endl;
  }
}
<commit_msg>local variable masking class variable<commit_after>#include "quering.hh"

unsigned char * read_binary_file(const char * filename, size_t filesize)
{
  //Get filesize
  int fd;
  unsigned char * map;

  fd = open(filename, O_RDONLY);

  if (fd == -1) {
    perror("Error opening file for reading");
    exit(EXIT_FAILURE);
  }

  map = (unsigned char *)mmap(0, filesize, PROT_READ, MAP_SHARED, fd, 0);
  if (map == MAP_FAILED) {
    close(fd);
    perror("Error mmapping the file");
    exit(EXIT_FAILURE);
  }

  return map;
}

QueryEngine::QueryEngine(const char * filepath) : decoder(filepath)
{

  //Create filepaths
  std::string basepath(filepath);
  std::string path_to_hashtable = basepath + "/probing_hash.dat";
  std::string path_to_data_bin = basepath + "/binfile.dat";
  std::string path_to_source_vocabid = basepath + "/source_vocabids";

  ///Source phrase vocabids
  read_map(&source_vocabids, path_to_source_vocabid.c_str());

  //Target phrase vocabIDs
  vocabids = decoder.get_target_lookup_map();

  //Read config file
  std::string line;
  std::ifstream config ((basepath + "/config").c_str());
  //Check API version:
  getline(config, line);
  if (atoi(line.c_str()) != API_VERSION) {
    std::cerr << "The ProbingPT API has changed, please rebinarize your phrase tables." << std::endl;
    exit(EXIT_FAILURE);
  }
  //Get tablesize.
  getline(config, line);
  int tablesize = atoi(line.c_str());
  //Number of scores
  getline(config, line);
  num_scores = atoi(line.c_str());
  //do we have a reordering table
  getline(config, line);
  std::transform(line.begin(), line.end(), line.begin(), ::tolower); //Get the boolean in lowercase
  is_reordering = false;
  if (line == "true") {
    is_reordering = true;
    std::cerr << "WARNING. REORDERING TABLES NOT SUPPORTED YET." << std::endl;
  }
  config.close();

  //Mmap binary table
  struct stat filestatus;
  stat(path_to_data_bin.c_str(), &filestatus);
  binary_filesize = filestatus.st_size;
  binary_mmaped = read_binary_file(path_to_data_bin.c_str(), binary_filesize);

  //Read hashtable
  table_filesize = Table::Size(tablesize, 1.2);
  mem = readTable(path_to_hashtable.c_str(), table_filesize);
  Table table_init(mem, table_filesize);
  table = table_init;

  std::cerr << "Initialized successfully! " << std::endl;
}

QueryEngine::~QueryEngine()
{
  //Clear mmap content from memory.
  munmap(binary_mmaped, binary_filesize);
  munmap(mem, table_filesize);

}

std::pair<bool, std::vector<target_text> > QueryEngine::query(std::vector<uint64_t> source_phrase)
{
  bool found;
  std::vector<target_text> translation_entries;
  const Entry * entry;
  //TOO SLOW
  //uint64_t key = util::MurmurHashNative(&source_phrase[0], source_phrase.size());
  uint64_t key = 0;
  for (int i = 0; i < source_phrase.size(); i++) {
    key += (source_phrase[i] << i);
  }

  found = table.Find(key, entry);

  if (found) {
    //The phrase that was searched for was found! We need to get the translation entries.
    //We will read the largest entry in bytes and then filter the unnecesarry with functions
    //from line_splitter
    uint64_t initial_index = entry -> GetValue();
    unsigned int bytes_toread = entry -> bytes_toread;

    //ASK HIEU FOR MORE EFFICIENT WAY TO DO THIS!
    std::vector<unsigned char> encoded_text; //Assign to the vector the relevant portion of the array.
    encoded_text.reserve(bytes_toread);
    for (int i = 0; i < bytes_toread; i++) {
      encoded_text.push_back(binary_mmaped[i+initial_index]);
    }

    //Get only the translation entries necessary
    translation_entries = decoder.full_decode_line(encoded_text, num_scores);

  }

  std::pair<bool, std::vector<target_text> > output (found, translation_entries);

  return output;

}

std::pair<bool, std::vector<target_text> > QueryEngine::query(StringPiece source_phrase)
{
  bool found;
  std::vector<target_text> translation_entries;
  const Entry * entry;
  //Convert source frase to VID
  std::vector<uint64_t> source_phrase_vid = getVocabIDs(source_phrase);
  //TOO SLOW
  //uint64_t key = util::MurmurHashNative(&source_phrase_vid[0], source_phrase_vid.size());
  uint64_t key = 0;
  for (int i = 0; i < source_phrase_vid.size(); i++) {
    key += (source_phrase_vid[i] << i);
  }

  found = table.Find(key, entry);

  if (found) {
    //The phrase that was searched for was found! We need to get the translation entries.
    //We will read the largest entry in bytes and then filter the unnecesarry with functions
    //from line_splitter
    uint64_t initial_index = entry -> GetValue();
    unsigned int bytes_toread = entry -> bytes_toread;
    //At the end of the file we can't readd + largest_entry cause we get a segfault.
    std::cerr << "Entry size is bytes is: " << bytes_toread << std::endl;

    //ASK HIEU FOR MORE EFFICIENT WAY TO DO THIS!
    std::vector<unsigned char> encoded_text; //Assign to the vector the relevant portion of the array.
    encoded_text.reserve(bytes_toread);
    for (int i = 0; i < bytes_toread; i++) {
      encoded_text.push_back(binary_mmaped[i+initial_index]);
    }

    //Get only the translation entries necessary
    translation_entries = decoder.full_decode_line(encoded_text, num_scores);

  }

  std::pair<bool, std::vector<target_text> > output (found, translation_entries);

  return output;

}

void QueryEngine::printTargetInfo(std::vector<target_text> target_phrases)
{
  int entries = target_phrases.size();

  for (int i = 0; i<entries; i++) {
    std::cout << "Entry " << i+1 << " of " << entries << ":" << std::endl;
    //Print text
    std::cout << getTargetWordsFromIDs(target_phrases[i].target_phrase, &vocabids) << "\t";

    //Print probabilities:
    for (int j = 0; j<target_phrases[i].prob.size(); j++) {
      std::cout << target_phrases[i].prob[j] << " ";
    }
    std::cout << "\t";

    //Print word_all1
    for (int j = 0; j<target_phrases[i].word_all1.size(); j++) {
      if (j%2 == 0) {
        std::cout << (short)target_phrases[i].word_all1[j] << "-";
      } else {
        std::cout << (short)target_phrases[i].word_all1[j] << " ";
      }
    }
    std::cout << std::endl;
  }
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <fcntl.h>
#include <errno.h>
#include <math.h>
#include <poll.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/select.h>
#include <cutils/log.h>

#include "sensors.h"
#include "LightSensor.h"

#define EVENT_TYPE_LIGHT		ABS_MISC
/*****************************************************************************/

enum input_device_name {
	LIGHTSENSOR_LEVEL = 0,
	CM36283_LS,
	SUPPORTED_LSENSOR_COUNT,
};

enum {
	TYPE_ADC = 0,
	TYPE_LUX,
};

static const char *data_device_name[] = {
	[LIGHTSENSOR_LEVEL] = "lightsensor-level",
	[CM36283_LS] = "cm36283-ls",
};

static const char *input_sysfs_path_list[] = {
	[LIGHTSENSOR_LEVEL] = "/sys/class/input/%s/device/",
	[CM36283_LS] = "/sys/class/optical_sensors/lightsensor/",
};

static const char *input_sysfs_enable_list[] = {
	[LIGHTSENSOR_LEVEL] = "enable",
	[CM36283_LS] = "ls_auto",
};

static const int input_report_type[] = {
	[LIGHTSENSOR_LEVEL] = TYPE_ADC,
	[CM36283_LS] = TYPE_LUX,
};

LightSensor::LightSensor()
: SensorBase(NULL, NULL),
	  mEnabled(0),
	  mInputReader(4),
	  mHasPendingEvent(false),
	  sensor_index(-1)
{
	int i;
	char *tok = NULL;

	mPendingEvent.version = sizeof(sensors_event_t);
	mPendingEvent.sensor = SENSORS_LIGHT_HANDLE;
	mPendingEvent.type = SENSOR_TYPE_LIGHT;
	memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data));

	for(i = 0; i < SUPPORTED_LSENSOR_COUNT; i++) {
		data_name = data_device_name[i];

		// data_fd is not initialized if data_name passed
		// to SensorBase is NULL.
		data_fd = openInput(data_name);
		if (data_fd > 0) {
			sensor_index = i;
			break;
		}
	}

	if (data_fd) {
		snprintf(input_sysfs_path, sizeof(input_sysfs_path),
				input_sysfs_path_list[i], input_name);
		input_sysfs_path_len = strlen(input_sysfs_path);
		enable(0, 1);
	}
}

LightSensor::~LightSensor() {
	if (mEnabled) {
		enable(0, 0);
	}
}

int LightSensor::setDelay(int32_t handle, int64_t ns)
{
	int fd;
	strcpy(&input_sysfs_path[input_sysfs_path_len], "poll_delay");
	fd = open(input_sysfs_path, O_RDWR);
	if (fd >= 0) {
		char buf[80];
		sprintf(buf, "%lld", ns);
		write(fd, buf, strlen(buf)+1);
		close(fd);
		return 0;
	}
	return -1;
}

int LightSensor::enable(int32_t handle, int en)
{
	int flags = en ? 1 : 0;
	if (flags != mEnabled) {
		int fd;
		if (sensor_index >= 0) {
			strlcpy(&input_sysfs_path[input_sysfs_path_len],
				input_sysfs_enable_list[sensor_index], sizeof(input_sysfs_path) - input_sysfs_path_len);
		}
		else
			return -1;
		fd = open(input_sysfs_path, O_RDWR);
		if (fd >= 0) {
			char buf[2];
			int err;
			buf[1] = 0;
			if (flags) {
				buf[0] = '1';
			} else {
				buf[0] = '0';
			}
			err = write(fd, buf, sizeof(buf));
			close(fd);
			mEnabled = flags;
			return 0;
		}
		return -1;
	}
	return 0;
}

bool LightSensor::hasPendingEvents() const {
	return mHasPendingEvent;
}

int LightSensor::readEvents(sensors_event_t* data, int count)
{
	if (count < 1)
		return -EINVAL;

	if (mHasPendingEvent) {
		mHasPendingEvent = false;
		mPendingEvent.timestamp = getTimestamp();
		*data = mPendingEvent;
		return mEnabled ? 1 : 0;
	}

	ssize_t n = mInputReader.fill(data_fd);
	if (n < 0)
		return n;

	int numEventReceived = 0;
	input_event const* event;

	while (count && mInputReader.readEvent(&event)) {
		int type = event->type;
		if (type == EV_ABS) {
			if (event->code == EVENT_TYPE_LIGHT) {
				mPendingEvent.light = convertEvent(event->value);
			}
		} else if (type == EV_SYN) {
			mPendingEvent.timestamp = timevalToNano(event->time);
			if (mEnabled) {
				*data++ = mPendingEvent;
				count--;
				numEventReceived++;
			}
		} else {
			ALOGE("LightSensor: unknown event (type=%d, code=%d)",
					type, event->code);
		}
		mInputReader.next();
	}

	return numEventReceived;
}

float LightSensor::convertEvent(int value)
{
	float lux = 0;

	if (sensor_index >= 0) {
		if (input_report_type[sensor_index] == TYPE_ADC) {
			// Convert adc value to lux assuming:
			// I = 10 * log(Ev) uA
			// R = 47kOhm
			// Max adc value 4095 = 3.3V
			// 1/4 of light reaches sensor
			lux =  powf(10, value * (330.0f / 4095.0f / 47.0f)) * 4;
		} else if (input_report_type[sensor_index] == TYPE_LUX) {
			lux = value;
		} else {
			ALOGE("LightSensor: unknown report type\n");
			lux = 0;
		}
	}

	return lux;
}
<commit_msg>hardware: sensors: add stk3x1x light sensor support to sensor list<commit_after>/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <fcntl.h>
#include <errno.h>
#include <math.h>
#include <poll.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/select.h>
#include <cutils/log.h>

#include "sensors.h"
#include "LightSensor.h"

#define EVENT_TYPE_LIGHT		ABS_MISC
/*****************************************************************************/

enum input_device_name {
	LIGHTSENSOR_LEVEL = 0,
	CM36283_LS,
	STK3x1x_LS,
	SUPPORTED_LSENSOR_COUNT,
};

enum {
	TYPE_ADC = 0,
	TYPE_LUX,
};

static const char *data_device_name[] = {
	[LIGHTSENSOR_LEVEL] = "lightsensor-level",
	[CM36283_LS] = "cm36283-ls",
	[STK3x1x_LS] = "stk3x1x-ls",
};

static const char *input_sysfs_path_list[] = {
	[LIGHTSENSOR_LEVEL] = "/sys/class/input/%s/device/",
	[CM36283_LS] = "/sys/class/optical_sensors/lightsensor/",
	[STK3x1x_LS] = "/sys/class/input/%s/device/",
};

static const char *input_sysfs_enable_list[] = {
	[LIGHTSENSOR_LEVEL] = "enable",
	[CM36283_LS] = "ls_auto",
	[STK3x1x_LS] = "enable",
};

static const int input_report_type[] = {
	[LIGHTSENSOR_LEVEL] = TYPE_ADC,
	[CM36283_LS] = TYPE_LUX,
	[STK3x1x_LS] = TYPE_LUX,
};

LightSensor::LightSensor()
: SensorBase(NULL, NULL),
	  mEnabled(0),
	  mInputReader(4),
	  mHasPendingEvent(false),
	  sensor_index(-1)
{
	int i;
	char *tok = NULL;

	mPendingEvent.version = sizeof(sensors_event_t);
	mPendingEvent.sensor = SENSORS_LIGHT_HANDLE;
	mPendingEvent.type = SENSOR_TYPE_LIGHT;
	memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data));

	for(i = 0; i < SUPPORTED_LSENSOR_COUNT; i++) {
		data_name = data_device_name[i];

		// data_fd is not initialized if data_name passed
		// to SensorBase is NULL.
		data_fd = openInput(data_name);
		if (data_fd > 0) {
			sensor_index = i;
			break;
		}
	}

	if (data_fd) {
		snprintf(input_sysfs_path, sizeof(input_sysfs_path),
				input_sysfs_path_list[i], input_name);
		input_sysfs_path_len = strlen(input_sysfs_path);
		enable(0, 1);
	}
}

LightSensor::~LightSensor() {
	if (mEnabled) {
		enable(0, 0);
	}
}

int LightSensor::setDelay(int32_t handle, int64_t ns)
{
	int fd;
	strcpy(&input_sysfs_path[input_sysfs_path_len], "poll_delay");
	fd = open(input_sysfs_path, O_RDWR);
	if (fd >= 0) {
		char buf[80];
		sprintf(buf, "%lld", ns);
		write(fd, buf, strlen(buf)+1);
		close(fd);
		return 0;
	}
	return -1;
}

int LightSensor::enable(int32_t handle, int en)
{
	int flags = en ? 1 : 0;
	if (flags != mEnabled) {
		int fd;
		if (sensor_index >= 0) {
			strlcpy(&input_sysfs_path[input_sysfs_path_len],
				input_sysfs_enable_list[sensor_index], sizeof(input_sysfs_path) - input_sysfs_path_len);
		}
		else
			return -1;
		fd = open(input_sysfs_path, O_RDWR);
		if (fd >= 0) {
			char buf[2];
			int err;
			buf[1] = 0;
			if (flags) {
				buf[0] = '1';
			} else {
				buf[0] = '0';
			}
			err = write(fd, buf, sizeof(buf));
			close(fd);
			mEnabled = flags;
			return 0;
		}
		return -1;
	}
	return 0;
}

bool LightSensor::hasPendingEvents() const {
	return mHasPendingEvent;
}

int LightSensor::readEvents(sensors_event_t* data, int count)
{
	if (count < 1)
		return -EINVAL;

	if (mHasPendingEvent) {
		mHasPendingEvent = false;
		mPendingEvent.timestamp = getTimestamp();
		*data = mPendingEvent;
		return mEnabled ? 1 : 0;
	}

	ssize_t n = mInputReader.fill(data_fd);
	if (n < 0)
		return n;

	int numEventReceived = 0;
	input_event const* event;

	while (count && mInputReader.readEvent(&event)) {
		int type = event->type;
		if (type == EV_ABS) {
			if (event->code == EVENT_TYPE_LIGHT) {
				mPendingEvent.light = convertEvent(event->value);
			}
		} else if (type == EV_SYN) {
			mPendingEvent.timestamp = timevalToNano(event->time);
			if (mEnabled) {
				*data++ = mPendingEvent;
				count--;
				numEventReceived++;
			}
		} else {
			ALOGE("LightSensor: unknown event (type=%d, code=%d)",
					type, event->code);
		}
		mInputReader.next();
	}

	return numEventReceived;
}

float LightSensor::convertEvent(int value)
{
	float lux = 0;

	if (sensor_index >= 0) {
		if (input_report_type[sensor_index] == TYPE_ADC) {
			// Convert adc value to lux assuming:
			// I = 10 * log(Ev) uA
			// R = 47kOhm
			// Max adc value 4095 = 3.3V
			// 1/4 of light reaches sensor
			lux =  powf(10, value * (330.0f / 4095.0f / 47.0f)) * 4;
		} else if (input_report_type[sensor_index] == TYPE_LUX) {
			lux = value;
		} else {
			ALOGE("LightSensor: unknown report type\n");
			lux = 0;
		}
	}

	return lux;
}
<|endoftext|>


<commit_before>/********************************************************************
 * AUTHORS: Trevor Hansen
 *
 * BEGIN DATE: May, 2010
 *
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
********************************************************************/

#include "stp/Printer/printers.h"
#include "stp/Printer/SMTLIBPrinter.h"

// Functions used by both the version1 and version2 STMLIB printers.

namespace printer
{
using namespace BEEV;
using std::pair;
using std::endl;

static string tolower(const char* name)
{
  string s(name);
  for (size_t i = 0; i < s.size(); ++i)
    s[i] = ::tolower(s[i]);
  return s;
}

// Map from ASTNodes to LetVars
BEEV::ASTNodeMap NodeLetVarMap;

// This is a vector which stores the Node to LetVars pairs. It
// allows for sorted printing, as opposed to NodeLetVarMap
std::vector<pair<ASTNode, ASTNode>> NodeLetVarVec;

// a partial Map from ASTNodes to LetVars. Needed in order to
// correctly print shared subterms inside the LET itself
BEEV::ASTNodeMap NodeLetVarMap1;

// copied from Presentation Langauge printer.
ostream& SMTLIB_Print(ostream& os, const ASTNode n, const int indentation,
                      void (*SMTLIB1_Print1)(ostream&, const ASTNode, int,
                                             bool),
                      bool smtlib1)
{
  // Clear the maps
  NodeLetVarMap.clear();
  NodeLetVarVec.clear();
  NodeLetVarMap1.clear();

  // pass 1: letize the node
  {
    ASTNodeSet PLPrintNodeSet;
    LetizeNode(n, PLPrintNodeSet, smtlib1);
  }

  // pass 2:
  //
  // 2. print all the let variables and their counterpart expressions
  // 2. as follows (LET var1 = expr1, var2 = expr2, ...
  //
  // 3. Then print the Node itself, replacing every occurence of
  // 3. expr1 with var1, expr2 with var2, ...
  // os << "(";
  if (0 < NodeLetVarMap.size())
  {
    std::vector<pair<ASTNode, ASTNode>>::iterator it = NodeLetVarVec.begin();
    const std::vector<pair<ASTNode, ASTNode>>::iterator itend =
        NodeLetVarVec.end();

    os << "(let (";
    if (!smtlib1)
      os << "(";
    // print the let var first
    SMTLIB1_Print1(os, it->first, indentation, false);
    os << " ";
    // print the expr
    SMTLIB1_Print1(os, it->second, indentation, false);
    os << " )";
    if (!smtlib1)
      os << ")";

    // update the second map for proper printing of LET
    NodeLetVarMap1[it->second] = it->first;

    string closing = "";
    for (it++; it != itend; it++)
    {
      os << " " << endl;
      os << "(let (";
      if (!smtlib1)
        os << "(";
      // print the let var first
      SMTLIB1_Print1(os, it->first, indentation, false);
      os << " ";
      // print the expr
      SMTLIB1_Print1(os, it->second, indentation, false);
      os << ")";
      if (!smtlib1)
        os << ")";

      // update the second map for proper printing of LET
      NodeLetVarMap1[it->second] = it->first;
      closing += ")";
    }
    os << endl;
    SMTLIB1_Print1(os, n, indentation, true);
    os << closing;
    os << " )  ";
  }
  else
    SMTLIB1_Print1(os, n, indentation, false);

  os << endl;
  return os;
}

void LetizeNode(const ASTNode& n, ASTNodeSet& PLPrintNodeSet, bool smtlib1)
{
  const Kind kind = n.GetKind();

  if (kind == SYMBOL || kind == BVCONST || kind == FALSE || kind == TRUE)
    return;

  const ASTVec& c = n.GetChildren();
  for (ASTVec::const_iterator it = c.begin(), itend = c.end(); it != itend;
       it++)
  {
    const ASTNode& ccc = *it;

    const Kind k = ccc.GetKind();
    if (k == SYMBOL || k == BVCONST || k == FALSE || k == TRUE)
      continue;

    if (PLPrintNodeSet.find(ccc) == PLPrintNodeSet.end())
    {
      // If branch: if *it is not in NodeSet then,
      //
      // 1. add it to NodeSet
      //
      // 2. Letize its childNodes
      PLPrintNodeSet.insert(ccc);
      LetizeNode(ccc, PLPrintNodeSet, smtlib1);
    }
    else
    {
      // 0. Else branch: Node has been seen before
      //
      // 1. Check if the node has a corresponding letvar in the
      // 1. NodeLetVarMap.
      //
      // 2. if no, then create a new var and add it to the
      // 2. NodeLetVarMap
      if ((!smtlib1 || ccc.GetType() == BITVECTOR_TYPE) &&
          NodeLetVarMap.find(ccc) == NodeLetVarMap.end())
      {
        // Create a new symbol. Get some name. if it conflicts with a
        // declared name, too bad.
        int sz = NodeLetVarMap.size();
        std::ostringstream oss;
        oss << "?let_k_" << sz;

        ASTNode CurrentSymbol = n.GetSTPMgr()->CreateSymbol(
            oss.str().c_str(), n.GetIndexWidth(), n.GetValueWidth());
        /* If for some reason the variable being created here is
         * already declared by the user then the printed output will
         * not be a legal input to the system. too bad. I refuse to
         * check for this.  [Vijay is the author of this comment.]
         */

        NodeLetVarMap[ccc] = CurrentSymbol;
        std::pair<ASTNode, ASTNode> node_letvar_pair(CurrentSymbol, ccc);
        NodeLetVarVec.push_back(node_letvar_pair);
      }
    }
  }
} // end of LetizeNode()

string functionToSMTLIBName(const Kind k, bool smtlib1)
{
  switch (k)
  {
    case IFF:
      if (smtlib1)
        return "iff";
      else
        return "=";
    case IMPLIES:
      if (smtlib1)
        return "implies";
      else
        return "=>";
    case AND:
    case BVAND:
    case BVNAND:
    case BVNOR:
    case BVOR:
    case BVSGE:
    case BVSGT:
    case BVSLE:
    case BVSLT:
    case BVSUB:
    case BVXOR:
    case ITE:
    case NAND:
    case NOR:
    case NOT:
    case OR:
    case XOR:
    {
      return tolower(_kind_names[k]);
    }

    case BVCONCAT:
      return "concat";
    case BVDIV:
      return "bvudiv";
    case BVGT:
      return "bvugt";
    case BVGE:
      return "bvuge";
    case BVLE:
      return "bvule";
    case BVLEFTSHIFT:
      return "bvshl";
    case BVLT:
      return "bvult";
    case BVMOD:
      return "bvurem";
    case BVMULT:
      return "bvmul";
    case BVNEG:
      return "bvnot"; // CONFUSSSSINNG. (1/2)
    case BVPLUS:
      return "bvadd";
    case BVRIGHTSHIFT:
      return "bvlshr"; // logical
    case BVSRSHIFT:
      return "bvashr"; // arithmetic.
    case BVUMINUS:
      return "bvneg"; // CONFUSSSSINNG. (2/2)
    case EQ:
      return "=";
    case READ:
      return "select";
    case WRITE:
      return "store";
    case SBVDIV:
      return "bvsdiv";
    case SBVREM:
      return "bvsrem";
    case SBVMOD:
      return "bvsmod";

    default:
    {
      std::cerr << "Unknown name when outputting:";
      FatalError(_kind_names[k]);
      return ""; // to quieten compiler/
    }
  }
}
}
<commit_msg>Remove code copy-paste<commit_after>/********************************************************************
 * AUTHORS: Trevor Hansen
 *
 * BEGIN DATE: May, 2010
 *
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
********************************************************************/

#include "stp/Printer/printers.h"
#include "stp/Printer/SMTLIBPrinter.h"

// Functions used by both the version1 and version2 STMLIB printers.

namespace printer
{
using namespace BEEV;
using std::pair;
using std::endl;

static string tolower(const char* name)
{
  string s(name);
  for (size_t i = 0; i < s.size(); ++i)
    s[i] = ::tolower(s[i]);
  return s;
}

// Map from ASTNodes to LetVars
BEEV::ASTNodeMap NodeLetVarMap;

// This is a vector which stores the Node to LetVars pairs. It
// allows for sorted printing, as opposed to NodeLetVarMap
std::vector<pair<ASTNode, ASTNode>> NodeLetVarVec;

// a partial Map from ASTNodes to LetVars. Needed in order to
// correctly print shared subterms inside the LET itself
BEEV::ASTNodeMap NodeLetVarMap1;

// copied from Presentation Langauge printer.
ostream& SMTLIB_Print(ostream& os, const ASTNode n, const int indentation,
                      void (*SMTLIB1_Print1)(ostream&, const ASTNode, int,
                                             bool),
                      bool smtlib1)
{
  // Clear the maps
  NodeLetVarMap.clear();
  NodeLetVarVec.clear();
  NodeLetVarMap1.clear();

  // pass 1: letize the node
  {
    ASTNodeSet PLPrintNodeSet;
    LetizeNode(n, PLPrintNodeSet, smtlib1);
  }

  // pass 2:
  //
  // 2. print all the let variables and their counterpart expressions
  // 2. as follows (LET var1 = expr1, var2 = expr2, ...
  //
  // 3. Then print the Node itself, replacing every occurence of
  // 3. expr1 with var1, expr2 with var2, ...
  // os << "(";
  if (0 < NodeLetVarMap.size())
  {
    std::vector<pair<ASTNode, ASTNode>>::iterator it = NodeLetVarVec.begin();
    const std::vector<pair<ASTNode, ASTNode>>::iterator itend =
        NodeLetVarVec.end();

    os << "(let (";
    if (!smtlib1)
      os << "(";
    // print the let var first
    SMTLIB1_Print1(os, it->first, indentation, false);
    os << " ";
    // print the expr
    SMTLIB1_Print1(os, it->second, indentation, false);
    os << " )";
    if (!smtlib1)
      os << ")";

    // update the second map for proper printing of LET
    NodeLetVarMap1[it->second] = it->first;

    string closing = "";
    for (it++; it != itend; it++)
    {
      os << " " << endl;
      os << "(let (";
      if (!smtlib1)
        os << "(";
      // print the let var first
      SMTLIB1_Print1(os, it->first, indentation, false);
      os << " ";
      // print the expr
      SMTLIB1_Print1(os, it->second, indentation, false);
      os << ")";
      if (!smtlib1)
        os << ")";

      // update the second map for proper printing of LET
      NodeLetVarMap1[it->second] = it->first;
      closing += ")";
    }
    os << endl;
    SMTLIB1_Print1(os, n, indentation, true);
    os << closing;
    os << " )  ";
  }
  else
    SMTLIB1_Print1(os, n, indentation, false);

  os << endl;
  return os;
}

void LetizeNode(const ASTNode& n, ASTNodeSet& PLPrintNodeSet, bool smtlib1)
{
  if (n.isAtom())
    return;

  const ASTVec& c = n.GetChildren();
  for (ASTVec::const_iterator it = c.begin(), itend = c.end(); it != itend;
       it++)
  {
    const ASTNode& ccc = *it;
    if (ccc.isAtom())
      continue;

    if (PLPrintNodeSet.find(ccc) == PLPrintNodeSet.end())
    {
      // If branch: if *it is not in NodeSet then,
      //
      // 1. add it to NodeSet
      //
      // 2. Letize its childNodes
      PLPrintNodeSet.insert(ccc);
      LetizeNode(ccc, PLPrintNodeSet, smtlib1);
    }
    else
    {
      // 0. Else branch: Node has been seen before
      //
      // 1. Check if the node has a corresponding letvar in the
      // 1. NodeLetVarMap.
      //
      // 2. if no, then create a new var and add it to the
      // 2. NodeLetVarMap
      if ((!smtlib1 || ccc.GetType() == BITVECTOR_TYPE) &&
          NodeLetVarMap.find(ccc) == NodeLetVarMap.end())
      {
        // Create a new symbol. Get some name. if it conflicts with a
        // declared name, too bad.
        int sz = NodeLetVarMap.size();
        std::ostringstream oss;
        oss << "?let_k_" << sz;

        ASTNode CurrentSymbol = n.GetSTPMgr()->CreateSymbol(
            oss.str().c_str(), n.GetIndexWidth(), n.GetValueWidth());
        /* If for some reason the variable being created here is
         * already declared by the user then the printed output will
         * not be a legal input to the system. too bad. I refuse to
         * check for this.  [Vijay is the author of this comment.]
         */

        NodeLetVarMap[ccc] = CurrentSymbol;
        std::pair<ASTNode, ASTNode> node_letvar_pair(CurrentSymbol, ccc);
        NodeLetVarVec.push_back(node_letvar_pair);
      }
    }
  }
} // end of LetizeNode()

string functionToSMTLIBName(const Kind k, bool smtlib1)
{
  switch (k)
  {
    case IFF:
      if (smtlib1)
        return "iff";
      else
        return "=";
    case IMPLIES:
      if (smtlib1)
        return "implies";
      else
        return "=>";
    case AND:
    case BVAND:
    case BVNAND:
    case BVNOR:
    case BVOR:
    case BVSGE:
    case BVSGT:
    case BVSLE:
    case BVSLT:
    case BVSUB:
    case BVXOR:
    case ITE:
    case NAND:
    case NOR:
    case NOT:
    case OR:
    case XOR:
    {
      return tolower(_kind_names[k]);
    }

    case BVCONCAT:
      return "concat";
    case BVDIV:
      return "bvudiv";
    case BVGT:
      return "bvugt";
    case BVGE:
      return "bvuge";
    case BVLE:
      return "bvule";
    case BVLEFTSHIFT:
      return "bvshl";
    case BVLT:
      return "bvult";
    case BVMOD:
      return "bvurem";
    case BVMULT:
      return "bvmul";
    case BVNEG:
      return "bvnot"; // CONFUSSSSINNG. (1/2)
    case BVPLUS:
      return "bvadd";
    case BVRIGHTSHIFT:
      return "bvlshr"; // logical
    case BVSRSHIFT:
      return "bvashr"; // arithmetic.
    case BVUMINUS:
      return "bvneg"; // CONFUSSSSINNG. (2/2)
    case EQ:
      return "=";
    case READ:
      return "select";
    case WRITE:
      return "store";
    case SBVDIV:
      return "bvsdiv";
    case SBVREM:
      return "bvsrem";
    case SBVMOD:
      return "bvsmod";

    default:
    {
      std::cerr << "Unknown name when outputting:";
      FatalError(_kind_names[k]);
      return ""; // to quieten compiler/
    }
  }
}
}
<|endoftext|>


<commit_before>//===- Signals.cpp - Signal Handling support ------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines some helpful functions for dealing with the possibility of
// Unix signals occuring while your program is running.
//
//===----------------------------------------------------------------------===//

#include "Support/Signals.h"
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#include "Config/config.h"     // Get the signal handler return type
#ifdef HAVE_EXECINFO_H
# include <execinfo.h>         // For backtrace().
#endif
#include <signal.h>
#include <unistd.h>
using namespace llvm;

static std::vector<std::string> FilesToRemove;

// IntSigs - Signals that may interrupt the program at any time.
static const int IntSigs[] = {
  SIGHUP, SIGINT, SIGQUIT, SIGKILL, SIGPIPE, SIGTERM, SIGUSR1, SIGUSR2
};
static const int *IntSigsEnd = IntSigs + sizeof(IntSigs)/sizeof(IntSigs[0]);

// KillSigs - Signals that are synchronous with the program that will cause it
// to die.
static const int KillSigs[] = {
  SIGILL, SIGTRAP, SIGABRT, SIGFPE, SIGBUS, SIGSEGV, SIGSYS, SIGXCPU, SIGXFSZ
#ifdef SIGEMT
  , SIGEMT
#endif
};
static const int *KillSigsEnd = KillSigs + sizeof(KillSigs)/sizeof(KillSigs[0]);

static void* StackTrace[256];

// SignalHandler - The signal handler that runs...
static RETSIGTYPE SignalHandler(int Sig) {
  while (!FilesToRemove.empty()) {
    std::remove(FilesToRemove.back().c_str());
    FilesToRemove.pop_back();
  }

  if (std::find(IntSigs, IntSigsEnd, Sig) != IntSigsEnd)
    exit(1);   // If this is an interrupt signal, exit the program

  // Otherwise if it is a fault (like SEGV) output the stacktrace to
  // STDERR (if we can) and reissue the signal to die...
#ifdef HAVE_BACKTRACE
  // Use backtrace() to output a backtrace on Linux systems with glibc.
  int depth = backtrace(StackTrace, sizeof(StackTrace)/sizeof(StackTrace[0]));
  backtrace_symbols_fd(StackTrace, depth, STDERR_FILENO);
#endif
  signal(Sig, SIG_DFL);
}

static void RegisterHandler(int Signal) { signal(Signal, SignalHandler); }

// RemoveFileOnSignal - The public API
void llvm::RemoveFileOnSignal(const std::string &Filename) {
  FilesToRemove.push_back(Filename);

  std::for_each(IntSigs, IntSigsEnd, RegisterHandler);
  std::for_each(KillSigs, KillSigsEnd, RegisterHandler);
}

/// PrintStackTraceOnErrorSignal - When an error signal (such as SIBABRT or
/// SIGSEGV) is delivered to the process, print a stack trace and then exit.
void llvm::PrintStackTraceOnErrorSignal() {
  std::for_each(KillSigs, KillSigsEnd, RegisterHandler);
}
<commit_msg>When printing a stack trace, demangle it if possible.  Since we are potentially in a signal handler, allocating memory or doing other unsafe things is bad, which means we should do it in a different process.<commit_after>//===- Signals.cpp - Signal Handling support ------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines some helpful functions for dealing with the possibility of
// Unix signals occuring while your program is running.
//
//===----------------------------------------------------------------------===//

#include "Support/Signals.h"
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#include "Config/config.h"     // Get the signal handler return type
#ifdef HAVE_EXECINFO_H
# include <execinfo.h>         // For backtrace().
#endif
#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>
#include <cerrno>
using namespace llvm;

static std::vector<std::string> FilesToRemove;

// IntSigs - Signals that may interrupt the program at any time.
static const int IntSigs[] = {
  SIGHUP, SIGINT, SIGQUIT, SIGKILL, SIGPIPE, SIGTERM, SIGUSR1, SIGUSR2
};
static const int *IntSigsEnd = IntSigs + sizeof(IntSigs)/sizeof(IntSigs[0]);

// KillSigs - Signals that are synchronous with the program that will cause it
// to die.
static const int KillSigs[] = {
  SIGILL, SIGTRAP, SIGABRT, SIGFPE, SIGBUS, SIGSEGV, SIGSYS, SIGXCPU, SIGXFSZ
#ifdef SIGEMT
  , SIGEMT
#endif
};
static const int *KillSigsEnd = KillSigs + sizeof(KillSigs)/sizeof(KillSigs[0]);

#ifdef HAVE_BACKTRACE
static void* StackTrace[256];
#endif

// PrintStackTrace - In the case of a program crash or fault, print out a stack
// trace so that the user has an indication of why and where we died.
//
// On glibc systems we have the 'backtrace' function, which works nicely, but
// doesn't demangle symbols.  In order to backtrace symbols, we fork and exec a
// 'c++filt' process to do the demangling.  This seems like the simplest and
// most robust solution when we can't allocate memory (such as in a signal
// handler).  If we can't find 'c++filt', we fallback to printing mangled names.
//
static void PrintStackTrace() {
#ifdef HAVE_BACKTRACE
  // Use backtrace() to output a backtrace on Linux systems with glibc.
  int depth = backtrace(StackTrace, sizeof(StackTrace)/sizeof(StackTrace[0]));

  // Create a one-way unix pipe.  The backtracing process writes to PipeFDs[1],
  // the c++filt process reads from PipeFDs[0].
  int PipeFDs[2];
  if (pipe(PipeFDs)) {
    backtrace_symbols_fd(StackTrace, depth, STDERR_FILENO);
    return;
  }

  switch (pid_t ChildPID = fork()) {
  case -1:        // Error forking, print mangled stack trace
    close(PipeFDs[0]);
    close(PipeFDs[1]);
    backtrace_symbols_fd(StackTrace, depth, STDERR_FILENO);
    return;
  default:        // backtracing process
    close(PipeFDs[0]);  // Close the reader side.

    // Print the mangled backtrace into the pipe.
    backtrace_symbols_fd(StackTrace, depth, PipeFDs[1]);
    close(PipeFDs[1]);   // We are done writing.
    while (waitpid(ChildPID, 0, 0) == -1)
      if (errno != EINTR) break;
    return;

  case 0:         // c++filt process
    close(PipeFDs[1]);    // Close the writer side.
    dup2(PipeFDs[0], 0);  // Read from standard input
    close(PipeFDs[0]);    // Close the old descriptor
    dup2(2, 1);           // Revector stdout -> stderr

    // Try to run c++filt or gc++filt.  If neither is found, call back on 'cat'
    // to print the mangled stack trace.  If we can't find cat, just exit.
    execlp("c++filt", "c++filt", 0);
    execlp("gc++filt", "gc++filt", 0);
    execlp("cat", "cat", 0);
    execlp("/usr/bin/cat", "cat", 0);
    exit(0);
  }
#endif
}

// SignalHandler - The signal handler that runs...
static RETSIGTYPE SignalHandler(int Sig) {
  while (!FilesToRemove.empty()) {
    std::remove(FilesToRemove.back().c_str());
    FilesToRemove.pop_back();
  }

  if (std::find(IntSigs, IntSigsEnd, Sig) != IntSigsEnd)
    exit(1);   // If this is an interrupt signal, exit the program

  // Otherwise if it is a fault (like SEGV) output the stacktrace to
  // STDERR (if we can) and reissue the signal to die...
  PrintStackTrace();
  signal(Sig, SIG_DFL);
}

static void RegisterHandler(int Signal) { signal(Signal, SignalHandler); }

// RemoveFileOnSignal - The public API
void llvm::RemoveFileOnSignal(const std::string &Filename) {
  FilesToRemove.push_back(Filename);

  std::for_each(IntSigs, IntSigsEnd, RegisterHandler);
  std::for_each(KillSigs, KillSigsEnd, RegisterHandler);
}

/// PrintStackTraceOnErrorSignal - When an error signal (such as SIBABRT or
/// SIGSEGV) is delivered to the process, print a stack trace and then exit.
void llvm::PrintStackTraceOnErrorSignal() {
  std::for_each(KillSigs, KillSigsEnd, RegisterHandler);
}
<|endoftext|>


<commit_before>// Copyright (c) 2019 by Robert Bosch GmbH. All rights reserved.
//
// 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.
#ifndef IOX_POSH_ROUDI_INTROSPECTION_PORT_INTROSPECTION_HPP
#define IOX_POSH_ROUDI_INTROSPECTION_PORT_INTROSPECTION_HPP

#include "fixed_size_container.hpp"
#include "iceoryx_posh/iceoryx_posh_types.hpp"
#include "iceoryx_posh/internal/popo/ports/publisher_port_data.hpp"
#include "iceoryx_posh/internal/popo/ports/publisher_port_user.hpp"
#include "iceoryx_posh/mepoo/chunk_header.hpp"
#include "iceoryx_posh/roudi/introspection_types.hpp"
#include "iceoryx_utils/cxx/helplets.hpp"
#include "iceoryx_utils/platform/pthread.hpp"

#include <atomic>
#include <mutex>
#include <thread>
#include <vector>

#include <map>

namespace iox
{
namespace roudi
{
/**
 * @brief This class handles the port intropection for RouDi.
 *        It is recommended to use the PortIntrospectionType alias which sets
 *        the intended template parameter required for the actual introspection.
 *
 *        The class manages a thread that periodically updates a field with port
 *        introspection data to which clients may subscribe.
 */
template <typename PublisherPort, typename SubscriberPort>
class PortIntrospection
{
  private:
    enum class ConnectionState
    {
        DEFAULT,
        SUB_REQUESTED,
        CONNECTED
    };

    using PortIntrospectionTopic = PortIntrospectionFieldTopic;
    using PortThroughputIntrospectionTopic = PortThroughputIntrospectionFieldTopic;

    class PortData
    {
      private:
        // internal helper classes

        struct ConnectionInfo;

        struct PublisherInfo
        {
            PublisherInfo() = default;

            PublisherInfo(typename PublisherPort::MemberType_t* const portData,
                          const ProcessName_t& name,
                          const capro::ServiceDescription& service,
                          const NodeName_t& node)
                : portData(portData)
                , name(name)
                , service(service)
                , node(node)
            {
            }

            typename PublisherPort::MemberType_t* portData{nullptr};
            ProcessName_t name;
            capro::ServiceDescription service;
            NodeName_t node;

            using TimePointNs_t = mepoo::TimePointNs_t;
            using DurationNs_t = mepoo::DurationNs_t;
            TimePointNs_t m_sequenceNumberTimestamp {DurationNs_t(0)};
            mepoo::SequenceNumber_t m_sequenceNumber{0};

            // map from indices to object pointers
            std::map<int, ConnectionInfo*> connectionMap;
            int index{-1};
        };

        struct SubscriberInfo
        {
            SubscriberInfo()
            {
            }

            SubscriberInfo(typename SubscriberPort::MemberType_t* const portData,
                           const ProcessName_t& name,
                           const capro::ServiceDescription& service,
                           const NodeName_t& node)
                : portData(portData)
                , name(name)
                , service(service)
                , node(node)
            {
            }

            typename SubscriberPort::MemberType_t* portData{nullptr};
            ProcessName_t name;
            capro::ServiceDescription service;
            NodeName_t node;
        };

        struct ConnectionInfo
        {
            ConnectionInfo()
            {
            }

            ConnectionInfo(typename SubscriberPort::MemberType_t* const portData,
                           const ProcessName_t& name,
                           const capro::ServiceDescription& service,
                           const NodeName_t& node)
                : subscriberInfo(portData, name, service, node)
                , state(ConnectionState::DEFAULT)
            {
            }

            ConnectionInfo(SubscriberInfo& subscriberInfo)
                : subscriberInfo(subscriberInfo)
                , state(ConnectionState::DEFAULT)
            {
            }

            SubscriberInfo subscriberInfo;
            PublisherInfo* publisherInfo{nullptr};
            ConnectionState state{ConnectionState::DEFAULT};

            bool isConnected()
            {
                return publisherInfo && state == ConnectionState::CONNECTED;
            }
        };

      public:
        PortData();

        /*!
         * @brief add a publisher port to be tracked by introspection
         * there cannot be multiple publisher ports with the same capro id
         *
         * @param[in] port to be added
         * @param[in] name of the port to be added
         * @param[in] service capro service description of the port to be added
         * @param[in] name of the node the port belongs to
         *
         * @return returns false if the port could not be added and true otherwise
         */
        bool addPublisher(typename PublisherPort::MemberType_t* const port,
                          const ProcessName_t& name,
                          const capro::ServiceDescription& service,
                          const NodeName_t& node);

        /*!
         * @brief add a subscriber port to be tracked by introspection
         * multiple subscribers with the same capro id are possible as long as the names are different
         *
         * @param[in] portData to be added
         * @param[in] name name of the port to be added
         * @param[in] service capro service description of the port to be added
         * @param[in] name of the node the port belongs to
         *
         * @return returns false if the port could not be added and true otherwise
         */
        bool addSubscriber(typename SubscriberPort::MemberType_t* const portData,
                           const ProcessName_t& name,
                           const capro::ServiceDescription& service,
                           const NodeName_t& node);

        /*!
         * @brief remove a publisher port from introspection
         *
         * @param[in] name name of the port to be added
         * @param[in] service capro service description of the port to be added
         *
         * @return returns false if the port could not be removed (since it did not exist)
         *              and true otherwise
         */
        bool removePublisher(const ProcessName_t& name, const capro::ServiceDescription& service);

        /*!
         * @brief remove a subscriber port from introspection
         *
         * @param[in] name name of the port to be added
         * @param[in] service capro service description of the port to be added
         *
         * @return returns false if the port could not be removed (since it did not exist)
         *              and true otherwise
         */
        bool removeSubscriber(const ProcessName_t& name, const capro::ServiceDescription& service);

        /*!
         * @brief update the state of any connection identified by the capro id of a given message
         *        according to the message type (e.g. capro:SUB for a subscription request)
         *
         * @param[in] message capro message to be processed
         *
         * @return returns false there is no corresponding capro service and true otherwise
         */
        bool updateConnectionState(const capro::CaproMessage& message);

        /*!
         * @brief prepare the topic to be send based on the internal connection state of all tracked ports
         *
         * @param[out] topic data structure to be prepared for sending
         *
         */
        void prepareTopic(PortIntrospectionTopic& topic);

        void prepareTopic(PortThroughputIntrospectionTopic& topic);

        void prepareTopic(SubscriberPortChangingIntrospectionFieldTopic& topic);

        /*!
         * @brief compute the next connection state based on the current connection state and a capro message type
         *
         * @param[in] currentState current connection state (e.g. CONNECTED)
         * @param[in] messageType capro message type
         *
         * @return returns the new connection state
         */
        PortIntrospection::ConnectionState getNextState(ConnectionState currentState,
                                                        capro::CaproMessageType messageType);

        /*!
         * @brief indicates whether the logical object state has changed (i.e. the data is new)
         *
         * @return returns true if the data is new(e.g. new connections were established), false otherwise
         */
        bool isNew();

        /*!
         * @brief sets the internal flag indicating new data
         *
         * @param[in] value value to be set
         */
        void setNew(bool value);

      private:
        using PublisherContainer = FixedSizeContainer<PublisherInfo, MAX_PUBLISHERS>;
        using ConnectionContainer = FixedSizeContainer<ConnectionInfo, MAX_SUBSCRIBERS>;

        // index publisher and connections by capro Ids
        std::map<capro::ServiceDescription, typename PublisherContainer::Index_t> m_publisherMap;

        // TODO: replace inner map wih more approriate structure if possible
        // inner map maps from process names to indices in the ConnectionContainer
        std::map<capro::ServiceDescription, std::map<ProcessName_t, typename ConnectionContainer::Index_t>>
            m_connectionMap;

        // Rationale: we avoid allocating the objects on the heap but can still use a map
        // to locate/remove them fast(er)
        // max number needs to be a compile time constant
        PublisherContainer m_publisherContainer;
        ConnectionContainer m_connectionContainer;

        std::atomic<bool> m_newData;
        std::mutex m_mutex;
    };

    // end of helper classes

  public:
    PortIntrospection();

    ~PortIntrospection();

    // delete copy constructor and assignment operator
    PortIntrospection(PortIntrospection const&) = delete;
    PortIntrospection& operator=(PortIntrospection const&) = delete;
    // delete move constructor and assignment operator
    PortIntrospection(PortIntrospection&&) = delete;
    PortIntrospection& operator=(PortIntrospection&&) = delete;

    /*!
     * @brief add a publisher port to be tracked by introspection
     * there cannot be multiple publisher ports with the same capro id
     *
     * @param[in] port to be added
     * @param[in] name of the port to be added
     * @param[in] service capro service description of the port to be added
     * @param[in] name of the node the port belongs to
     *
     * @return returns false if the port could not be added and true otherwise
     */
    bool addPublisher(typename PublisherPort::MemberType_t* port,
                      const ProcessName_t& name,
                      const capro::ServiceDescription& service,
                      const NodeName_t& node);

    /*!
     * @brief add a subscriber port to be tracked by introspection
     * multiple subscribers with the same capro id are possible as long as the names are different
     *
     * @param[in] port to be added
     * @param[in] name name of the port to be added
     * @param[in] service capro service description of the port to be added
     * @param[in] name of the node the port belongs to
     *
     * @return returns false if the port could not be added and true otherwise
     */
    bool addSubscriber(typename SubscriberPort::MemberType_t* port,
                       const ProcessName_t& name,
                       const capro::ServiceDescription& service,
                       const NodeName_t& node);

    /*!
     * @brief remove a publisher port from introspection
     *
     * @param[in] name name of the port to be added
     * @param[in] service capro service description of the port to be added
     *
     * @return returns false if the port could not be removed (since it did not exist)
     *              and true otherwise
     */
    bool removePublisher(const ProcessName_t& name, const capro::ServiceDescription& service);

    /*!
     * @brief remove a subscriber port from introspection
     *
     * @param[in] name name of the port to be added
     * @param[in] service capro service description of the port to be added
     *
     * @return returns false if the port could not be removed (since it did not exist)
     *              and true otherwise
     */
    bool removeSubscriber(const ProcessName_t& name, const capro::ServiceDescription& service);

    /*!
     * @brief report a capro message to introspection (since this could change the state of active connections)
     *
     * @param[in] message capro message to be processed
     *
     */
    void reportMessage(const capro::CaproMessage& message);

    /*!
     * @brief register publisher port used to send introspection
     *
     * @param[in] publisherPort publisher port to be registered
     *
     * @return true if registration was successful, false otherwise
     */
    bool registerPublisherPort(PublisherPort&& publisherPortGeneric,
                               PublisherPort&& publisherPortThroughput,
                               PublisherPort&& publisherPortSubscriberPortsData);

    /*!
     * @brief set the time interval used to send new introspection data
     *
     * @param[in] sendIntervalMs time interval in ms
     *
     */
    void setSendInterval(unsigned int sendIntervalMs);

    /*!
     * @brief start the internal send thread
     *
     */
    void run();

    /*!
     * @brief stop the internal send thread
     *
     */
    void stop();

  protected:
    /*!
     * @brief sends the port data; this is used from the unittests
     *
     */
    void sendPortData();
    /*!
     * @brief sends the throughput data; this is used from the unittests
     *
     */
    void sendThroughputData();
    /*!
     * @brief sends the subscriberport changing data, this is used from the unittests
     *
     */
    void sendSubscriberPortsData();

  protected:
    cxx::optional<PublisherPort> m_publisherPort;
    cxx::optional<PublisherPort> m_publisherPortThroughput;
    cxx::optional<PublisherPort> m_publisherPortSubscriberPortsData;

  private:
    PortData m_portData;

    std::atomic<bool> m_runThread;
    std::thread m_thread;

    unsigned int m_sendIntervalCount{10};
    const std::chrono::milliseconds m_sendIntervalSleep{100};
};

/**
 * @brief typedef for the templated port introspection class that is used by RouDi for the
 * actual port introspection functionality.
 */
using PortIntrospectionType = PortIntrospection<PublisherPortUserType, SubscriberPortUserType>;

} // namespace roudi
} // namespace iox

#include "port_introspection.inl"

#endif // IOX_POSH_ROUDI_INTROSPECTION_PORT_INTROSPECTION_HPP
<commit_msg>iox-#14 add `U` postfix to literals<commit_after>// Copyright (c) 2019 by Robert Bosch GmbH. All rights reserved.
//
// 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.
#ifndef IOX_POSH_ROUDI_INTROSPECTION_PORT_INTROSPECTION_HPP
#define IOX_POSH_ROUDI_INTROSPECTION_PORT_INTROSPECTION_HPP

#include "fixed_size_container.hpp"
#include "iceoryx_posh/iceoryx_posh_types.hpp"
#include "iceoryx_posh/internal/popo/ports/publisher_port_data.hpp"
#include "iceoryx_posh/internal/popo/ports/publisher_port_user.hpp"
#include "iceoryx_posh/mepoo/chunk_header.hpp"
#include "iceoryx_posh/roudi/introspection_types.hpp"
#include "iceoryx_utils/cxx/helplets.hpp"
#include "iceoryx_utils/platform/pthread.hpp"

#include <atomic>
#include <mutex>
#include <thread>
#include <vector>

#include <map>

namespace iox
{
namespace roudi
{
/**
 * @brief This class handles the port intropection for RouDi.
 *        It is recommended to use the PortIntrospectionType alias which sets
 *        the intended template parameter required for the actual introspection.
 *
 *        The class manages a thread that periodically updates a field with port
 *        introspection data to which clients may subscribe.
 */
template <typename PublisherPort, typename SubscriberPort>
class PortIntrospection
{
  private:
    enum class ConnectionState
    {
        DEFAULT,
        SUB_REQUESTED,
        CONNECTED
    };

    using PortIntrospectionTopic = PortIntrospectionFieldTopic;
    using PortThroughputIntrospectionTopic = PortThroughputIntrospectionFieldTopic;

    class PortData
    {
      private:
        // internal helper classes

        struct ConnectionInfo;

        struct PublisherInfo
        {
            PublisherInfo() = default;

            PublisherInfo(typename PublisherPort::MemberType_t* const portData,
                          const ProcessName_t& name,
                          const capro::ServiceDescription& service,
                          const NodeName_t& node)
                : portData(portData)
                , name(name)
                , service(service)
                , node(node)
            {
            }

            typename PublisherPort::MemberType_t* portData{nullptr};
            ProcessName_t name;
            capro::ServiceDescription service;
            NodeName_t node;

            using TimePointNs_t = mepoo::TimePointNs_t;
            using DurationNs_t = mepoo::DurationNs_t;
            TimePointNs_t m_sequenceNumberTimestamp {DurationNs_t(0)};
            mepoo::SequenceNumber_t m_sequenceNumber{0U};

            // map from indices to object pointers
            std::map<int, ConnectionInfo*> connectionMap;
            int index{-1};
        };

        struct SubscriberInfo
        {
            SubscriberInfo()
            {
            }

            SubscriberInfo(typename SubscriberPort::MemberType_t* const portData,
                           const ProcessName_t& name,
                           const capro::ServiceDescription& service,
                           const NodeName_t& node)
                : portData(portData)
                , name(name)
                , service(service)
                , node(node)
            {
            }

            typename SubscriberPort::MemberType_t* portData{nullptr};
            ProcessName_t name;
            capro::ServiceDescription service;
            NodeName_t node;
        };

        struct ConnectionInfo
        {
            ConnectionInfo()
            {
            }

            ConnectionInfo(typename SubscriberPort::MemberType_t* const portData,
                           const ProcessName_t& name,
                           const capro::ServiceDescription& service,
                           const NodeName_t& node)
                : subscriberInfo(portData, name, service, node)
                , state(ConnectionState::DEFAULT)
            {
            }

            ConnectionInfo(SubscriberInfo& subscriberInfo)
                : subscriberInfo(subscriberInfo)
                , state(ConnectionState::DEFAULT)
            {
            }

            SubscriberInfo subscriberInfo;
            PublisherInfo* publisherInfo{nullptr};
            ConnectionState state{ConnectionState::DEFAULT};

            bool isConnected()
            {
                return publisherInfo && state == ConnectionState::CONNECTED;
            }
        };

      public:
        PortData();

        /*!
         * @brief add a publisher port to be tracked by introspection
         * there cannot be multiple publisher ports with the same capro id
         *
         * @param[in] port to be added
         * @param[in] name of the port to be added
         * @param[in] service capro service description of the port to be added
         * @param[in] name of the node the port belongs to
         *
         * @return returns false if the port could not be added and true otherwise
         */
        bool addPublisher(typename PublisherPort::MemberType_t* const port,
                          const ProcessName_t& name,
                          const capro::ServiceDescription& service,
                          const NodeName_t& node);

        /*!
         * @brief add a subscriber port to be tracked by introspection
         * multiple subscribers with the same capro id are possible as long as the names are different
         *
         * @param[in] portData to be added
         * @param[in] name name of the port to be added
         * @param[in] service capro service description of the port to be added
         * @param[in] name of the node the port belongs to
         *
         * @return returns false if the port could not be added and true otherwise
         */
        bool addSubscriber(typename SubscriberPort::MemberType_t* const portData,
                           const ProcessName_t& name,
                           const capro::ServiceDescription& service,
                           const NodeName_t& node);

        /*!
         * @brief remove a publisher port from introspection
         *
         * @param[in] name name of the port to be added
         * @param[in] service capro service description of the port to be added
         *
         * @return returns false if the port could not be removed (since it did not exist)
         *              and true otherwise
         */
        bool removePublisher(const ProcessName_t& name, const capro::ServiceDescription& service);

        /*!
         * @brief remove a subscriber port from introspection
         *
         * @param[in] name name of the port to be added
         * @param[in] service capro service description of the port to be added
         *
         * @return returns false if the port could not be removed (since it did not exist)
         *              and true otherwise
         */
        bool removeSubscriber(const ProcessName_t& name, const capro::ServiceDescription& service);

        /*!
         * @brief update the state of any connection identified by the capro id of a given message
         *        according to the message type (e.g. capro:SUB for a subscription request)
         *
         * @param[in] message capro message to be processed
         *
         * @return returns false there is no corresponding capro service and true otherwise
         */
        bool updateConnectionState(const capro::CaproMessage& message);

        /*!
         * @brief prepare the topic to be send based on the internal connection state of all tracked ports
         *
         * @param[out] topic data structure to be prepared for sending
         *
         */
        void prepareTopic(PortIntrospectionTopic& topic);

        void prepareTopic(PortThroughputIntrospectionTopic& topic);

        void prepareTopic(SubscriberPortChangingIntrospectionFieldTopic& topic);

        /*!
         * @brief compute the next connection state based on the current connection state and a capro message type
         *
         * @param[in] currentState current connection state (e.g. CONNECTED)
         * @param[in] messageType capro message type
         *
         * @return returns the new connection state
         */
        PortIntrospection::ConnectionState getNextState(ConnectionState currentState,
                                                        capro::CaproMessageType messageType);

        /*!
         * @brief indicates whether the logical object state has changed (i.e. the data is new)
         *
         * @return returns true if the data is new(e.g. new connections were established), false otherwise
         */
        bool isNew();

        /*!
         * @brief sets the internal flag indicating new data
         *
         * @param[in] value value to be set
         */
        void setNew(bool value);

      private:
        using PublisherContainer = FixedSizeContainer<PublisherInfo, MAX_PUBLISHERS>;
        using ConnectionContainer = FixedSizeContainer<ConnectionInfo, MAX_SUBSCRIBERS>;

        // index publisher and connections by capro Ids
        std::map<capro::ServiceDescription, typename PublisherContainer::Index_t> m_publisherMap;

        // TODO: replace inner map wih more approriate structure if possible
        // inner map maps from process names to indices in the ConnectionContainer
        std::map<capro::ServiceDescription, std::map<ProcessName_t, typename ConnectionContainer::Index_t>>
            m_connectionMap;

        // Rationale: we avoid allocating the objects on the heap but can still use a map
        // to locate/remove them fast(er)
        // max number needs to be a compile time constant
        PublisherContainer m_publisherContainer;
        ConnectionContainer m_connectionContainer;

        std::atomic<bool> m_newData;
        std::mutex m_mutex;
    };

    // end of helper classes

  public:
    PortIntrospection();

    ~PortIntrospection();

    // delete copy constructor and assignment operator
    PortIntrospection(PortIntrospection const&) = delete;
    PortIntrospection& operator=(PortIntrospection const&) = delete;
    // delete move constructor and assignment operator
    PortIntrospection(PortIntrospection&&) = delete;
    PortIntrospection& operator=(PortIntrospection&&) = delete;

    /*!
     * @brief add a publisher port to be tracked by introspection
     * there cannot be multiple publisher ports with the same capro id
     *
     * @param[in] port to be added
     * @param[in] name of the port to be added
     * @param[in] service capro service description of the port to be added
     * @param[in] name of the node the port belongs to
     *
     * @return returns false if the port could not be added and true otherwise
     */
    bool addPublisher(typename PublisherPort::MemberType_t* port,
                      const ProcessName_t& name,
                      const capro::ServiceDescription& service,
                      const NodeName_t& node);

    /*!
     * @brief add a subscriber port to be tracked by introspection
     * multiple subscribers with the same capro id are possible as long as the names are different
     *
     * @param[in] port to be added
     * @param[in] name name of the port to be added
     * @param[in] service capro service description of the port to be added
     * @param[in] name of the node the port belongs to
     *
     * @return returns false if the port could not be added and true otherwise
     */
    bool addSubscriber(typename SubscriberPort::MemberType_t* port,
                       const ProcessName_t& name,
                       const capro::ServiceDescription& service,
                       const NodeName_t& node);

    /*!
     * @brief remove a publisher port from introspection
     *
     * @param[in] name name of the port to be added
     * @param[in] service capro service description of the port to be added
     *
     * @return returns false if the port could not be removed (since it did not exist)
     *              and true otherwise
     */
    bool removePublisher(const ProcessName_t& name, const capro::ServiceDescription& service);

    /*!
     * @brief remove a subscriber port from introspection
     *
     * @param[in] name name of the port to be added
     * @param[in] service capro service description of the port to be added
     *
     * @return returns false if the port could not be removed (since it did not exist)
     *              and true otherwise
     */
    bool removeSubscriber(const ProcessName_t& name, const capro::ServiceDescription& service);

    /*!
     * @brief report a capro message to introspection (since this could change the state of active connections)
     *
     * @param[in] message capro message to be processed
     *
     */
    void reportMessage(const capro::CaproMessage& message);

    /*!
     * @brief register publisher port used to send introspection
     *
     * @param[in] publisherPort publisher port to be registered
     *
     * @return true if registration was successful, false otherwise
     */
    bool registerPublisherPort(PublisherPort&& publisherPortGeneric,
                               PublisherPort&& publisherPortThroughput,
                               PublisherPort&& publisherPortSubscriberPortsData);

    /*!
     * @brief set the time interval used to send new introspection data
     *
     * @param[in] sendIntervalMs time interval in ms
     *
     */
    void setSendInterval(unsigned int sendIntervalMs);

    /*!
     * @brief start the internal send thread
     *
     */
    void run();

    /*!
     * @brief stop the internal send thread
     *
     */
    void stop();

  protected:
    /*!
     * @brief sends the port data; this is used from the unittests
     *
     */
    void sendPortData();
    /*!
     * @brief sends the throughput data; this is used from the unittests
     *
     */
    void sendThroughputData();
    /*!
     * @brief sends the subscriberport changing data, this is used from the unittests
     *
     */
    void sendSubscriberPortsData();

  protected:
    cxx::optional<PublisherPort> m_publisherPort;
    cxx::optional<PublisherPort> m_publisherPortThroughput;
    cxx::optional<PublisherPort> m_publisherPortSubscriberPortsData;

  private:
    PortData m_portData;

    std::atomic<bool> m_runThread;
    std::thread m_thread;

    unsigned int m_sendIntervalCount{10};
    const std::chrono::milliseconds m_sendIntervalSleep{100};
};

/**
 * @brief typedef for the templated port introspection class that is used by RouDi for the
 * actual port introspection functionality.
 */
using PortIntrospectionType = PortIntrospection<PublisherPortUserType, SubscriberPortUserType>;

} // namespace roudi
} // namespace iox

#include "port_introspection.inl"

#endif // IOX_POSH_ROUDI_INTROSPECTION_PORT_INTROSPECTION_HPP
<|endoftext|>