Fail* directories reorganized, Code-cleanup (-> coding-style), Typos+comments fixed.

git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@1321 8c4709b5-6ec9-48aa-a5cd-a96041d1645a
This commit is contained in:
adrian
2012-06-08 20:09:43 +00:00
parent d474a5b952
commit 2575604b41
866 changed files with 1848 additions and 1879 deletions

View File

@ -0,0 +1,10 @@
set(SRCS
SynchronizedCounter.cc
Logger.hpp
Logger.cc
ProtoStream.cc
)
add_library(util ${SRCS})
# FIXME: Add protobuf-dependency (required by ProtoStream.cc@line56)

26
src/core/util/Logger.cc Normal file
View File

@ -0,0 +1,26 @@
#include <sstream>
#include <fstream>
#include <time.h>
#include "Logger.hpp"
namespace fail {
void Logger::timestamp()
{
(*m_pDest) << "[" << m_description;
if (m_showTime) {
time_t rawtime;
struct tm* timeinfo;
char buffer[80];
time(&rawtime);
timeinfo = localtime(&rawtime);
strftime(buffer, 80, "%H:%M:%S", timeinfo);
(*m_pDest) << " " << buffer;
}
(*m_pDest) << "] ";
}
} // end-of-namespace: fail

53
src/core/util/Logger.hpp Normal file
View File

@ -0,0 +1,53 @@
#ifndef __LOGGER_HPP__
#define __LOGGER_HPP__
#include <iostream>
#include <sstream>
namespace fail {
/**
* \class Logger
* Provides logging mechanisms.
*/
class Logger {
private:
std::ostream* m_pDest;
std::string m_description;
bool m_showTime;
void timestamp();
public:
/**
* Constructor.
* @param description Description shown alongside each log entry in
* square brackets [ ]. Can be overridden in single add() calls.
* @param show_time Show a timestamp with each log entry.
* @param dest Stream to log into.
*/
Logger(const std::string& description = "Fail*", bool show_time = true,
std::ostream& dest = std::cout)
: m_pDest(&dest), m_description(description), m_showTime(show_time) { }
/**
* Change the default description which is shown alongside each log
* entry in square brackets [ ].
* @param descr The description text.
*/
void setDescription(const std::string& descr) { m_description = descr; }
/**
* Change the default option of show_time which shows a timestamp
* each log entry.
* @param choice The choice for show_time
*/
void showTime(bool choice) { m_showTime = choice; }
/**
* Add a new log entry.
* @param v data to log
* @return a \c std::ostream reference to continue streaming a longer log entry
*/
template<class T>
inline std::ostream& operator <<(const T& v) { timestamp(); return (*m_pDest) << v; }
};
} // end-of-namespace: fail
#endif // __LOGGER_HPP__

View File

@ -0,0 +1,80 @@
#ifndef __MEMORYMAP_HPP__
#define __MEMORYMAP_HPP__
#ifdef BOOST_1_46_OR_NEWER
#include <boost/icl/interval_set.hpp>
using namespace boost::icl;
#endif
#include <set>
#include "sal/SALConfig.hpp"
namespace fail {
/**
* \class MemoryMap
* An efficient container for memory maps with holes.
*/
class MemoryMap {
private:
#ifdef BOOST_1_46_OR_NEWER
typedef interval<address_t>::type address_interval;
typedef interval_set<address_t>::type address_set;
address_set as;
public:
MemoryMap() { }
void clear() { as.clear(); }
void add(address_t addr, int size) { as.add(address_interval(addr, addr+size-1)); }
void isMatching(address_t addr, int size) { return intersects(as, address_interval(addr, addr+size-1)); }
#endif
std::set<address_t> as;
public:
MemoryMap() { }
/**
* Clears the map.
*/
void clear() { as.clear(); }
/**
* Adds one or a sequence of addresses to the map.
*/
void add(address_t addr, int size = 1)
{
for (int i = 0; i < size; ++i) {
as.insert(addr + i);
}
}
/**
* Determines whether a given memory access at address \a addr with width
* \a size hits the map.
*/
bool isMatching(address_t addr, int size = 1)
{
for (int i = 0; i < size; ++i) {
if (as.find(addr + i) != as.end()) {
return true;
}
}
return false;
}
/**
* The (STL-style) iterator of this class used to iterate over all
* addresses in this map.
*/
typedef std::set<address_t>::iterator iterator;
/**
* Returns an (STL-style) iterator to the beginning of the internal data
* structure.
*/
iterator begin() { return as.begin(); }
/**
* Returns an (STL-style) iterator to the end of the interal data
* structure.
*/
iterator end() { return as.end(); }
};
} // end-of-namespace: fail
#endif // __MEMORYMAP_HPP__

View File

@ -0,0 +1,62 @@
#include "ProtoStream.hpp"
namespace fail {
ProtoOStream::ProtoOStream(std::ostream *outfile) : m_outfile(outfile)
{
m_log.setDescription("ProtoStream");
// TODO: log-Level?
m_log.showTime(false);
}
bool ProtoOStream::writeMessage(google::protobuf::Message* m)
{
m_size = htonl(m->ByteSize());
m_outfile->write(reinterpret_cast<char*>(&m_size), sizeof(m_size));
if (m_outfile->bad()) {
m_log << "Could not write to file!" << std::endl;
// TODO: log-Level?
return false;
}
m->SerializeToOstream(m_outfile);
return true;
}
ProtoIStream::ProtoIStream(std::istream *infile) : m_infile(infile)
{
m_log.setDescription("ProtoStream");
// TODO: log-Level?
m_log.showTime(false);
}
void ProtoIStream::reset()
{
m_infile->clear();
m_infile->seekg(0, std::ios::beg);
}
bool ProtoIStream::getNext(google::protobuf::Message* m)
{
m_infile->read(reinterpret_cast<char*>(&m_size), sizeof(m_size));
if (!m_infile->good())
return false;
m_size = ntohl(m_size);
// FIXME reuse buffer (efficiency)
// FIXME new[] may fail (i.e., return 0)
char *buf = new char[m_size];
m_infile->read(buf, m_size);
if (!m_infile->good())
// FIXME we're leaking buf[]
return false;
std::string st(buf, m_size);
m->ParseFromString(st);
delete [] buf;
return true;
}
} // end-of-namespace: fail

View File

@ -0,0 +1,81 @@
/**
* \brief One way to manage large protobuf-messages
*
* Google protobuf is not designed for large messages. That leads to
* much memory which is consumed by processing large messages. To
* solve this problem the ProtoStream class stores the protobuf-messages
* in an other way. Instead of using the repeat-function the data is
* written sequentially in a file. Written in the format:
*
* \code
* | 4 bytes length-information of the first message | first message
* | 4 bytes length-information of the second message | second message
* | ...
* \endcode
*/
#ifndef __PROTOSTREAM_HPP__
#define __PROTOSTREAM_HPP__
#include <iostream>
#include <sys/types.h>
#include <netinet/in.h>
#include <google/protobuf/message.h>
#include "Logger.hpp"
namespace fail {
/**
* \class ProtoOStream
*
* This class can be used to sequentially write a large number of
* protocol buffer messages to a \c std::ostream.
*/
class ProtoOStream {
private:
uint32_t m_size; // TODO: comments needed here
Logger m_log;
std::ostream* m_outfile;
public:
ProtoOStream(std::ostream *outfile);
virtual ~ProtoOStream() { }
/**
* Writes a message to a file.
* @param m The protobuf-message to be written
* @return Returns \c true on success, \c false otherwise
*/
bool writeMessage(google::protobuf::Message* m);
};
/**
* \class ProtoIStream
*
* This class can be used to read protocol buffer messages sequentially
* from a \c std::istream.
*/
class ProtoIStream {
private:
uint32_t m_size; // TODO: comments needed here
long m_sizeOfInfile;
Logger m_log;
std::istream *m_infile;
public:
ProtoIStream(std::istream *infile);
virtual ~ProtoIStream() { }
/**
* Resets the position of the get pointer. After that \c getNext()
* reads the first message again.
*/
void reset();
/**
* Reads the next protobuf message from the input stream.
* @param m The output protobuf message
* @return Returns \c true on success, \c false otherwise
*/
bool getNext(google::protobuf::Message* m);
};
} // end-of-namespace: fail
#endif // __PROTOSTREAM_HPP__

View File

@ -0,0 +1,29 @@
#include "SynchronizedCounter.hpp"
namespace fail {
int SynchronizedCounter::increment()
{
#ifndef __puma
boost::unique_lock<boost::mutex> lock(m_mutex);
#endif
return ++m_counter;
}
int SynchronizedCounter::decrement()
{
#ifndef __puma
boost::unique_lock<boost::mutex> lock(m_mutex);
#endif
return --m_counter;
}
int SynchronizedCounter::getValue()
{
#ifndef __puma
boost::unique_lock<boost::mutex> lock(m_mutex);
#endif
return m_counter;
}
} // end-of-namespace: fail

View File

@ -0,0 +1,38 @@
/**
* \brief Thread safe (synchronized) counter.
*/
#ifndef __SYNCHRONIZED_COUNTER_HPP__
#define __SYNCHRONIZED_COUNTER_HPP__
#ifndef __puma
#include <boost/thread.hpp>
#include <sys/types.h>
#endif
namespace fail {
/**
* \class ssd
*
* Provides a thread safe (synchronized) counter. When a method is called,
* the internal mutex is automatically locked. On return, the lock is
* automatically released ("scoped lock").
*/
class SynchronizedCounter {
private:
int m_counter;
#ifndef __puma
boost::mutex m_mutex; //! The mutex to synchronise on
#endif
public:
SynchronizedCounter() : m_counter(0) { }
int increment();
int decrement();
int getValue();
};
} // end-of-namespace: fail
#endif // __SYNCHRONIZED_COUNTER_HPP__

View File

@ -0,0 +1,116 @@
/**
* \brief Map class that has thread synchronisation
*/
#ifndef __SYNCHRONIZED_MAP_HPP__
#define __SYNCHRONIZED_MAP_HPP__
#include <map>
#ifndef __puma
#include <boost/thread.hpp>
#endif
// TODO: We should consider to use Aspects for synchronisation primitives.
namespace fail {
template <typename Tkey, typename Tvalue>
class SynchronizedMap {
private:
typedef std::map< Tkey, Tvalue > Tmap;
typedef typename Tmap::iterator Tit;
Tmap m_map; //! Use STL map to store data
#ifndef __puma
boost::mutex m_mutex; //! The mutex to synchronise on
#endif
int nextpick;
enum { pick_window_size = 500 };
public:
SynchronizedMap() : nextpick(0) { }
int Size()
{
#ifndef __puma
boost::unique_lock<boost::mutex> lock(m_mutex);
#endif
return m_map.size();
}
/**
* Retrieves one element from the map from a small window at the beginning.
* @return a pointer to the element, or \c NULL if empty
*/
Tvalue pickone()
{
#ifndef __puma
boost::unique_lock<boost::mutex> lock(m_mutex);
#endif
if (m_map.size() == 0) {
return NULL;
}
// XXX not really elegant: linear complexity
typename Tmap::iterator it = m_map.begin();
for (int i = 0; i < nextpick; ++i) {
++it;
if (it == m_map.end()) {
it = m_map.begin();
nextpick = 0;
break;
}
}
++nextpick;
if (nextpick >= pick_window_size) {
nextpick = 0;
}
return it->second;
} // Lock is automatically released here
/**
* Add data to the map, return false if already present
* @param key Map key
* @param value value according to key
* @return false if key already present
*/
bool insert(const Tkey& key, const Tvalue& value)
{
// Acquire lock on the queue
#ifndef __puma
boost::unique_lock<boost::mutex> lock(m_mutex);
#endif
if( m_map.find(key) == m_map.end() ){ // not present, add it
m_map[key] = value;
return true;
}else{ // item is already in, oops
return false;
}
} // Lock is automatically released here
/**
* Remove value from the map.
* @param key The Map key to remove
* @return false if key was not present
*
*/
bool remove(const Tkey& key, Tvalue& value)
{
// Acquire lock on the queue
#ifndef __puma
boost::unique_lock<boost::mutex> lock(m_mutex);
#endif
Tit iterator;
if ((iterator = m_map.find(key)) != m_map.end()) {
value = iterator->second;
m_map.erase(iterator);
return true;
} else {
return false;
}
} // Lock is automatically released here
};
} // end-of-namespace: fail
#endif // __SYNCHRONIZED_MAP_HPP__

View File

@ -0,0 +1,96 @@
/**
* \brief Queue class that has thread synchronisation.
*/
#ifndef __SYNCHRONIZED_QUEUE_HPP__
#define __SYNCHRONIZED_QUEUE_HPP__
#include <queue>
#ifndef __puma
#include <boost/thread.hpp>
#endif
namespace fail {
template <typename T>
class SynchronizedQueue { // Adapted from: http://www.quantnet.com/cplusplus-multithreading-boost/
private:
std::queue<T> m_queue; //!< Use STL queue to store data
#ifndef __puma
boost::mutex m_mutex; //!< The mutex to synchronise on
boost::condition_variable m_cond; //!< The condition to wait for
#endif
public:
int Size()
{
#ifndef __puma
boost::unique_lock<boost::mutex> lock(m_mutex);
#endif
return m_queue.size();
}
// Add data to the queue and notify others
void Enqueue(const T& data)
{
// Acquire lock on the queue
#ifndef __puma
boost::unique_lock<boost::mutex> lock(m_mutex);
#endif
// Add the data to the queue
m_queue.push(data);
// Notify others that data is ready
#ifndef __puma
m_cond.notify_one();
#endif
} // Lock is automatically released here
/**
* Get data from the queue. Wait for data if not available
*/
T Dequeue()
{
// Acquire lock on the queue
#ifndef __puma
boost::unique_lock<boost::mutex> lock(m_mutex);
#endif
// When there is no data, wait till someone fills it.
// Lock is automatically released in the wait and obtained
// again after the wait
#ifndef __puma
while (m_queue.size() == 0)
m_cond.wait(lock);
#endif
// Retrieve the data from the queue
T result=m_queue.front(); m_queue.pop();
return result;
} // Lock is automatically released here
/**
* Get data from the queue. Non blocking variant.
* @param d Pointer to copy queue element to
* @return false if no element in queue
*
*/
bool Dequeue_nb(T& d)
{
// Acquire lock on the queue
#ifndef __puma
boost::unique_lock<boost::mutex> lock(m_mutex);
#endif
// When there is no data, return false.
// Lock is automatically released in the wait and obtained
// again after the wait
if (m_queue.size() > 0) {
// Retrieve the data from the queue
d = m_queue.front(); m_queue.pop();
return true;
} else {
return false;
}
} // Lock is automatically released here
};
} // end-of-namespace: fail
#endif // __SYNCHRONIZED_QUEUE_HPP__