import from yans

This commit is contained in:
Mathieu Lacage
2006-08-29 17:42:13 +02:00
parent ae6d55badc
commit 5c90e561b4
101 changed files with 12664 additions and 0 deletions

595
src/common/buffer.cc Normal file
View File

@@ -0,0 +1,595 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005,2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "buffer.h"
#include <cassert>
#include <iostream>
//#define TRACE(x) std::cout << x << std::endl;
#define TRACE(x)
namespace yans {
Buffer::BufferDataList Buffer::m_free_list;
uint32_t Buffer::m_max_total_add_start = 0;
uint32_t Buffer::m_max_total_add_end = 0;
struct Buffer::BufferData *
Buffer::allocate (uint32_t req_size, uint32_t req_start)
{
if (req_size == 0) {
req_size = 1;
}
assert (req_size >= 1);
uint32_t size = req_size - 1 + sizeof (struct Buffer::BufferData);
uint8_t *b = new uint8_t [size];
struct BufferData *data = reinterpret_cast<struct Buffer::BufferData*>(b);
data->m_size = req_size;
data->m_initial_start = req_start;
data->m_dirty_start = req_start;
data->m_dirty_size = 0;
data->m_count = 1;
return data;
}
void
Buffer::deallocate (struct Buffer::BufferData *data)
{
uint8_t *buf = reinterpret_cast<uint8_t *> (data);
delete [] buf;
}
#ifdef USE_FREE_LIST
void
Buffer::recycle (struct Buffer::BufferData *data)
{
assert (data->m_count == 0);
/* get rid of it if it is too small for later reuse. */
if (data->m_size < (Buffer::m_max_total_add_start + Buffer::m_max_total_add_end)) {
Buffer::deallocate (data);
return;
}
/* feed into free list */
if (Buffer::m_free_list.size () > 1000) {
Buffer::deallocate (data);
} else {
Buffer::m_free_list.push_back (data);
}
}
Buffer::BufferData *
Buffer::create (void)
{
/* try to find a buffer correctly sized. */
while (!Buffer::m_free_list.empty ()) {
struct Buffer::BufferData *data = Buffer::m_free_list.back ();
Buffer::m_free_list.pop_back ();
if (data->m_size >= (m_max_total_add_start + m_max_total_add_end)) {
data->m_initial_start = m_max_total_add_start;
data->m_dirty_start = m_max_total_add_start;
data->m_dirty_size = 0;
data->m_count = 1;
return data;
}
Buffer::deallocate (data);
}
struct Buffer::BufferData *data = Buffer::allocate (m_max_total_add_start+m_max_total_add_end,
m_max_total_add_start);
assert (data->m_count == 1);
return data;
}
#else
void
Buffer::recycle (struct Buffer::BufferData *data)
{
Buffer::deallocate (data);
}
Buffer::BufferData *
Buffer::create (void)
{
return Buffer::allocate (m_max_total_add_start+m_max_total_add_end,
m_max_total_add_start);
}
#endif
}; // namespace yans
#include <cassert>
namespace yans {
void
Buffer::add_at_start (uint32_t start)
{
assert (m_start <= m_data->m_initial_start);
bool is_dirty = m_data->m_count > 1 && m_start > m_data->m_dirty_start;
if (m_start >= start && !is_dirty) {
/* enough space in the buffer and not dirty. */
m_start -= start;
m_size += start;
} else if (m_size + start <= m_data->m_size && !is_dirty) {
/* enough space but need to move data around to fit new data */
memmove (m_data->m_data + start, get_start (), m_size);
assert (start > m_start);
m_data->m_initial_start += start;
m_start = 0;
m_size += start;
} else if (m_start < start) {
/* not enough space in buffer */
uint32_t new_size = m_size + start;
struct Buffer::BufferData *new_data = Buffer::allocate (new_size, 0);
memcpy (new_data->m_data + start, get_start (), m_size);
new_data->m_initial_start = m_data->m_initial_start + start;
m_data->m_count--;
if (m_data->m_count == 0) {
Buffer::deallocate (m_data);
}
m_data = new_data;
m_start = 0;
m_size = new_size;
} else {
/* enough space in the buffer but it is dirty ! */
assert (is_dirty);
struct Buffer::BufferData *new_data = Buffer::create ();
memcpy (new_data->m_data + m_start, get_start (), m_size);
new_data->m_initial_start = m_data->m_initial_start;
m_data->m_count--;
if (m_data->m_count == 0) {
recycle (m_data);
}
m_data = new_data;
m_start -= start;
m_size += start;
}
// update dirty area
m_data->m_dirty_start = m_start;
m_data->m_dirty_size = m_size;
// update m_max_total_add_start
uint32_t added_at_start;
if (m_data->m_initial_start > m_start) {
added_at_start = m_data->m_initial_start - m_start;
} else {
added_at_start = 0;
}
if (added_at_start > m_max_total_add_start) {
m_max_total_add_start = added_at_start;
}
TRACE ("start add="<<start<<", start="<<m_start<<", size="<<m_size<<", zero="<<m_zero_area_size<<
", real size="<<m_data->m_size<<", ini start="<<m_data->m_initial_start<<
", dirty start="<<m_data->m_dirty_start<<", dirty size="<<m_data->m_dirty_size);
}
void
Buffer::add_at_end (uint32_t end)
{
assert (m_start <= m_data->m_initial_start);
bool is_dirty = m_data->m_count > 1 &&
m_start + m_size < m_data->m_dirty_start + m_data->m_dirty_size;
if (m_start + m_size + end <= m_data->m_size && !is_dirty) {
/* enough space in buffer and not dirty */
m_size += end;
} else if (m_size + end <= m_data->m_size && !is_dirty) {
/* enough space but need to move data around to fit the extra data */
uint32_t new_start = m_data->m_size - (m_size + end);
memmove (m_data->m_data + new_start, get_start (), m_size);
assert (new_start < m_start);
m_data->m_initial_start -= m_start - new_start;
m_start = new_start;
m_size += end;
} else if (m_start + m_size + end > m_data->m_size) {
/* not enough space in buffer */
uint32_t new_size = m_size + end;
struct Buffer::BufferData *new_data = Buffer::allocate (new_size, 0);
memcpy (new_data->m_data, get_start (), m_size);
new_data->m_initial_start = m_data->m_initial_start;
m_data->m_count--;
if (m_data->m_count == 0) {
Buffer::deallocate (m_data);
}
m_data = new_data;
m_size = new_size;
m_start = 0;
} else {
/* enough space in the buffer but it is dirty ! */
assert (is_dirty);
struct Buffer::BufferData *new_data = Buffer::create ();
memcpy (new_data->m_data + m_start, get_start (), m_size);
new_data->m_initial_start = m_data->m_initial_start;
m_data->m_count--;
if (m_data->m_count == 0) {
recycle (m_data);
}
m_data = new_data;
m_size += end;
}
// update dirty area
m_data->m_dirty_start = m_start;
m_data->m_dirty_size = m_size;
// update m_max_total_add_end
uint32_t end_loc = m_start + m_size;
uint32_t added_at_end;
if (m_data->m_initial_start < end_loc) {
added_at_end = end_loc - m_data->m_initial_start;
} else {
added_at_end = 0;
}
if (added_at_end > m_max_total_add_end) {
m_max_total_add_end = added_at_end;
}
TRACE ("end add="<<end<<", start="<<m_start<<", size="<<m_size<<", zero="<<m_zero_area_size<<
", real size="<<m_data->m_size<<", ini start="<<m_data->m_initial_start<<
", dirty start="<<m_data->m_dirty_start<<", dirty size="<<m_data->m_dirty_size);
}
void
Buffer::remove_at_start (uint32_t start)
{
if (m_zero_area_size == 0) {
if (m_size <= start) {
m_start += m_size;
m_size = 0;
} else {
m_start += start;
m_size -= start;
}
} else {
assert (m_data->m_initial_start >= m_start);
uint32_t zero_start = m_data->m_initial_start - m_start;
uint32_t zero_end = zero_start + m_zero_area_size;
uint32_t data_end = m_size + m_zero_area_size;
if (start <= zero_start) {
/* only remove start of buffer */
m_start += start;
m_size -= start;
} else if (start <= zero_end) {
/* remove start of buffer _and_ start of zero area */
m_start += zero_start;
uint32_t zero_delta = start - zero_start;
m_zero_area_size -= zero_delta;
assert (zero_delta <= start);
m_size -= zero_start;
} else if (start <= data_end) {
/* remove start of buffer, complete zero area, and part
* of end of buffer */
m_start += start - m_zero_area_size;
m_size -= start - m_zero_area_size;
m_zero_area_size = 0;
} else {
/* remove all buffer */
m_start += m_size;
m_size = 0;
m_zero_area_size = 0;
}
}
TRACE ("start remove="<<start<<", start="<<m_start<<", size="<<m_size<<", zero="<<m_zero_area_size<<
", real size="<<m_data->m_size<<", ini start="<<m_data->m_initial_start<<
", dirty start="<<m_data->m_dirty_start<<", dirty size="<<m_data->m_dirty_size);
}
void
Buffer::remove_at_end (uint32_t end)
{
if (m_zero_area_size == 0) {
if (m_size <= end) {
m_size = 0;
} else {
m_size -= end;
}
} else {
assert (m_data->m_initial_start >= m_start);
uint32_t zero_start = m_data->m_initial_start - m_start;
uint32_t zero_end = zero_start + m_zero_area_size;
uint32_t data_end = m_size + m_zero_area_size;
assert (zero_start <= m_size);
assert (zero_end <= m_size + m_zero_area_size);
if (data_end <= end) {
/* remove all buffer */
m_zero_area_size = 0;
m_start += m_size;
m_size = 0;
} else if (data_end - zero_start <= end) {
/* remove end of buffer, zero area, part of start of buffer */
assert (end >= m_zero_area_size);
m_size -= end - m_zero_area_size;
m_zero_area_size = 0;
} else if (data_end - zero_end <= end) {
/* remove end of buffer, part of zero area */
uint32_t zero_delta = end - (data_end - zero_end);
m_zero_area_size -= zero_delta;
m_size -= end - zero_delta;
} else {
/* remove part of end of buffer */
m_size -= end;
}
}
TRACE ("end remove="<<end<<", start="<<m_start<<", size="<<m_size<<", zero="<<m_zero_area_size<<
", real size="<<m_data->m_size<<", ini start="<<m_data->m_initial_start<<
", dirty start="<<m_data->m_dirty_start<<", dirty size="<<m_data->m_dirty_size);
}
Buffer
Buffer::create_fragment (uint32_t start, uint32_t length) const
{
uint32_t zero_start = m_data->m_initial_start - m_start;
uint32_t zero_end = zero_start + m_zero_area_size;
if (m_zero_area_size != 0 &&
start + length > zero_start &&
start <= zero_end) {
transform_into_real_buffer ();
}
Buffer tmp = *this;
tmp.remove_at_start (start);
tmp.remove_at_end (get_size () - (start + length));
return tmp;
}
void
Buffer::transform_into_real_buffer (void) const
{
if (m_zero_area_size != 0) {
assert (m_data->m_initial_start >= m_start);
assert (m_size >= (m_data->m_initial_start - m_start));
Buffer tmp;
tmp.add_at_start (m_zero_area_size);
tmp.begin ().write_u8 (0, m_zero_area_size);
uint32_t data_start = m_data->m_initial_start - m_start;
tmp.add_at_start (data_start);
tmp.begin ().write (m_data->m_data+m_start, data_start);
uint32_t data_end = m_size - (m_data->m_initial_start - m_start);
tmp.add_at_end (data_end);
Buffer::Iterator i = tmp.end ();
i.prev (data_end);
i.write (m_data->m_data+m_data->m_initial_start,data_end);
*const_cast<Buffer *> (this) = tmp;
}
}
uint8_t *
Buffer::peek_data (void) const
{
transform_into_real_buffer ();
return m_data->m_data + m_start;
}
}; // namespace yans
#ifdef RUN_SELF_TESTS
#include "yans/test.h"
#include <iomanip>
namespace yans {
class BufferTest: public Test {
private:
bool ensure_written_bytes (Buffer b, uint32_t n, uint8_t array[]);
public:
virtual bool run_tests (void);
BufferTest ();
};
BufferTest::BufferTest ()
: Test ("Buffer") {}
bool
BufferTest::ensure_written_bytes (Buffer b, uint32_t n, uint8_t array[])
{
bool success = true;
uint8_t *expected = array;
uint8_t *got;
got = b.peek_data ();
for (uint32_t j = 0; j < n; j++) {
if (got[j] != expected[j]) {
success = false;
}
}
if (!success) {
failure () << "Buffer -- ";
failure () << "expected: n=";
failure () << n << ", ";
failure ().setf (std::ios::hex, std::ios::basefield);
for (uint32_t j = 0; j < n; j++) {
failure () << (uint16_t)expected[j] << " ";
}
failure ().setf (std::ios::dec, std::ios::basefield);
failure () << "got: ";
failure ().setf (std::ios::hex, std::ios::basefield);
for (uint32_t j = 0; j < n; j++) {
failure () << (uint16_t)got[j] << " ";
}
failure () << std::endl;
}
return success;
}
/* Note: works only when variadic macros are
* available which is the case for gcc.
* XXX
*/
#define ENSURE_WRITTEN_BYTES(buffer, n, ...) \
{ \
uint8_t bytes[] = {__VA_ARGS__}; \
if (!ensure_written_bytes (buffer, n , bytes)) { \
ok = false; \
} \
}
bool
BufferTest::run_tests (void)
{
bool ok = true;
Buffer buffer;
Buffer::Iterator i;
buffer.add_at_start (6);
i = buffer.begin ();
i.write_u8 (0x66);
ENSURE_WRITTEN_BYTES (buffer, 1, 0x66);
i = buffer.begin ();
i.write_u8 (0x67);
ENSURE_WRITTEN_BYTES (buffer, 1, 0x67);
i.write_hton_u16 (0x6568);
i = buffer.begin ();
ENSURE_WRITTEN_BYTES (buffer, 3, 0x67, 0x65, 0x68);
i.write_hton_u16 (0x6369);
ENSURE_WRITTEN_BYTES (buffer, 3, 0x63, 0x69, 0x68);
i.write_hton_u32 (0xdeadbeaf);
ENSURE_WRITTEN_BYTES (buffer, 6, 0x63, 0x69, 0xde, 0xad, 0xbe, 0xaf);
buffer.add_at_start (2);
i = buffer.begin ();
i.write_u16 (0);
ENSURE_WRITTEN_BYTES (buffer, 8, 0, 0, 0x63, 0x69, 0xde, 0xad, 0xbe, 0xaf);
buffer.add_at_end (2);
i = buffer.begin ();
i.next (8);
i.write_u16 (0);
ENSURE_WRITTEN_BYTES (buffer, 10, 0, 0, 0x63, 0x69, 0xde, 0xad, 0xbe, 0xaf, 0, 0);
buffer.remove_at_start (3);
i = buffer.begin ();
ENSURE_WRITTEN_BYTES (buffer, 7, 0x69, 0xde, 0xad, 0xbe, 0xaf, 0, 0);
buffer.remove_at_end (4);
i = buffer.begin ();
ENSURE_WRITTEN_BYTES (buffer, 3, 0x69, 0xde, 0xad);
buffer.add_at_start (1);
i = buffer.begin ();
i.write_u8 (0xff);
ENSURE_WRITTEN_BYTES (buffer, 4, 0xff, 0x69, 0xde, 0xad);
buffer.add_at_end (1);
i = buffer.begin ();
i.next (4);
i.write_u8 (0xff);
i.prev (2);
uint16_t saved = i.read_u16 ();
i.prev (2);
i.write_hton_u16 (0xff00);
i.prev (2);
if (i.read_ntoh_u16 () != 0xff00) {
ok = false;
}
i.prev (2);
i.write_u16 (saved);
ENSURE_WRITTEN_BYTES (buffer, 5, 0xff, 0x69, 0xde, 0xad, 0xff);
Buffer o = buffer;
ENSURE_WRITTEN_BYTES (o, 5, 0xff, 0x69, 0xde, 0xad, 0xff);
o.add_at_start (1);
i = o.begin ();
i.write_u8 (0xfe);
ENSURE_WRITTEN_BYTES (o, 6, 0xfe, 0xff, 0x69, 0xde, 0xad, 0xff);
buffer.add_at_start (2);
i = buffer.begin ();
i.write_u8 (0xfd);
i.write_u8 (0xfd);
ENSURE_WRITTEN_BYTES (o, 6, 0xfe, 0xff, 0x69, 0xde, 0xad, 0xff);
ENSURE_WRITTEN_BYTES (buffer, 7, 0xfd, 0xfd, 0xff, 0x69, 0xde, 0xad, 0xff);
// test self-assignment
{
Buffer a = o;
a = a;
}
// test remove start.
buffer = Buffer (5);
ENSURE_WRITTEN_BYTES (buffer, 5, 0, 0, 0, 0, 0);
buffer.remove_at_start (1);
ENSURE_WRITTEN_BYTES (buffer, 4, 0, 0, 0, 0);
buffer.add_at_start (1);
buffer.begin ().write_u8 (0xff);
ENSURE_WRITTEN_BYTES (buffer, 5, 0xff, 0, 0, 0, 0);
buffer.remove_at_start(3);
ENSURE_WRITTEN_BYTES (buffer, 2, 0, 0);
buffer.add_at_start (4);
buffer.begin ().write_hton_u32 (0xdeadbeaf);
ENSURE_WRITTEN_BYTES (buffer, 6, 0xde, 0xad, 0xbe, 0xaf, 0, 0);
buffer.remove_at_start (2);
ENSURE_WRITTEN_BYTES (buffer, 4, 0xbe, 0xaf, 0, 0);
buffer.add_at_end (4);
i = buffer.begin ();
i.next (4);
i.write_hton_u32 (0xdeadbeaf);
ENSURE_WRITTEN_BYTES (buffer, 8, 0xbe, 0xaf, 0, 0, 0xde, 0xad, 0xbe, 0xaf);
buffer.remove_at_start (5);
ENSURE_WRITTEN_BYTES (buffer, 3, 0xad, 0xbe, 0xaf);
// test remove end
buffer = Buffer (5);
ENSURE_WRITTEN_BYTES (buffer, 5, 0, 0, 0, 0, 0);
buffer.remove_at_end (1);
ENSURE_WRITTEN_BYTES (buffer, 4, 0, 0, 0, 0);
buffer.add_at_end (2);
i = buffer.begin ();
i.next (4);
i.write_u8 (0xab);
i.write_u8 (0xac);
ENSURE_WRITTEN_BYTES (buffer, 6, 0, 0, 0, 0, 0xab, 0xac);
buffer.remove_at_end (1);
ENSURE_WRITTEN_BYTES (buffer, 5, 0, 0, 0, 0, 0xab);
buffer.remove_at_end (3);
ENSURE_WRITTEN_BYTES (buffer, 2, 0, 0);
buffer.add_at_end (6);
i = buffer.begin ();
i.next (2);
i.write_u8 (0xac);
i.write_u8 (0xad);
i.write_u8 (0xae);
i.write_u8 (0xaf);
i.write_u8 (0xba);
i.write_u8 (0xbb);
ENSURE_WRITTEN_BYTES (buffer, 8, 0, 0, 0xac, 0xad, 0xae, 0xaf, 0xba, 0xbb);
buffer.add_at_start (3);
i = buffer.begin ();
i.write_u8 (0x30);
i.write_u8 (0x31);
i.write_u8 (0x32);
ENSURE_WRITTEN_BYTES (buffer, 11, 0x30, 0x31, 0x32, 0, 0, 0xac, 0xad, 0xae, 0xaf, 0xba, 0xbb);
buffer.remove_at_end (9);
ENSURE_WRITTEN_BYTES (buffer, 2, 0x30, 0x31);
buffer = Buffer (3);
buffer.add_at_end (2);
i = buffer.begin ();
i.next (3);
i.write_hton_u16 (0xabcd);
buffer.add_at_start (1);
buffer.begin ().write_u8 (0x21);
ENSURE_WRITTEN_BYTES (buffer, 6, 0x21, 0, 0, 0, 0xab, 0xcd);
buffer.remove_at_end (8);
if (buffer.get_size () != 0) {
ok = false;
}
return ok;
}
static BufferTest g_buffer_test;
}; // namespace yans
#endif /* RUN_SELF_TESTS */

690
src/common/buffer.h Normal file
View File

@@ -0,0 +1,690 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005,2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef BUFFER_H
#define BUFFER_H
#include <stdint.h>
#include <vector>
namespace yans {
/**
* \brief automatically resized byte buffer
*
* This represents a buffer of bytes. Its size is
* automatically adjusted to hold any data prepended
* or appended by the user. Its implementation is optimized
* to ensure that the number of buffer resizes is minimized,
* by creating new Buffers of the maximum size ever used.
* The correct maximum size is learned at runtime during use by
* recording the maximum size of each packet.
*/
class Buffer {
public:
/**
* \brief iterator in a Buffer instance
*/
class Iterator {
public:
inline Iterator ();
/**
* go forward by one byte
*/
inline void next (void);
/**
* go backward by one byte
*/
inline void prev (void);
/**
* \param delta number of bytes to go forward
*/
inline void next (uint32_t delta);
/**
* \param delta number of bytes to go backward
*/
inline void prev (uint32_t delta);
/**
* \param o the second iterator
* \return number of bytes included between the two iterators
*
* This method works only if the two iterators point
* to the same underlying buffer. Debug builds ensure
* this with an assert.
*/
inline int32_t get_distance_from (Iterator const &o) const;
/**
* \return true if this iterator points to the end of the byte array.
* false otherwise.
*/
inline bool is_end (void) const;
/**
* \return true if this iterator points to the start of the byte array.
* false otherwise.
*/
inline bool is_start (void) const;
/**
* \param data data to write in buffer
*
* Write the data in buffer and avance the iterator position
* by one byte.
*/
inline void write_u8 (uint8_t data);
/**
* \param data data to write in buffer
* \param len number of times data must be written in buffer
*
* Write the data in buffer len times and avance the iterator position
* by len byte.
*/
inline void write_u8 (uint8_t data, uint32_t len);
/**
* \param data data to write in buffer
*
* Write the data in buffer and avance the iterator position
* by two bytes. The format of the data written in the byte
* buffer is non-portable. We only ensure that read_u16 will
* return exactly what we wrote with write_u16 if the program
* is run on the same machine.
*/
inline void write_u16 (uint16_t data);
/**
* \param data data to write in buffer
*
* Write the data in buffer and avance the iterator position
* by four bytes. The format of the data written in the byte
* buffer is non-portable. We only ensure that read_u32 will
* return exactly what we wrote with write_u32 if the program
* is run on the same machine.
*/
inline void write_u32 (uint32_t data);
/**
* \param data data to write in buffer
*
* Write the data in buffer and avance the iterator position
* by eight bytes. The format of the data written in the byte
* buffer is non-portable. We only ensure that read_u64 will
* return exactly what we wrote with write_u64 if the program
* is run on the same machine.
*/
inline void write_u64 (uint64_t data);
/**
* \param data data to write in buffer
*
* Write the data in buffer and avance the iterator position
* by two bytes. The data is written in network order and the
* input data is expected to be in host order.
*/
inline void write_hton_u16 (uint16_t data);
/**
* \param data data to write in buffer
*
* Write the data in buffer and avance the iterator position
* by four bytes. The data is written in network order and the
* input data is expected to be in host order.
*/
inline void write_hton_u32 (uint32_t data);
/**
* \param data data to write in buffer
*
* Write the data in buffer and avance the iterator position
* by eight bytes. The data is written in network order and the
* input data is expected to be in host order.
*/
inline void write_hton_u64 (uint64_t data);
/**
* \param buffer a byte buffer to copy in the internal buffer.
* \param size number of bytes to copy.
*
* Write the data in buffer and avance the iterator position
* by size bytes.
*/
inline void write (uint8_t const*buffer, uint16_t size);
/**
* \param start the start of the data to copy
* \param end the end of the data to copy
*
* Write the data delimited by start and end in internal buffer
* and avance the iterator position by the number of bytes
* copied.
* The input interators _must_ not point to the same Buffer as
* we do to avoid overlapping copies. This is enforced
* in debug builds by asserts.
*/
inline void write (Iterator start, Iterator end);
/**
* \return the byte read in the buffer.
*
* Read data and advance the Iterator by the number of bytes
* read.
*/
inline uint8_t read_u8 (void);
/**
* \return the two bytes read in the buffer.
*
* Read data and advance the Iterator by the number of bytes
* read.
* The data is read in the format written by write_u16.
*/
inline uint16_t read_u16 (void);
/**
* \return the four bytes read in the buffer.
*
* Read data and advance the Iterator by the number of bytes
* read.
* The data is read in the format written by write_u32.
*/
inline uint32_t read_u32 (void);
/**
* \return the eight bytes read in the buffer.
*
* Read data and advance the Iterator by the number of bytes
* read.
* The data is read in the format written by write_u64.
*/
inline uint64_t read_u64 (void);
/**
* \return the two bytes read in the buffer.
*
* Read data and advance the Iterator by the number of bytes
* read.
* The data is read in network format and return in host format.
*/
inline uint16_t read_ntoh_u16 (void);
/**
* \return the four bytes read in the buffer.
*
* Read data and advance the Iterator by the number of bytes
* read.
* The data is read in network format and return in host format.
*/
inline uint32_t read_ntoh_u32 (void);
/**
* \return the eight bytes read in the buffer.
*
* Read data and advance the Iterator by the number of bytes
* read.
* The data is read in network format and return in host format.
*/
inline uint64_t read_ntoh_u64 (void);
/**
* \param buffer buffer to copy data into
* \param size number of bytes to copy
*
* Copy size bytes of data from the internal buffer to the
* input buffer and avance the Iterator by the number of
* bytes read.
*/
inline void read (uint8_t *buffer, uint16_t size);
private:
friend class Buffer;
inline Iterator (Buffer const*buffer, uint32_t m_current);
inline uint32_t get_index (uint32_t n);
uint32_t m_zero_start;
uint32_t m_zero_end;
uint32_t m_data_end;
uint32_t m_current;
uint8_t *m_data;
};
/**
* \return the number of bytes stored in this buffer.
*/
inline uint32_t get_size (void) const;
/**
* \return a pointer to the start of the internal
* byte buffer.
*
* The returned pointer points to an area of
* memory which is yans::Buffer::get_size () bytes big.
* Please, try to never ever use this method. It is really
* evil and is present only for a few specific uses.
*/
uint8_t *peek_data (void) const;
/**
* \param start size to reserve
*
* Add bytes at the start of the Buffer. The
* content of these bytes is undefined but debugging
* builds initialize them to 0x33.
* Any call to this method invalidates any Iterator
* pointing to this Buffer.
*/
void add_at_start (uint32_t start);
/**
* \param end size to reserve
*
* Add bytes at the end of the Buffer. The
* content of these bytes is undefined but debugging
* builds initialize them to 0x33.
* Any call to this method invalidates any Iterator
* pointing to this Buffer.
*/
void add_at_end (uint32_t end);
/**
* \param start size to remove
*
* Remove bytes at the start of the Buffer.
* Any call to this method invalidates any Iterator
* pointing to this Buffer.
*/
void remove_at_start (uint32_t start);
/**
* \param end size to remove
*
* Remove bytes at the end of the Buffer.
* Any call to this method invalidates any Iterator
* pointing to this Buffer.
*/
void remove_at_end (uint32_t end);
/**
* \param start offset from start of packet
* \param length
*
* \return a fragment of size length starting at offset
* start.
*/
Buffer create_fragment (uint32_t start, uint32_t length) const;
/**
* \return an Iterator which points to the
* start of this Buffer.
*/
inline Buffer::Iterator begin (void) const;
/**
* \return an Iterator which points to the
* end of this Buffer.
*/
inline Buffer::Iterator end (void) const;
inline Buffer (Buffer const &o);
inline Buffer &operator = (Buffer const &o);
inline Buffer ();
inline Buffer (uint32_t data_size);
inline ~Buffer ();
private:
struct BufferData {
uint32_t m_count;
uint32_t m_size;
uint32_t m_initial_start;
uint32_t m_dirty_start;
uint32_t m_dirty_size;
uint8_t m_data[1];
};
typedef std::vector<struct Buffer::BufferData*> BufferDataList;
inline uint8_t *get_start (void) const;
void transform_into_real_buffer (void) const;
static void recycle (struct Buffer::BufferData *data);
static struct Buffer::BufferData *create (void);
static struct Buffer::BufferData *allocate (uint32_t size, uint32_t start);
static void deallocate (struct Buffer::BufferData *data);
static BufferDataList m_free_list;
static uint32_t m_max_total_add_start;
static uint32_t m_max_total_add_end;
struct BufferData *m_data;
uint32_t m_zero_area_size;
uint32_t m_start;
uint32_t m_size;
};
}; // namespace yans
#include <cassert>
namespace yans {
Buffer::Buffer ()
: m_data (Buffer::create ()),
m_zero_area_size (0),
m_start (m_max_total_add_start),
m_size (0)
{
if (m_start > m_data->m_size) {
m_start = 0;
}
assert (m_start <= m_data->m_size);
}
Buffer::Buffer (uint32_t data_size)
: m_data (Buffer::create ()),
m_zero_area_size (data_size),
m_start (m_max_total_add_start),
m_size (0)
{
if (m_start > m_data->m_size) {
m_start = 0;
}
assert (m_start <= m_data->m_size);
}
Buffer::Buffer (Buffer const&o)
: m_data (o.m_data),
m_zero_area_size (o.m_zero_area_size),
m_start (o.m_start),
m_size (o.m_size)
{
m_data->m_count++;
assert (m_start <= m_data->m_size);
}
Buffer &
Buffer::operator = (Buffer const&o)
{
if (m_data != o.m_data) {
// not assignment to self.
m_data->m_count--;
if (m_data->m_count == 0) {
recycle (m_data);
}
m_data = o.m_data;
m_data->m_count++;
}
m_zero_area_size = o.m_zero_area_size;
m_start = o.m_start;
m_size = o.m_size;
assert (m_start <= m_data->m_size);
return *this;
}
Buffer::~Buffer ()
{
m_data->m_count--;
if (m_data->m_count == 0) {
recycle (m_data);
}
}
uint8_t *
Buffer::get_start (void) const
{
return m_data->m_data + m_start;
}
uint32_t
Buffer::get_size (void) const
{
return m_size + m_zero_area_size;
}
Buffer::Iterator
Buffer::begin (void) const
{
return Buffer::Iterator (this, 0);
}
Buffer::Iterator
Buffer::end (void) const
{
return Buffer::Iterator (this, get_size ());
}
Buffer::Iterator::Iterator ()
: m_zero_start (0),
m_zero_end (0),
m_data_end (0),
m_current (0),
m_data (0)
{}
Buffer::Iterator::Iterator (Buffer const*buffer, uint32_t current)
: m_zero_start (buffer->m_data->m_initial_start-buffer->m_start),
m_zero_end (m_zero_start+buffer->m_zero_area_size),
m_data_end (buffer->get_size ()),
m_current (current),
m_data (buffer->m_data->m_data+buffer->m_start)
{}
void
Buffer::Iterator::next (void)
{
assert (m_current + 1 <= m_data_end);
m_current++;
}
void
Buffer::Iterator::prev (void)
{
assert (m_current >= 1);
m_current--;
}
void
Buffer::Iterator::next (uint32_t delta)
{
assert (m_current + delta <= m_data_end);
m_current += delta;
}
void
Buffer::Iterator::prev (uint32_t delta)
{
assert (m_current >= delta);
m_current -= delta;
}
int32_t
Buffer::Iterator::get_distance_from (Iterator const &o) const
{
assert (m_data == o.m_data);
int32_t start = m_current;
int32_t end = o.m_current;
return end - start;
}
bool
Buffer::Iterator::is_end (void) const
{
return m_current == m_data_end;
}
bool
Buffer::Iterator::is_start (void) const
{
return m_current == 0;
}
uint32_t
Buffer::Iterator::get_index (uint32_t n)
{
assert (
(m_current + n <= m_data_end) &&
((m_current + n <= m_zero_start) ||
(m_current >= m_zero_end))
);
uint32_t index;
if (m_current < m_zero_start) {
index = m_current;
} else {
index = m_current - (m_zero_end-m_zero_start);
}
return index;
}
void
Buffer::Iterator::write (Iterator start, Iterator end)
{
assert (start.m_data == end.m_data);
assert (start.m_current <= end.m_current);
assert (m_data != start.m_data);
uint32_t size = end.m_current - start.m_current;
uint8_t *src = start.m_data + start.get_index (size);
uint8_t *dest = m_data + get_index (size);
memcpy (dest, src, size);
m_current += size;
}
void
Buffer::Iterator::write_u8 (uint8_t data, uint32_t len)
{
uint8_t *current = m_data + get_index (len);
memset (current, data, len);
m_current += len;
}
void
Buffer::Iterator::write_u8 (uint8_t data)
{
m_data[get_index (1)] = data;
m_current++;
}
void
Buffer::Iterator::write_u16 (uint16_t data)
{
uint16_t *buffer = (uint16_t *)(m_data + get_index (2));
*buffer = data;
m_current += 2;
}
void
Buffer::Iterator::write_u32 (uint32_t data)
{
uint32_t *buffer = (uint32_t *)(m_data + get_index (4));
*buffer = data;
m_current += 4;
}
void
Buffer::Iterator::write_u64 (uint64_t data)
{
uint64_t *buffer = (uint64_t *)(m_data + get_index (8));
*buffer = data;
m_current += 8;
}
void
Buffer::Iterator::write_hton_u16 (uint16_t data)
{
uint8_t *current = m_data + get_index (2);
*(current+0) = (data >> 8) & 0xff;
*(current+1) = (data >> 0) & 0xff;
m_current += 2;
}
void
Buffer::Iterator::write_hton_u32 (uint32_t data)
{
uint8_t *current = m_data + get_index (4);
*(current+0) = (data >> 24) & 0xff;
*(current+1) = (data >> 16) & 0xff;
*(current+2) = (data >> 8) & 0xff;
*(current+3) = (data >> 0) & 0xff;
m_current += 4;
}
void
Buffer::Iterator::write_hton_u64 (uint64_t data)
{
uint8_t *current = m_data + get_index (8);
*(current+0) = (data >> 56) & 0xff;
*(current+1) = (data >> 48) & 0xff;
*(current+2) = (data >> 40) & 0xff;
*(current+3) = (data >> 32) & 0xff;
*(current+4) = (data >> 24) & 0xff;
*(current+5) = (data >> 16) & 0xff;
*(current+6) = (data >> 8) & 0xff;
*(current+7) = (data >> 0) & 0xff;
m_current += 8;
}
void
Buffer::Iterator::write (uint8_t const*buffer, uint16_t size)
{
uint8_t *current = m_data + get_index (size);
memcpy (current, buffer, size);
m_current += size;
}
uint8_t
Buffer::Iterator::read_u8 (void)
{
uint8_t data = m_data[get_index(1)];
m_current++;
return data;
}
uint16_t
Buffer::Iterator::read_u16 (void)
{
uint16_t *buffer = reinterpret_cast<uint16_t *>(m_data + get_index (2));
m_current += 2;
return *buffer;
}
uint32_t
Buffer::Iterator::read_u32 (void)
{
uint32_t *buffer = reinterpret_cast<uint32_t *>(m_data + get_index (4));
m_current += 4;
return *buffer;
}
uint64_t
Buffer::Iterator::read_u64 (void)
{
uint64_t *buffer = reinterpret_cast<uint64_t *>(m_data + get_index (8));
m_current += 8;
return *buffer;
}
uint16_t
Buffer::Iterator::read_ntoh_u16 (void)
{
uint8_t *current = m_data + get_index (2);
uint16_t retval = 0;
retval |= static_cast<uint16_t> (current[0]) << 8;
retval |= static_cast<uint16_t> (current[1]) << 0;
m_current += 2;
return retval;
}
uint32_t
Buffer::Iterator::read_ntoh_u32 (void)
{
uint8_t *current = m_data + get_index (4);
uint32_t retval = 0;
retval |= static_cast<uint32_t> (current[0]) << 24;
retval |= static_cast<uint32_t> (current[1]) << 16;
retval |= static_cast<uint32_t> (current[2]) << 8;
retval |= static_cast<uint32_t> (current[3]) << 0;
m_current += 4;
return retval;
}
uint64_t
Buffer::Iterator::read_ntoh_u64 (void)
{
uint8_t *current = m_data + get_index (8);
uint64_t retval = 0;
retval |= static_cast<uint64_t> (current[0]) << 56;
retval |= static_cast<uint64_t> (current[1]) << 48;
retval |= static_cast<uint64_t> (current[2]) << 40;
retval |= static_cast<uint64_t> (current[3]) << 32;
retval |= static_cast<uint64_t> (current[4]) << 24;
retval |= static_cast<uint64_t> (current[5]) << 16;
retval |= static_cast<uint64_t> (current[6]) << 8;
retval |= static_cast<uint64_t> (current[7]) << 0;
m_current += 8;
return retval;
}
void
Buffer::Iterator::read (uint8_t *buffer, uint16_t size)
{
uint8_t *current = m_data + get_index (size);
memcpy (buffer, current, size);
m_current += size;
}
}; // namespace yans
#endif /* BUFFER_H */

View File

@@ -0,0 +1,84 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005,2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef CALLBACK_LOGGER_H
#define CALLBACK_LOGGER_H
#include "yans/callback.h"
namespace yans {
class CallbackLoggerBase {};
/**
* \brief log arbitrary number of parameters to a matching yans:Callback
*
* Whenever operator () is invoked on this class, the call and its arguments
* are forwarded to the internal matching yans::Callback.
*/
template<typename T1 = empty, typename T2 = empty,
typename T3 = empty, typename T4 = empty,
typename T5 = empty>
class CallbackLogger : public CallbackLoggerBase{
public:
CallbackLogger ()
: m_callback () {}
void set_callback (Callback<void,T1,T2,T3,T4,T5> callback) {
m_callback = callback;
}
void operator() (void) {
if (!m_callback.is_null ()) {
m_callback ();
}
}
void operator() (T1 a1) {
if (!m_callback.is_null ()) {
m_callback (a1);
}
}
void operator() (T1 a1, T2 a2) {
if (!m_callback.is_null ()) {
m_callback (a1,a2);
}
}
void operator() (T1 a1, T2 a2, T3 a3) {
if (!m_callback.is_null ()) {
m_callback (a1,a2,a3);
}
}
void operator() (T1 a1, T2 a2, T3 a3, T4 a4) {
if (!m_callback.is_null ()) {
m_callback (a1,a2,a3,a4);
}
}
void operator() (T1 a1, T2 a2, T3 a3, T4 a4,T5 a5) {
if (!m_callback.is_null ()) {
m_callback (a1,a2,a3,a4,a5);
}
}
private:
Callback<void,T1,T2,T3,T4,T5> m_callback;
};
}; // namespace yans
#endif /* CALLBACK_LOGGER_H */

View File

@@ -0,0 +1,63 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "chunk-constant-data.h"
namespace yans {
ChunkConstantData::ChunkConstantData (uint32_t len, uint8_t data)
: m_len (len), m_data (data)
{}
ChunkConstantData::~ChunkConstantData ()
{}
void
ChunkConstantData::print (std::ostream *os) const
{
*os << "(constant data)"
<< " len=" << m_len
<< ", data=" << m_data;
}
void
ChunkConstantData::add_to (Buffer *buffer) const
{
buffer->add_at_start (m_len);
#ifndef NDEBUG
buffer->begin ().write_u8 (m_data, m_len);
#endif
}
void
ChunkConstantData::peek_from (Buffer const *buffer)
{
m_len = buffer->get_size ();
m_data = buffer->begin ().read_u8 ();
}
void
ChunkConstantData::remove_from (Buffer *buffer)
{
buffer->remove_at_start (m_len);
}
}; // namespace yans

View File

@@ -0,0 +1,47 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef CHUNK_CONSTANT_DATA_H
#define CHUNK_CONSTANT_DATA_H
#include "chunk.h"
#include <stdint.h>
namespace yans {
class ChunkConstantData : public Chunk {
public:
ChunkConstantData (uint32_t len, uint8_t data);
~ChunkConstantData ();
private:
virtual void print (std::ostream *os) const;
virtual void add_to (Buffer *buffer) const;
virtual void peek_from (Buffer const *buffer);
virtual void remove_from (Buffer *buffer);
uint32_t m_len;
uint8_t m_data;
};
}; // namespace yans
#endif /* CHUNK_CONSTANT_DATA_H */

View File

@@ -0,0 +1,94 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "chunk-llc-snap.h"
#include <cassert>
#define noTRACE_CHUNK_LLC_SNAP 1
#ifdef TRACE_CHUNK_LLC_SNAP
#include <iostream>
#include "simulator.h"
# define TRACE(x) \
std::cout << "CHUNK LLCSNAP TRACE " << Simulator::now_s () << " " << x << std::endl;
#else /* TRACE_CHUNK_LLC_SNAP */
# define TRACE(format,...)
#endif /* TRACE_CHUNK_LLC_SNAP */
namespace yans {
ChunkLlcSnap::ChunkLlcSnap ()
{}
ChunkLlcSnap::~ChunkLlcSnap ()
{}
void
ChunkLlcSnap::set_type (enum Type type)
{
m_ether_type = type;
}
enum ChunkLlcSnap::Type
ChunkLlcSnap::get_type (void)
{
return (enum ChunkLlcSnap::Type) m_ether_type;
}
uint32_t
ChunkLlcSnap::get_size (void) const
{
return 1 + 1 + 1 + 3 + 2;
}
void
ChunkLlcSnap::print (std::ostream *os) const
{
*os << "(mac)"
<< " EtherType: ";
os->setf (std::ios::hex, std::ios::basefield);
*os << m_ether_type;
os->setf (std::ios::dec, std::ios::basefield);
}
void
ChunkLlcSnap::add_to (Buffer *buffer) const
{
buffer->add_at_start (get_size ());
Buffer::Iterator i = buffer->begin ();
uint8_t buf[] = {0xaa, 0xaa, 0x03, 0, 0, 0};
i.write (buf, 6);
i.write_hton_u16 (m_ether_type);
}
void
ChunkLlcSnap::peek_from (Buffer const *buffer)
{
Buffer::Iterator i = buffer->begin ();
i.next (5+1);
m_ether_type = i.read_ntoh_u16 ();
}
void
ChunkLlcSnap::remove_from (Buffer *buffer)
{
buffer->remove_at_start (get_size ());
}
}; // namespace yans

View File

@@ -0,0 +1,55 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef CHUNK_LLC_SNAP_H
#define CHUNK_LLC_SNAP_H
#include "chunk.h"
#include <stdint.h>
namespace yans {
class ChunkLlcSnap : public Chunk {
public:
ChunkLlcSnap ();
virtual ~ChunkLlcSnap ();
enum Type {
TYPE_IPV4 = 0x0800,
TYPE_ARP = 0x0806
};
void set_type (enum Type type);
enum Type get_type (void);
uint32_t get_size (void) const;
private:
virtual void print (std::ostream *os) const;
virtual void add_to (Buffer *buffer) const;
virtual void peek_from (Buffer const *buffer);
virtual void remove_from (Buffer *buffer);
uint16_t m_ether_type;
};
}; // namespace yans
#endif /* CHUNK_LLC_SNAP_H */

49
src/common/chunk-utils.cc Normal file
View File

@@ -0,0 +1,49 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "chunk-utils.h"
namespace yans {
void write_to (Buffer::Iterator &i, Ipv4Address ad)
{
i.write_hton_u32 (ad.get_host_order ());
}
void write_to (Buffer::Iterator &i, MacAddress ad)
{
uint8_t mac[6];
ad.peek (mac);
i.write (mac, 6);
}
void read_from (Buffer::Iterator &i, Ipv4Address &ad)
{
ad.set_host_order (i.read_ntoh_u32 ());
}
void read_from (Buffer::Iterator &i, MacAddress &ad)
{
uint8_t mac[6];
i.read (mac, 6);
ad.set (mac);
}
}; // namespace yans

38
src/common/chunk-utils.h Normal file
View File

@@ -0,0 +1,38 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef CHUNK_UTILS_H
#define CHUNK_UTILS_H
#include "buffer.h"
#include "ipv4-address.h"
#include "mac-address.h"
namespace yans {
void write_to (Buffer::Iterator &i, Ipv4Address ad);
void write_to (Buffer::Iterator &i, MacAddress ad);
void read_from (Buffer::Iterator &i, Ipv4Address &ad);
void read_from (Buffer::Iterator &i, MacAddress &ad);
};
#endif /* CHUNK_UTILS_H */

65
src/common/chunk.cc Normal file
View File

@@ -0,0 +1,65 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "chunk.h"
#include <cassert>
namespace yans {
Chunk::Chunk ()
: m_must_peek_before_remove (false) {}
void
Chunk::print (std::ostream &os) const
{
print (&os);
}
void
Chunk::add (Buffer *buffer) const
{
add_to (buffer);
}
void
Chunk::peek (Buffer const *buffer)
{
peek_from (buffer);
m_must_peek_before_remove = true;
}
void
Chunk::remove (Buffer *buffer)
{
assert (m_must_peek_before_remove);
remove_from (buffer);
m_must_peek_before_remove = false;
}
Chunk::~Chunk ()
{}
std::ostream& operator<< (std::ostream& os, Chunk const& chunk)
{
chunk.print (os);
return os;
}
}; // namespace yans

89
src/common/chunk.h Normal file
View File

@@ -0,0 +1,89 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef CHUNK_H
#define CHUNK_H
#include <stdint.h>
#include <ostream>
#include "buffer.h"
namespace yans {
/**
* \brief Protocol header serialization and deserialization.
*
* Every Protocol header which needs to be inserted and removed
* from a Packet instance must derive from this abstract base class
* and implement the private pure virtual methods defined here.
*/
class Chunk {
public:
Chunk ();
/**
* Derived classes must provided an explicit virtual destructor
*/
virtual ~Chunk () = 0;
void print (std::ostream &os) const;
void add (Buffer *buffer) const;
void peek (Buffer const *buffer);
void remove (Buffer *buffer);
private:
bool m_must_peek_before_remove;
/**
* \param os the std output stream in which this
* protocol header must print itself.
*/
virtual void print (std::ostream *os) const = 0;
/**
* \param buffer the buffer in which the protocol header
* must serialize itself.
*
* This method must:
* - reserve room for its serialized representation in the input buffer
* - serialize itself in this reserved room
*/
virtual void add_to (Buffer *buffer) const = 0;
/**
* \param buffer the buffer from which the protocol header must
* deserialize itself.
*
*/
virtual void peek_from (Buffer const *buffer) = 0;
/**
* \param buffer the buffer from which the protocol header
* must remove itself.
*
* This method must remove its serialized representation
* from the input buffer. This method does not need to deserialize
* the data itself.
*/
virtual void remove_from (Buffer *buffer) = 0;
};
std::ostream& operator<< (std::ostream& os, Chunk const& chunk);
}; // namespace yans
#endif /* CHUNK_H */

View File

@@ -0,0 +1,70 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef COUNT_PTR_HOLDER_TCC
#define COUNT_PTR_HOLDER_TCC
namespace yans {
template <typename T>
class CountPtrHolder {
public:
typedef T *real_type;
CountPtrHolder (T *env)
: m_env (env) {
m_env->ref ();
}
~CountPtrHolder () {
if (m_env != 0) {
m_env->unref ();
}
}
CountPtrHolder (CountPtrHolder const&o) {
m_env = o.m_env;
m_env->ref ();
}
T *remove (void) {
T *env = m_env;
m_env = 0;
return env;
}
private:
CountPtrHolder ();
CountPtrHolder &operator = (CountPtrHolder const& o);
T *m_env;
};
template<typename T>
CountPtrHolder<T>
make_count_ptr_holder (T *t) {
return CountPtrHolder<T> (t);
}
template<typename T>
CountPtrHolder<T const>
make_const_count_ptr_holder (T *t) {
return CountPtrHolder<T const> (t);
}
}; // namespace yans
#endif /* REF_HOLDER_TCC */

119
src/common/data-writer.cc Normal file
View File

@@ -0,0 +1,119 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "data-writer.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/poll.h>
#include <fcntl.h>
#include <unistd.h>
#include <cassert>
#include <string.h>
#include <list>
#define noTRACE_DATA_WRITER 1
#ifdef TRACE_DATA_WRITER
#include <iostream>
# define TRACE(x) \
std::cout << "DATA WRITER TRACE " << this << " " << x << std::endl;
#else /* TRACE_DATA_WRITER */
# define TRACE(format,...)
#endif /* TRACE_DATA_WRITER */
#define BUFFER_SIZE (4096)
namespace yans {
class DataWriterPrivate {
public:
DataWriterPrivate ();
~DataWriterPrivate ();
void open (char const *filename);
void write (uint8_t *buffer, uint32_t size);
private:
uint8_t m_data[BUFFER_SIZE];
uint32_t m_current;
int m_fd;
};
DataWriterPrivate::DataWriterPrivate ()
: m_current (0)
{}
DataWriterPrivate::~DataWriterPrivate ()
{
::write (m_fd, m_data, m_current);
::close (m_fd);
}
void
DataWriterPrivate::open (char const *filename)
{
m_fd = ::open (filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
assert (m_fd != -1);
}
#ifndef min
#define min(a,b) ((a)<(b)?(a):(b))
#endif /* min */
void
DataWriterPrivate::write (uint8_t *buffer, uint32_t size)
{
while (size > 0) {
uint32_t to_copy = min (BUFFER_SIZE - m_current, size);
memcpy (m_data + m_current, buffer, to_copy);
size -= to_copy;
m_current += to_copy;
buffer += to_copy;
if (m_current == BUFFER_SIZE) {
ssize_t written = 0;
written = ::write (m_fd, m_data, BUFFER_SIZE);
assert (written == BUFFER_SIZE);
m_current = 0;
}
}
}
DataWriter::DataWriter ()
: m_priv (new DataWriterPrivate ())
{}
DataWriter::~DataWriter ()
{
delete m_priv;
m_priv = 0;
}
void
DataWriter::open (char const *filename)
{
m_priv->open (filename);
}
void
DataWriter::write (uint8_t *buffer, uint32_t size)
{
m_priv->write (buffer, size);
}
}; // namespace

44
src/common/data-writer.h Normal file
View File

@@ -0,0 +1,44 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef DATA_WRITER_H
#define DATA_WRITER_H
#include <stdint.h>
namespace yans {
class DataWriterPrivate;
class DataWriter {
public:
DataWriter ();
~DataWriter ();
void open (char const *filename);
void write (uint8_t *buffer, uint32_t size);
private:
DataWriterPrivate *m_priv;
};
}; //namespace yans
#endif /* DATA_WRITER_H */

View File

@@ -0,0 +1,58 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef F_TRACED_VARIABLE_TCC
#define F_TRACED_VARIABLE_TCC
#include "yans/callback.h"
#include <stdint.h>
namespace yans {
class FTracedVariableBase {
public:
typedef Callback<void,double, double> ChangeNotifyCallback;
FTracedVariableBase () {}
FTracedVariableBase (FTracedVariableBase const &o) {}
FTracedVariableBase &operator = (FTracedVariableBase const &o) {
return *this;
}
~FTracedVariableBase () {}
void set_callback(ChangeNotifyCallback callback) {
m_callback = callback;
}
protected:
void notify (double old_val, double new_val) {
if (old_val != new_val && !m_callback.is_null ()) {
m_callback (old_val, new_val);
}
}
private:
ChangeNotifyCallback m_callback;
};
}; // namespace yans
#endif /* F_TRACED_VARIABLE_TCC */

203
src/common/ipv4-address.cc Normal file
View File

@@ -0,0 +1,203 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "utils.h"
#include "ipv4-address.h"
namespace yans {
Ipv4Mask::Ipv4Mask ()
: m_mask (0x66666666)
{}
Ipv4Mask::Ipv4Mask (uint32_t mask)
: m_mask (mask)
{}
Ipv4Mask::Ipv4Mask (char const *mask)
{
m_mask = ascii_to_ipv4_host (mask);
}
bool
Ipv4Mask::is_equal (Ipv4Mask other) const
{
if (other.m_mask == m_mask) {
return true;
} else {
return false;
}
}
bool
Ipv4Mask::is_match (Ipv4Address a, Ipv4Address b) const
{
if ((a.get_host_order () & m_mask) == (b.get_host_order () & m_mask)) {
return true;
} else {
return false;
}
}
uint32_t
Ipv4Mask::get_host_order (void) const
{
return m_mask;
}
void
Ipv4Mask::set_host_order (uint32_t value)
{
m_mask = value;
}
void
Ipv4Mask::print (std::ostream *os) const
{
*os << ((m_mask >> 24) & 0xff) << "."
<< ((m_mask >> 16) & 0xff) << "."
<< ((m_mask >> 8) & 0xff) << "."
<< ((m_mask >> 0) & 0xff);
}
Ipv4Mask
Ipv4Mask::get_loopback (void)
{
static Ipv4Mask loopback = Ipv4Mask ("255.0.0.0");
return loopback;
}
Ipv4Mask
Ipv4Mask::get_zero (void)
{
static Ipv4Mask zero = Ipv4Mask ("0.0.0.0");
return zero;
}
Ipv4Address::Ipv4Address ()
: m_address (0x66666666)
{}
Ipv4Address::Ipv4Address (uint32_t address)
{
m_address = address;
}
Ipv4Address::Ipv4Address (char const *address)
{
m_address = ascii_to_ipv4_host (address);
}
bool
Ipv4Address::is_equal (Ipv4Address other) const
{
if (other.m_address == m_address) {
return true;
} else {
return false;
}
}
bool
Ipv4Address::is_multicast (void)
{
// XXX
return false;
}
uint32_t
Ipv4Address::get_host_order (void) const
{
return m_address;
}
void
Ipv4Address::set_host_order (uint32_t ip)
{
m_address = ip;
}
void
Ipv4Address::serialize (uint8_t buf[4]) const
{
buf[0] = (m_address >> 24) & 0xff;
buf[1] = (m_address >> 16) & 0xff;
buf[2] = (m_address >> 8) & 0xff;
buf[3] = (m_address >> 0) & 0xff;
}
void
Ipv4Address::print (std::ostream *os) const
{
*os << ((m_address >> 24) & 0xff) << "."
<< ((m_address >> 16) & 0xff) << "."
<< ((m_address >> 8) & 0xff) << "."
<< ((m_address >> 0) & 0xff);
}
Ipv4Address
Ipv4Address::get_zero (void)
{
static Ipv4Address zero ("0.0.0.0");
return zero;
}
Ipv4Address
Ipv4Address::get_any (void)
{
static Ipv4Address any ("0.0.0.0");
return any;
}
Ipv4Address
Ipv4Address::get_broadcast (void)
{
static Ipv4Address broadcast ("255.255.255.255");
return broadcast;
}
Ipv4Address
Ipv4Address::get_loopback (void)
{
Ipv4Address loopback ("127.0.0.1");
return loopback;
}
bool operator == (Ipv4Address const &a, Ipv4Address const &b)
{
return a.is_equal (b);
}
bool operator != (Ipv4Address const &a, Ipv4Address const &b)
{
return !a.is_equal (b);
}
size_t Ipv4AddressHash::operator()(Ipv4Address const &x) const
{
return x.get_host_order ();
}
std::ostream& operator<< (std::ostream& os, Ipv4Address const& address)
{
address.print (&os);
return os;
}
std::ostream& operator<< (std::ostream& os, Ipv4Mask const& mask)
{
mask.print (&os);
return os;
}
}; // namespace yans

107
src/common/ipv4-address.h Normal file
View File

@@ -0,0 +1,107 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef IPV4_ADDRESS_H
#define IPV4_ADDRESS_H
#include <stdint.h>
#include <ostream>
namespace yans {
/* Ipv4 addresses are stored in host order in
* this class.
*/
class Ipv4Address {
public:
Ipv4Address ();
/* input address is in host order. */
Ipv4Address (uint32_t address);
/* input address is in format:
* hhh.xxx.xxx.lll
* where h is the high byte and l the
* low byte
*/
Ipv4Address (char const *address);
bool is_equal (Ipv4Address other) const;
/* Using this method is frowned upon.
* Please, do _not_ use this method.
* It is there only for chunk-ipv4.
*/
uint32_t get_host_order (void) const;
void set_host_order (uint32_t ip);
void serialize (uint8_t buf[4]) const;
void print (std::ostream *os) const;
bool is_broadcast (void);
bool is_multicast (void);
static Ipv4Address get_zero (void);
static Ipv4Address get_any (void);
static Ipv4Address get_broadcast (void);
static Ipv4Address get_loopback (void);
private:
uint32_t m_address;
};
class Ipv4Mask {
public:
Ipv4Mask ();
Ipv4Mask (uint32_t mask);
Ipv4Mask (char const *mask);
bool is_match (Ipv4Address a, Ipv4Address b) const;
bool is_equal (Ipv4Mask other) const;
/* Using this method is frowned upon.
* Please, do _not_ use this method.
*/
uint32_t get_host_order (void) const;
void set_host_order (uint32_t value);
void print (std::ostream *os) const;
static Ipv4Mask get_loopback (void);
static Ipv4Mask get_zero (void);
private:
uint32_t m_mask;
};
std::ostream& operator<< (std::ostream& os, Ipv4Address const& address);
std::ostream& operator<< (std::ostream& os, Ipv4Mask const& mask);
bool operator == (Ipv4Address const &a, Ipv4Address const &b);
bool operator != (Ipv4Address const &a, Ipv4Address const &b);
class Ipv4AddressHash : public std::unary_function<Ipv4Address, size_t> {
public:
size_t operator()(Ipv4Address const &x) const;
};
bool operator != (Ipv4Address const &a, Ipv4Address const &b);
}; // namespace yans
#endif /* IPV4_ADDRESS_H */

View File

@@ -0,0 +1,82 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "ipv4-network-interface.h"
namespace yans {
Ipv4NetworkInterface::~Ipv4NetworkInterface ()
{}
void
Ipv4NetworkInterface::set_address (Ipv4Address ad)
{
m_address = ad;
}
void
Ipv4NetworkInterface::set_mask (Ipv4Mask mask)
{
m_mask = mask;
}
uint16_t
Ipv4NetworkInterface::get_mtu (void) const
{
return real_get_mtu ();
}
Ipv4Mask
Ipv4NetworkInterface::get_mask (void) const
{
return m_mask;
}
Ipv4Address
Ipv4NetworkInterface::get_address (void) const
{
return m_address;
}
Ipv4Address
Ipv4NetworkInterface::get_broadcast (void) const
{
uint32_t mask = m_mask.get_host_order ();
uint32_t address = m_address.get_host_order ();
Ipv4Address broadcast = Ipv4Address (address | (~mask));
return broadcast;
}
void
Ipv4NetworkInterface::send (Packet packet, Ipv4Address to)
{
real_send (packet, to);
}
void
Ipv4NetworkInterface::set_rx_callback (RxCallback callback)
{
m_rx_callback = callback;
}
void
Ipv4NetworkInterface::forward_up (Packet packet)
{
m_rx_callback (packet, this);
}
}; // namespace yans

View File

@@ -0,0 +1,59 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef IPV4_NETWORK_INTERFACE
#define IPV4_NETWORK_INTERFACE
#include "ipv4-address.h"
#include "yans/callback.h"
#include "packet.h"
namespace yans {
class Packet;
class Ipv4NetworkInterface {
public:
typedef Callback<void, Packet , Ipv4NetworkInterface *> RxCallback;
virtual ~Ipv4NetworkInterface () = 0;
void set_address (Ipv4Address ad);
void set_mask (Ipv4Mask mask);
uint16_t get_mtu (void) const;
Ipv4Mask get_mask (void) const;
Ipv4Address get_address (void) const;
Ipv4Address get_broadcast (void) const;
void send (Packet packet, Ipv4Address to);
void set_rx_callback (RxCallback callback);
protected:
void forward_up (Packet packet);
private:
virtual uint16_t real_get_mtu (void) const = 0;
virtual void real_send (Packet packet, Ipv4Address to) = 0;
RxCallback m_rx_callback;
Ipv4Address m_address;
Ipv4Mask m_mask;
};
}; // namespace yans
#endif /* IPV4_NETWORK_INTERFACE */

View File

@@ -0,0 +1,89 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "llc-snap-encapsulation.h"
#include "chunk-llc-snap.h"
#include "packet.h"
#include "chunk.h"
#include "mac-network-interface.h"
#include <cassert>
namespace yans {
uint32_t
LlcSnapEncapsulation::get_overhead (void) const
{
ChunkLlcSnap llc;
return llc.get_size ();
}
void
LlcSnapEncapsulation::set_ipv4_callback (RxCallback callback)
{
m_ipv4_callback = callback;
}
void
LlcSnapEncapsulation::set_arp_callback (RxCallback callback)
{
m_arp_callback = callback;
}
void
LlcSnapEncapsulation::set_mac_interface (MacNetworkInterface *interface)
{
m_interface = interface;
}
void
LlcSnapEncapsulation::send_ipv4 (Packet packet, MacAddress to)
{
ChunkLlcSnap llc;
llc.set_type (ChunkLlcSnap::TYPE_IPV4);
packet.add (&llc);
m_interface->send (packet, to);
}
void
LlcSnapEncapsulation::send_arp (Packet packet, MacAddress to)
{
ChunkLlcSnap llc;
llc.set_type (ChunkLlcSnap::TYPE_ARP);
packet.add (&llc);
m_interface->send (packet, to);
}
void
LlcSnapEncapsulation::receive (Packet packet, MacNetworkInterface *interface)
{
assert (interface == m_interface);
ChunkLlcSnap llc;
packet.peek (&llc);
packet.remove (&llc);
switch (llc.get_type ()) {
case ChunkLlcSnap::TYPE_IPV4:
m_ipv4_callback (packet);
break;
case ChunkLlcSnap::TYPE_ARP:
m_arp_callback (packet);
break;
default:
assert (false);
//NOT REACHED
break;
}
}
}; // namespace yans

View File

@@ -0,0 +1,52 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef LLC_SNAP_ENCAPSULATION
#define LLC_SNAP_ENCAPSULATION
#include <stdint.h>
#include "yans/callback.h"
#include "mac-address.h"
#include "packet.h"
namespace yans {
class MacNetworkInterface;
class LlcSnapEncapsulation {
public:
typedef Callback<void, Packet > RxCallback;
uint32_t get_overhead (void) const;
void set_ipv4_callback (RxCallback callback);
void set_arp_callback (RxCallback callback);
void set_mac_interface (MacNetworkInterface *interface);
void send_ipv4 (Packet packet, MacAddress to);
void send_arp (Packet packet, MacAddress to);
void receive (Packet packet, MacNetworkInterface *interface);
private:
RxCallback m_ipv4_callback;
RxCallback m_arp_callback;
MacNetworkInterface *m_interface;
};
}; // namespace yans
#endif /* LLC_SNAP_ENCAPSULATION */

View File

@@ -0,0 +1,46 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "mac-address-factory.h"
namespace yans {
MacAddressFactory::MacAddressFactory ()
{
m_addr[0] = 0;
m_addr[1] = 0;
m_addr[2] = 0;
m_addr[3] = 0;
m_addr[4] = 0;
m_addr[5] = 0;
m_index = 0;
}
MacAddress
MacAddressFactory::get_next (void)
{
m_addr[m_index]++;
if (m_addr[m_index] == 0) {
m_index++;
}
return MacAddress (m_addr);
}
}; // namespace yans

View File

@@ -0,0 +1,40 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef MAC_ADDRESS_FACTORY_H
#define MAC_ADDRESS_FACTORY_H
#include "mac-address.h"
namespace yans {
class MacAddressFactory {
public:
MacAddressFactory ();
MacAddress get_next (void);
private:
uint8_t m_addr[6];
uint8_t m_cur;
uint8_t m_index;
};
}; // namespace yans
#endif /* MAC_ADDRESS_FACTORY_H */

187
src/common/mac-address.cc Normal file
View File

@@ -0,0 +1,187 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "mac-address.h"
#include "utils.h"
namespace yans {
MacAddress::MacAddress ()
{
m_address[0] = 0;
m_address[1] = 0;
m_address[2] = 0;
m_address[3] = 0;
m_address[4] = 0;
m_address[5] = 0;
}
MacAddress::MacAddress (uint8_t const address[6])
{
m_address[0] = address[0];
m_address[1] = address[1];
m_address[2] = address[2];
m_address[3] = address[3];
m_address[4] = address[4];
m_address[5] = address[5];
}
MacAddress::MacAddress (char const *address)
{
ascii_to_mac_network (address, m_address);
}
MacAddress::MacAddress (uint32_t ip_multicast_address)
{
m_address[0] = 1 | ((ip_multicast_address & 0x7f) << 1);
m_address[1] = (ip_multicast_address >> 7) & 0xff;
m_address[2] = (ip_multicast_address >> 16) & 0xff;
m_address[3] = 0x5e;
m_address[4] = 0;
m_address[5] = 0;
}
MacAddress::~MacAddress ()
{}
bool
MacAddress::is_equal (MacAddress other) const
{
if (m_address[0] == other.m_address[0] &&
m_address[1] == other.m_address[1] &&
m_address[2] == other.m_address[2] &&
m_address[3] == other.m_address[3] &&
m_address[4] == other.m_address[4] &&
m_address[5] == other.m_address[5]) {
return true;
} else {
return false;
}
}
bool
MacAddress::is_broadcast (void) const
{
if (m_address[0] == 0xff &&
m_address[1] == 0xff &&
m_address[2] == 0xff &&
m_address[3] == 0xff &&
m_address[4] == 0xff &&
m_address[5] == 0xff) {
return true;
} else {
return false;
}
}
bool
MacAddress::is_multicast (void) const
{
if (m_address[0] & 0x1) {
return true;
} else {
return false;
}
}
bool
MacAddress::is_multicast_equal (MacAddress other) const
{
if (get_multicast_part () == other.get_multicast_part ()) {
return true;
} else {
return false;
}
}
uint32_t
MacAddress::get_multicast_part (void) const
{
uint32_t part = 0;
part |= m_address[0] >> 1;
part |= m_address[1] << 7;
part |= (m_address[1] << 15);
return part;
}
void
MacAddress::peek (uint8_t ad[6]) const
{
memcpy (ad, m_address, 6);
}
void
MacAddress::set (uint8_t const ad[6])
{
memcpy (m_address, ad, 6);
}
void
MacAddress::print (std::ostream *os) const
{
os->setf (std::ios::hex, std::ios::basefield);
*os << (uint32_t)m_address[0] << ":"
<< (uint32_t)m_address[1] << ":"
<< (uint32_t)m_address[2] << ":"
<< (uint32_t)m_address[3] << ":"
<< (uint32_t)m_address[4] << ":"
<< (uint32_t)m_address[5];
os->setf (std::ios::dec, std::ios::basefield);
}
MacAddress
MacAddress::get_broadcast (void)
{
static MacAddress broadcast = MacAddress ("ff:ff:ff:ff:ff:ff");
return broadcast;
}
bool operator == (MacAddress const&a, MacAddress const&b)
{
return a.is_equal (b);
}
bool operator != (MacAddress const&a, MacAddress const&b)
{
return !a.is_equal (b);
}
bool operator < (MacAddress const&a, MacAddress const&b)
{
uint8_t a_p[6];
uint8_t b_p[6];
a.peek (a_p);
b.peek (b_p);
for (uint8_t i = 0; i < 6; i++) {
if (a_p[i] < b_p[i]) {
return true;
} else if (a_p[i] > b_p[i]) {
return false;
}
}
return false;
}
std::ostream& operator<< (std::ostream& os, MacAddress const& address)
{
address.print (&os);
return os;
}
}; // namespace yans

72
src/common/mac-address.h Normal file
View File

@@ -0,0 +1,72 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef MAC_ADDRESS_H
#define MAC_ADDRESS_H
#include <stdint.h>
#include <ostream>
namespace yans {
class MacAddress {
public:
MacAddress (void);
/* low byte should be first.
*/
MacAddress (uint8_t const address[6]);
/* The string should look like this:
* hh-xx-xx-xx-xx-ll
* where hh is the high byte and ll is
* the low byte.
*/
MacAddress (char const *address);
/* create the mac address associated to
* this multicast ip address.
*/
MacAddress (uint32_t multicast_ip_address);
~MacAddress ();
bool is_equal (MacAddress other) const;
bool is_broadcast (void) const;
bool is_multicast (void) const;
bool is_multicast_equal (MacAddress other) const;
void print (std::ostream *os) const;
void peek (uint8_t ad[6]) const;
void set (uint8_t const ad[6]);
static MacAddress get_broadcast (void);
private:
uint32_t get_multicast_part (void) const;
uint8_t m_address[6];
};
bool operator == (MacAddress const&a, MacAddress const&b);
bool operator != (MacAddress const&a, MacAddress const&b);
bool operator < (MacAddress const&a, MacAddress const&b);
std::ostream& operator<< (std::ostream& os, MacAddress const& address);
}; // namespace yans
#endif /* MAC_ADDRESS_H */

View File

@@ -0,0 +1,96 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "mac-network-interface.h"
namespace yans {
MacNetworkInterface::MacNetworkInterface (MacAddress self, uint16_t max_mtu)
: m_self (self), m_max_mtu (max_mtu), m_mtu (max_mtu)
{}
MacNetworkInterface::~MacNetworkInterface ()
{}
MacAddress
MacNetworkInterface::get_mac_address (void) const
{
return m_self;
}
void
MacNetworkInterface::set_mtu (uint16_t mtu)
{
if (mtu > m_max_mtu ) {
m_mtu = m_max_mtu;
} else {
m_mtu = mtu;
}
}
uint16_t
MacNetworkInterface::get_mtu (void) const
{
return m_mtu;
}
bool
MacNetworkInterface::is_down (void) const
{
return m_is_down;
}
void
MacNetworkInterface::set_up (void)
{
m_is_down = false;
notify_up ();
}
void
MacNetworkInterface::set_down (void)
{
m_is_down = true;
notify_down ();
}
void
MacNetworkInterface::set_status_change_callback (StatusChangeCallback callback)
{
m_status_change_callback = callback;
}
void
MacNetworkInterface::set_rx_callback (RxCallback callback)
{
m_rx_callback = callback;
}
void
MacNetworkInterface::send (Packet packet, MacAddress to)
{
real_send (packet, to);
}
void
MacNetworkInterface::forward_up (Packet packet)
{
m_rx_callback (packet, this);
}
void
MacNetworkInterface::notify_status_change (void)
{
m_status_change_callback (this);
}
}; // namespace yans

View File

@@ -0,0 +1,68 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef MAC_NETWORK_INTERFACE_H
#define MAC_NETWORK_INTERFACE_H
#include <stdint.h>
#include "yans/callback.h"
#include "mac-address.h"
#include "packet.h"
namespace yans {
class MacNetworkInterface {
public:
typedef Callback<void, Packet , MacNetworkInterface *> RxCallback;
typedef Callback<void,MacNetworkInterface *> StatusChangeCallback;
MacNetworkInterface (MacAddress self, uint16_t max_mtu);
virtual ~MacNetworkInterface () = 0;
MacAddress get_mac_address (void) const;
void set_mtu (uint16_t mtu);
uint16_t get_mtu (void) const;
bool is_down (void) const;
void set_up (void);
void set_down (void);
void set_status_change_callback (StatusChangeCallback callback);
void set_rx_callback (RxCallback callback);
void send (Packet packet, MacAddress to);
protected:
void forward_up (Packet packet);
void notify_status_change (void);
private:
virtual void notify_up (void) = 0;
virtual void notify_down (void) = 0;
virtual void real_send (Packet packet, MacAddress to) = 0;
StatusChangeCallback m_status_change_callback;
RxCallback m_rx_callback;
MacAddress m_self;
uint16_t m_max_mtu;
uint16_t m_mtu;
bool m_is_down;
};
}; // namespace yans
#endif /* MAC_NETWORK_INTERFACE_H */

View File

@@ -0,0 +1,42 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "packet-logger.h"
namespace yans {
PacketLogger::PacketLogger ()
{}
void
PacketLogger::log (Packet const packet)
{
if (!m_callback.is_null ()) {
m_callback (packet);
}
}
void
PacketLogger::set_callback (PacketLoggerCallback callback)
{
m_callback = callback;
}
}; // namespace yans

View File

@@ -0,0 +1,53 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef PACKET_LOGGER_H
#define PACKET_LOGGER_H
#include "yans/callback.h"
#include "packet.h"
namespace yans {
/**
* \brief log packets
*/
class PacketLogger {
public:
typedef Callback<void,Packet const> PacketLoggerCallback;
PacketLogger ();
/**
* \param packet to log
* If a non-null callback was set, the packet
* is forwarded to that callback.
*/
void log (Packet const packet);
/**
* \param callback callback to store
*/
void set_callback (PacketLoggerCallback callback);
private:
PacketLoggerCallback m_callback;
};
}; // namespace yans
#endif /* PACKET_LOGGER_H */

127
src/common/packet.cc Normal file
View File

@@ -0,0 +1,127 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005,2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "packet.h"
#include <cassert>
namespace yans {
Packet::Packet ()
: m_buffer () {}
Packet::Packet (uint32_t size)
: m_buffer (size)
{}
Packet::Packet (Buffer buffer, Tags tags)
: m_buffer (buffer),
m_tags (tags)
{}
Packet
Packet::create_fragment (uint32_t start, uint32_t length) const
{
Buffer tmp = m_buffer.create_fragment (start, length);
return Packet (tmp, m_tags);
}
uint32_t
Packet::get_size (void) const
{
return m_buffer.get_size ();
}
void
Packet::add (Chunk *chunk)
{
chunk->add (&m_buffer);
}
void
Packet::peek (Chunk *chunk) const
{
chunk->peek (&m_buffer);
}
void
Packet::remove (Chunk *chunk)
{
chunk->remove (&m_buffer);
}
void
Packet::write (PacketReadWriteCallback callback) const
{
uint8_t *data = m_buffer.peek_data ();
uint32_t to_write = get_size ();
callback (data, to_write);
}
void
Packet::add_at_end (Packet packet)
{
Buffer src = packet.m_buffer;
m_buffer.add_at_end (src.get_size ());
Buffer::Iterator dest_start = m_buffer.end ();
dest_start.prev (src.get_size ());
dest_start.write (src.begin (), src.end ());
/**
* XXX: we might need to merge the tag list of the
* other packet into the current packet.
*/
}
void
Packet::add_at_end (Packet packet, uint32_t start, uint32_t size)
{
assert (packet.get_size () <= start + size);
Buffer src = packet.m_buffer;
m_buffer.add_at_end (src.get_size ());
Buffer::Iterator dest_start = m_buffer.end ();
dest_start.prev (size);
Buffer::Iterator src_start = src.begin ();
src_start.next (start);
Buffer::Iterator src_end = src_start;
src_end.next (size);
dest_start.write (src_start, src_end);
/**
* XXX: we might need to merge the tag list of the
* other packet into the current packet.
*/
}
void
Packet::remove_at_end (uint32_t size)
{
m_buffer.remove_at_end (size);
}
void
Packet::remove_at_start (uint32_t size)
{
m_buffer.remove_at_start (size);
}
void
Packet::remove_all_tags (void)
{
m_tags.remove_all ();
}
}; // namespace yans

90
src/common/packet.h Normal file
View File

@@ -0,0 +1,90 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005,2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef PACKET_H
#define PACKET_H
#include <stdint.h>
#include "buffer.h"
#include "chunk.h"
#include "tags.h"
#include "yans/callback.h"
namespace yans {
class Packet {
public:
typedef Callback<void,uint8_t *,uint32_t> PacketReadWriteCallback;
Packet ();
Packet (uint32_t size);
Packet create_fragment (uint32_t start, uint32_t length) const;
uint32_t get_size (void) const;
void add (Chunk *chunk);
void peek (Chunk *chunk) const;
void remove (Chunk *chunk);
template <typename T>
void add_tag (T const *tag);
template <typename T>
bool remove_tag (T *tag);
template <typename T>
bool peek_tag (T *tag) const;
template <typename T>
bool update_tag (T const*tag);
void remove_all_tags (void);
void write (PacketReadWriteCallback callback) const;
void add_at_end (Packet packet);
void add_at_end (Packet packet, uint32_t offset, uint32_t size);
void remove_at_end (uint32_t size);
void remove_at_start (uint32_t size);
private:
Packet (Buffer buffer, Tags tags);
Buffer m_buffer;
Tags m_tags;
};
}; // namespace yans
namespace yans {
template <typename T>
void Packet::add_tag (T const*tag)
{
m_tags.add (tag);
}
template <typename T>
bool Packet::remove_tag (T *tag)
{
return m_tags.remove (tag);
}
template <typename T>
bool Packet::peek_tag (T *tag) const
{
return m_tags.peek (tag);
}
template <typename T>
bool Packet::update_tag (T const*tag)
{
return m_tags.update (tag);
}
}; // namespace yans
#endif /* PACKET_H */

99
src/common/pcap-writer.cc Normal file
View File

@@ -0,0 +1,99 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005,2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
/*
* Documentation kindly pointed out by Tom Henderson:
* http://wiki.ethereal.com/Development/LibpcapFileFormat
*/
#include "yans/simulator.h"
#include "yans/system-file.h"
#include "pcap-writer.h"
#include "packet.h"
namespace yans {
enum {
PCAP_ETHERNET = 1
};
PcapWriter::PcapWriter ()
{
m_writer = 0;
m_write_callback = make_callback (&PcapWriter::write_data, this);
}
PcapWriter::~PcapWriter ()
{
delete m_writer;
}
void
PcapWriter::open (char const *name)
{
m_writer = new SystemFile ();
m_writer->open (name);
}
void
PcapWriter::write_header_ethernet (void)
{
write_32 (0xa1b2c3d4);
write_16 (2);
write_16 (4);
write_32 (0);
write_32 (0);
write_32 (0xffff);
write_32 (PCAP_ETHERNET);
}
void
PcapWriter::write_packet (Packet const packet)
{
if (m_writer != 0) {
uint64_t current = Simulator::now_us ();
uint64_t s = current / 1000000;
uint64_t us = current % 1000000;
write_32 (s & 0xffffffff);
write_32 (us & 0xffffffff);
write_32 (packet.get_size ());
write_32 (packet.get_size ());
packet.write (m_write_callback);
}
}
void
PcapWriter::write_data (uint8_t *buffer, uint32_t size)
{
m_writer->write (buffer, size);
}
void
PcapWriter::write_32 (uint32_t data)
{
m_writer->write ((uint8_t*)&data, 4);
}
void
PcapWriter::write_16 (uint16_t data)
{
m_writer->write ((uint8_t*)&data, 2);
}
}; // namespace yans

73
src/common/pcap-writer.h Normal file
View File

@@ -0,0 +1,73 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005,2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef PCAP_WRITER_H
#define PCAP_WRITER_H
#include "yans/callback.h"
#include <stdint.h>
#include "packet.h"
namespace yans {
class SystemFile;
/**
* \brief Pcap output for Packet logger
*
* Log Packets to a file in pcap format which can be
* read by pcap readers.
*/
class PcapWriter {
public:
PcapWriter ();
~PcapWriter ();
/**
* \param name the name of the file to store packet log into.
* This method creates the file if it does not exist. If it
* exists, the file is emptied.
*/
void open (char const *name);
/**
* Write a pcap header in the output file which specifies
* that the content of the file will Packets with
* Ethernet/LLC/SNAP encapsulation.
*/
void write_header_ethernet (void);
/**
* \param packet packet to write to output file
*/
void write_packet (Packet const packet);
private:
void write_data (uint8_t *buffer, uint32_t size);
void write_32 (uint32_t data);
void write_16 (uint16_t data);
SystemFile *m_writer;
Callback<void,uint8_t *,uint32_t> m_write_callback;
};
}; // namespace yans
#endif /* PCAP_WRITER_H */

View File

@@ -0,0 +1,94 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include <cassert>
#include <math.h>
#include "population-analysis.h"
/* This code is a C++ translation of Java code released under the GPLv2
copyright Mathieu Lacage in treegrowth-stable:
http://cutebugs.net/code/treegrowth-stable.
*/
namespace yans {
PopulationAnalysis::PopulationAnalysis ()
{
reset ();
}
PopulationAnalysis::~PopulationAnalysis ()
{}
void
PopulationAnalysis::reset (void)
{
m_n = 0;
m_square_sum = 0.0;
m_mean = 0.0;
m_sum = 0.0;
}
void
PopulationAnalysis::add_term (double term)
{
double d = (term - m_mean);
m_n++;
m_mean += d / m_n;
m_square_sum += d * (term - m_mean);
m_sum += term;
}
uint32_t
PopulationAnalysis::get_n (void)
{
return m_n;
}
double
PopulationAnalysis::get_total (void)
{
return m_sum;
}
double
PopulationAnalysis::get_mean (void)
{
return m_mean;
}
double
PopulationAnalysis::get_standard_deviation (void)
{
if (m_n == 0) {
return 0.0;
}
assert (get_unbiased_variance () >= 0);
double deviation = sqrt (get_unbiased_variance ());
return deviation;
}
double
PopulationAnalysis::get_unbiased_variance (void)
{
if (m_n == 1 || m_n == 0) {
return 0.0;
}
return m_square_sum / (m_n - 1);
}
}; // namespace yans

View File

@@ -0,0 +1,55 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef POPULATION_ANALYSIS_H
#define POPULATION_ANALYSIS_H
#include <stdint.h>
namespace yans {
class PopulationAnalysis {
public:
PopulationAnalysis ();
~PopulationAnalysis ();
void reset (void);
void add_term (double term);
uint32_t get_n (void);
double get_total (void);
double get_mean (void);
double get_standard_deviation (void);
double get_unbiased_variance (void);
private:
double m_mean;
double m_square_sum;
double m_sum;
uint32_t m_n;
};
}; // namespace yans
#endif /* POPULATION_ANALYSIS_H */

47
src/common/position.cc Normal file
View File

@@ -0,0 +1,47 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "position.h"
#include <math.h>
namespace yans {
Position::~Position ()
{}
void
Position::get (double &x, double &y, double &z) const
{
real_get (x,y,z);
}
double
Position::get_distance_from (Position const*position) const
{
double ox,oy,oz;
double x,y,z;
position->real_get (ox,oy,oz);
real_get (x,y,z);
double dx = ox - x;
double dy = oy - y;
double dz = oz - z;
return sqrt (dx*dx+dy*dy+dz*dz);
}
}; // namespace yans

38
src/common/position.h Normal file
View File

@@ -0,0 +1,38 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef POSITION_H
#define POSITION_H
namespace yans {
class Position {
public:
virtual ~Position () = 0;
void get (double &x, double &y, double &z) const;
double get_distance_from (Position const*position) const;
private:
virtual void real_get (double &x, double &y, double &z) const = 0;
};
}; // namespace yans
#endif /* POSITION_H */

View File

@@ -0,0 +1,137 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "random-uniform.h"
#include "seed-generator.h"
#include "rng-mrg32k3a.h"
namespace yans {
class RandomUniformPrivate {
public:
RandomUniformPrivate ();
~RandomUniformPrivate ();
void reset (uint32_t seed);
uint32_t get_max (void) const;
uint32_t get_min (void) const;
uint32_t get_uint (void);
uint32_t get_uint (uint32_t n);
uint32_t get_uint (uint32_t a, uint32_t b);
double get_double (void);
private:
RngMrg32k3a m_rng;
};
RandomUniformPrivate::RandomUniformPrivate ()
: m_rng ()
{
m_rng.reset (SeedGenerator::get ());
}
RandomUniformPrivate::~RandomUniformPrivate ()
{}
void
RandomUniformPrivate::reset (uint32_t seed)
{
m_rng.reset (seed);
}
uint32_t
RandomUniformPrivate::get_max (void) const
{
return m_rng.get_max ();
}
uint32_t
RandomUniformPrivate::get_min (void) const
{
return m_rng.get_min ();
}
uint32_t
RandomUniformPrivate::get_uint (void)
{
return m_rng.get_uint ();
}
uint32_t
RandomUniformPrivate::get_uint (uint32_t n)
{
return m_rng.get_uint (n);
}
uint32_t
RandomUniformPrivate::get_uint (uint32_t a, uint32_t b)
{
return m_rng.get_uint (a, b);
}
double
RandomUniformPrivate::get_double (void)
{
return m_rng.get_double ();
}
RandomUniform::RandomUniform ()
: m_priv (new RandomUniformPrivate ())
{}
RandomUniform::~RandomUniform ()
{
delete m_priv;
m_priv = reinterpret_cast<RandomUniformPrivate *> (0xdeadbeaf);
}
void
RandomUniform::reset (uint32_t seed)
{
m_priv->reset (seed);
}
uint32_t
RandomUniform::get_max (void) const
{
return m_priv->get_max ();
}
uint32_t
RandomUniform::get_min (void) const
{
return m_priv->get_min ();
}
uint32_t
RandomUniform::get_uint (void)
{
return m_priv->get_uint ();
}
uint32_t
RandomUniform::get_uint (uint32_t n)
{
return m_priv->get_uint (n);
}
uint32_t
RandomUniform::get_uint (uint32_t a, uint32_t b)
{
return m_priv->get_uint (a, b);
}
double
RandomUniform::get_double (void)
{
return m_priv->get_double ();
}
}; // namespace yans

View File

@@ -0,0 +1,57 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef RANDOM_UNIFORM_H
#define RANDOM_UNIFORM_H
#include <stdint.h>
namespace yans {
class RandomUniformPrivate;
class RandomUniform {
public:
RandomUniform ();
~RandomUniform ();
void reset (uint32_t seed);
uint32_t get_max (void) const;
uint32_t get_min (void) const;
/* return an integer in the range [min,max] */
uint32_t get_uint (void);
/* return an integer in the range [0,n] */
uint32_t get_uint (uint32_t n);
/* return an integer in the range [a,b] */
uint32_t get_uint (uint32_t a, uint32_t b);
/* return a floating-point number in the
* range [0,1)
*/
double get_double (void);
private:
RandomUniformPrivate *m_priv;
};
}; // namespace yans
#endif /* RANDOM_UNIFORM_H */

139
src/common/ref-ptr.h Normal file
View File

@@ -0,0 +1,139 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005,2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef REF_PTR_H
#define REF_PTR_H
namespace yans {
template <typename T>
class RefPtr {
private:
T *m_env;
public:
RefPtr ()
: m_env (0)
{}
RefPtr (T *env)
: m_env (env)
{}
RefPtr (RefPtr const&o)
: m_env (o.m_env)
{
if (m_env != 0) {
m_env->m_count++;
}
}
// allow conversions from T to T const.
template <typename U>
RefPtr (RefPtr<U> const &o)
: m_env (o.peek ())
{
if (m_env != 0) {
m_env->m_count++;
}
}
~RefPtr ()
{
if (m_env != 0) {
m_env->m_count--;
if (m_env->m_count == 0) {
m_env->destroy ();
}
}
}
RefPtr &operator = (RefPtr const& o)
{
if (o.m_env != 0) {
o.m_env->m_count++;
}
if (m_env != 0) {
m_env->m_count--;
if (m_env->m_count == 0) {
m_env->destroy ();
}
}
m_env = o.m_env;
return *this;
}
T *operator -> ()
{
return m_env;
}
T *operator -> () const
{
return m_env;
}
// allow if (!sp)
bool operator! ()
{
return m_env == 0;
}
private:
class Tester {
private:
void operator delete (void *);
};
public:
// allow if (sp)
operator Tester * () const
{
if (m_env == 0) {
return 0;
}
static Tester test;
return &test;
}
// allow if (sp == 0)
inline friend bool operator == (RefPtr const &lhs, T const *rhs)
{
return lhs.m_env == rhs;
}
// allow if (0 == sp)
inline friend bool operator == (T const *lhs, RefPtr &rhs)
{
return lhs == rhs.m_env;
}
// allow if (sp != 0)
inline friend bool operator != (RefPtr const &lhs, T const *rhs)
{
return lhs.m_env != rhs;
}
// allow if (0 != sp)
inline friend bool operator != (T const *lhs, RefPtr &rhs)
{
return lhs != rhs.m_env;
}
T *peek (void)
{
return m_env;
}
T *peek (void) const
{
return m_env;
}
};
}; // namespace yans
#endif /* REF_PTR_H */

336
src/common/rng-mrg32k3a.cc Normal file
View File

@@ -0,0 +1,336 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (C) 2001 Pierre L'Ecuyer (lecuyer@iro.umontreal.ca)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include "rng-mrg32k3a.h"
#include "seed-generator.h"
#include <iostream>
#ifndef MAXINT
#define MAXINT 2147483647 // XX [for now]
#endif
using namespace std;
namespace
{
const double m1 = 4294967087.0;
const double m2 = 4294944443.0;
const double norm = 1.0 / (m1 + 1.0);
const double a12 = 1403580.0;
const double a13n = 810728.0;
const double a21 = 527612.0;
const double a23n = 1370589.0;
const double two17 = 131072.0;
const double two53 = 9007199254740992.0;
const double fact = 5.9604644775390625e-8; /* 1 / 2^24 */
// The following are the transition matrices of the two MRG
// components (in matrix form), raised to the powers -1, 1,
// 2^76, and 2^127, resp.
const double InvA1[3][3] = { // Inverse of A1p0
{ 184888585.0, 0.0, 1945170933.0 },
{ 1.0, 0.0, 0.0 },
{ 0.0, 1.0, 0.0 }
};
const double InvA2[3][3] = { // Inverse of A2p0
{ 0.0, 360363334.0, 4225571728.0 },
{ 1.0, 0.0, 0.0 },
{ 0.0, 1.0, 0.0 }
};
const double A1p0[3][3] = {
{ 0.0, 1.0, 0.0 },
{ 0.0, 0.0, 1.0 },
{ -810728.0, 1403580.0, 0.0 }
};
const double A2p0[3][3] = {
{ 0.0, 1.0, 0.0 },
{ 0.0, 0.0, 1.0 },
{ -1370589.0, 0.0, 527612.0 }
};
const double A1p76[3][3] = {
{ 82758667.0, 1871391091.0, 4127413238.0 },
{ 3672831523.0, 69195019.0, 1871391091.0 },
{ 3672091415.0, 3528743235.0, 69195019.0 }
};
const double A2p76[3][3] = {
{ 1511326704.0, 3759209742.0, 1610795712.0 },
{ 4292754251.0, 1511326704.0, 3889917532.0 },
{ 3859662829.0, 4292754251.0, 3708466080.0 }
};
const double A1p127[3][3] = {
{ 2427906178.0, 3580155704.0, 949770784.0 },
{ 226153695.0, 1230515664.0, 3580155704.0 },
{ 1988835001.0, 986791581.0, 1230515664.0 }
};
const double A2p127[3][3] = {
{ 1464411153.0, 277697599.0, 1610723613.0 },
{ 32183930.0, 1464411153.0, 1022607788.0 },
{ 2824425944.0, 32183930.0, 2093834863.0 }
};
} // end of anonymous namespace
//-------------------------------------------------------------------
// Return (a*s + c) MOD m; a, s, c and m must be < 2^35
//
double
RngMrg32k3a::MultModM (double a, double s, double c, double m)
{
double v;
long a1;
v=a*s+c;
if (v >= two53 || v <= -two53) {
a1 = static_cast<long> (a / two17); a -= a1 * two17;
v =a1*s;
a1 = static_cast<long> (v / m); v -= a1 * m;
v = v * two17 + a * s + c;
}
a1 = static_cast<long> (v / m);
/* in case v < 0)*/
if ((v -= a1 * m) < 0.0) return v += m; else return v;
}
//-------------------------------------------------------------------
// Compute the vector v = A*s MOD m. Assume that -m < s[i] < m.
// Works also when v = s.
//
void
RngMrg32k3a::MatVecModM (const double A[3][3], const double s[3], double v[3],
double m)
{
int i;
double x[3]; // Necessary if v = s
for (i = 0; i < 3; ++i) {
x[i] = MultModM (A[i][0], s[0], 0.0, m);
x[i] = MultModM (A[i][1], s[1], x[i], m);
x[i] = MultModM (A[i][2], s[2], x[i], m);
}
for (i = 0; i < 3; ++i)
v[i] = x[i];
}
//-------------------------------------------------------------------
// Compute the matrix C = A*B MOD m. Assume that -m < s[i] < m.
// Note: works also if A = C or B = C or A = B = C.
//
void
RngMrg32k3a::MatMatModM (const double A[3][3], const double B[3][3],
double C[3][3], double m)
{
int i, j;
double V[3], W[3][3];
for (i = 0; i < 3; ++i) {
for (j = 0; j < 3; ++j)
V[j] = B[j][i];
MatVecModM (A, V, V, m);
for (j = 0; j < 3; ++j)
W[j][i] = V[j];
}
for (i = 0; i < 3; ++i)
for (j = 0; j < 3; ++j)
C[i][j] = W[i][j];
}
//-------------------------------------------------------------------
// Compute the matrix B = (A^(2^e) Mod m); works also if A = B.
//
void
RngMrg32k3a::MatTwoPowModM (const double A[3][3], double B[3][3], double m,
long e)
{
int i, j;
/* initialize: B = A */
if (A != B) {
for (i = 0; i < 3; ++i)
for (j = 0; j < 3; ++j)
B[i][j] = A[i][j];
}
/* Compute B = A^(2^e) mod m */
for (i = 0; i < e; i++)
MatMatModM (B, B, B, m);
}
//-------------------------------------------------------------------
// Compute the matrix B = (A^n Mod m); works even if A = B.
//
void
RngMrg32k3a::MatPowModM (const double A[3][3], double B[3][3], double m,
long n)
{
int i, j;
double W[3][3];
/* initialize: W = A; B = I */
for (i = 0; i < 3; ++i)
for (j = 0; j < 3; ++j) {
W[i][j] = A[i][j];
B[i][j] = 0.0;
}
for (j = 0; j < 3; ++j)
B[j][j] = 1.0;
/* Compute B = A^n mod m using the binary decomposition of n */
while (n > 0) {
if (n % 2) MatMatModM (W, B, B, m);
MatMatModM (W, W, W, m);
n/=2;
}
}
//--------------------------------------------------------------------
// Check that the seeds are legitimate values. Returns 0 if legal
// seeds, -1 otherwise.
//
int
RngMrg32k3a::CheckSeed (const unsigned long seed[6])
{
int i;
for (i = 0; i < 3; ++i) {
if (seed[i] >= m1) {
std::cerr << "****************************************" << std::endl
<< "ERROR: Seed["<<i<<"] >= 4294967087, Seed is not set." << std::endl
<< "****************************************" << std::endl;
return (-1);
}
}
for (i = 3; i < 6; ++i) {
if (seed[i] >= m2) {
std::cerr << "****************************************" << std::endl
<< "ERROR: Seed["<<i<<"] >= 429444443, Seed is not set."<<std::endl
<< "****************************************" <<std::endl;
return (-1);
}
}
if (seed[0] == 0 && seed[1] == 0 && seed[2] == 0) {
std::cerr<< "****************************************" << std::endl
<< "ERROR: First 3 seeds = 0." << std::endl
<< "****************************************" << std::endl;
return (-1);
}
if (seed[3] == 0 && seed[4] == 0 && seed[5] == 0) {
std::cerr << "****************************************" <<std::endl
<< "ERROR: Last 3 seeds = 0." << std::endl
<< "****************************************" << std::endl;
return (-1);
}
return 0;
}
//-------------------------------------------------------------------------
// Generate the next random number.
//
double RngMrg32k3a::U01 ()
{
long k;
double p1, p2, u;
/* Component 1 */
p1 = a12 * Cg_[1] - a13n * Cg_[0];
k = static_cast<long> (p1 / m1);
p1 -= k * m1;
if (p1 < 0.0) p1 += m1;
Cg_[0] = Cg_[1]; Cg_[1] = Cg_[2]; Cg_[2] = p1;
/* Component 2 */
p2 = a21 * Cg_[5] - a23n * Cg_[3];
k = static_cast<long> (p2 / m2);
p2 -= k * m2;
if (p2 < 0.0) p2 += m2;
Cg_[3] = Cg_[4]; Cg_[4] = Cg_[5]; Cg_[5] = p2;
/* Combination */
u = ((p1 > p2) ? (p1 - p2) * norm : (p1 - p2 + m1) * norm);
return u;
}
//-------------------------------------------------------------------------
// Generate the next random number with extended (53 bits) precision.
//
double RngMrg32k3a::U01d ()
{
double u;
u = U01();
u += (U01() - 1.0) * fact;
return (u < 0.0) ? u + 1.0 : u;
}
//*************************************************************************
// Public members of the class start here
//-------------------------------------------------------------------------
RngMrg32k3a::RngMrg32k3a ()
{}
void RngMrg32k3a::reset (long seed)
{
for (int i = 0; i < 6; ++i) {
Bg_[i] = Cg_[i] = Ig_[i] = seed;
}
}
//-------------------------------------------------------------------------
// Generate the next random number.
//
uint32_t
RngMrg32k3a::get_max (void) const
{
return MAXINT;
}
uint32_t
RngMrg32k3a::get_min (void) const
{
return 0;
}
uint32_t
RngMrg32k3a::get_uint (void)
{
return get_uint (0, MAXINT);
}
uint32_t
RngMrg32k3a::get_uint (uint32_t n)
{
return get_uint (0, n);
}
uint32_t
RngMrg32k3a::get_uint (uint32_t low, uint32_t high)
{
return ((uint32_t) (low + (uint32_t) (((uint32_t)
(high-low+1)) * U01())));
}
double
RngMrg32k3a::get_double (void)
{
return U01d ();
}

65
src/common/rng-mrg32k3a.h Normal file
View File

@@ -0,0 +1,65 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (C) 2001 Pierre L'Ecuyer (lecuyer@iro.umontreal.ca)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#ifndef RNG_MRG32k3A_H
#define RNG_MRG32k3A_H
#include <stdint.h>
/*
* Use class RNG in real programs.
*/
class RngMrg32k3a {
public:
RngMrg32k3a ();
void reset (long seed);
uint32_t get_max (void) const;
uint32_t get_min (void) const;
uint32_t get_uint (void);
uint32_t get_uint (uint32_t n);
uint32_t get_uint (uint32_t low, uint32_t high);
double get_double (void);
private:
double U01 ();
double U01d ();
double MultModM (double a, double s, double c, double m);
void MatVecModM (const double A[3][3], const double s[3], double v[3],
double m);
void MatMatModM (const double A[3][3], const double B[3][3],
double C[3][3], double m) ;
void MatTwoPowModM (const double A[3][3], double B[3][3], double m,
long e);
void MatPowModM (const double A[3][3], double B[3][3], double m,
long n);
int CheckSeed (const unsigned long seed[6]);
/*
Vectors to store the current seed, the beginning of the current block
(substream) and the beginning of the current stream.
*/
double Cg_[6], Bg_[6], Ig_[6];
};
#endif /* RNG_MRG32k3A_H */

View File

@@ -0,0 +1,61 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "seed-generator.h"
#include "rng-mrg32k3a.h"
namespace yans {
class SeedGeneratorPrivate {
public:
static void destroy (void);
static void reset (uint32_t seed);
static uint32_t get (void);
private:
static RngMrg32k3a m_generator;
};
RngMrg32k3a SeedGeneratorPrivate::m_generator;
void
SeedGeneratorPrivate::reset (uint32_t seed)
{
m_generator.reset (seed);
}
uint32_t
SeedGeneratorPrivate::get (void)
{
return m_generator.get_uint ();
}
void
SeedGenerator::reset (uint32_t seed)
{
SeedGeneratorPrivate::reset (seed);
}
uint32_t
SeedGenerator::get (void)
{
return SeedGeneratorPrivate::get ();
}
}; // namespace yans

View File

@@ -0,0 +1,40 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef SEED_GENERATOR_H
#define SEED_GENERATOR_H
#include <stdint.h>
namespace yans {
class SeedGeneratorPrivate;
class SeedGenerator {
public:
static void reset (uint32_t seed);
static uint32_t get (void);
private:
SeedGenerator ();
};
}; // namespace yans
#endif /* SEED_GENERATOR_H */

32
src/common/sgi-hashmap.h Normal file
View File

@@ -0,0 +1,32 @@
/* This code snippet was ripped out of the gcc
* documentation and slightly modified to work
* with gcc 4.x
*/
#ifndef SGI_HASHMAP_H
#define SGI_HASHMAP_H
/* To use gcc extensions.
*/
#ifdef __GNUC__
#if __GNUC__ < 3
#include <hash_map.h>
namespace Sgi { using ::hash_map; }; // inherit globals
#else
#if __GNUC__ < 4
#include <ext/hash_map>
#if __GNUC_MINOR__ == 0
namespace Sgi = std; // GCC 3.0
#else
namespace Sgi = ::__gnu_cxx; // GCC 3.1 and later
#endif
#else // gcc 4.x and later
#include <ext/hash_map>
namespace Sgi = ::__gnu_cxx;
#endif
#endif
#else // ... there are other compilers, right?
namespace Sgi = std;
#endif
#endif /* SGI_HASHMAP_H */

View File

@@ -0,0 +1,237 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef SI_TRACED_VARIABLE_TCC
#define SI_TRACED_VARIABLE_TCC
#include "yans/callback.h"
#include <stdint.h>
namespace yans {
class SiTracedVariableBase {
public:
typedef Callback<void,int64_t, int64_t> ChangeNotifyCallback;
SiTracedVariableBase () {}
SiTracedVariableBase (SiTracedVariableBase const &o) {}
SiTracedVariableBase &operator = (SiTracedVariableBase const &o) {
return *this;
}
~SiTracedVariableBase () {}
void set_callback(ChangeNotifyCallback callback) {
m_callback = callback;
}
protected:
void notify (int64_t old_val, int64_t new_val) {
if (old_val != new_val && !m_callback.is_null ()) {
m_callback (old_val, new_val);
}
}
private:
ChangeNotifyCallback m_callback;
};
template <typename T>
class UiTracedVariable;
/**
* \brief trace variables of type "signed integer"
*
* This template class implements a POD type: it
* behaves like any other variable of type "signed integer"
* except that it also reports any changes to its
* value with its internal callback.
*
* To instantiate a 32-bit signed variable (to store
* a TCP counter for example), you would create a variable of type
* yans::UiTracedVariable<int32_t> :
\code
#include <stdint.h>
#include "yans/si-traced-variable.tcc"
yans::SiTracedVariable<uint16_t> var;
\endcode
* and you would use it like any other variable of type int32_t:
\code
var += 12;
var = 10;
var = -10;
\endcode
*/
template <typename T>
class SiTracedVariable : public SiTracedVariableBase {
public:
SiTracedVariable ()
: m_var (0)
{}
SiTracedVariable (T const &var)
: m_var (var)
{}
SiTracedVariable &operator = (SiTracedVariable const &o) {
assign (o.get ());
return *this;
}
template <typename TT>
SiTracedVariable &operator = (SiTracedVariable<TT> const &o) {
assign (o.get ());
return *this;
}
template <typename TT>
SiTracedVariable &operator = (UiTracedVariable<TT> const &o) {
assign (o.get ());
return *this;
}
SiTracedVariable &operator++ () {
assign (get () + 1);
return *this;
}
SiTracedVariable &operator-- () {
assign (get () - 1);
return *this;
}
SiTracedVariable operator++ (int) {
SiTracedVariable old (*this);
++*this;
return old;
}
SiTracedVariable operator-- (int) {
SiTracedVariable old (*this);
--*this;
return old;
}
operator T () const {
return get ();
}
void assign (T var) {
notify (m_var, var);
m_var = var;
}
T get (void) const {
return m_var;
}
private:
T m_var;
};
template <typename T>
SiTracedVariable<T> &operator += (SiTracedVariable<T> &lhs, SiTracedVariable<T> const &rhs) {
lhs.assign (lhs.get () + rhs.get ());
return lhs;
}
template <typename T>
SiTracedVariable<T> &operator -= (SiTracedVariable<T> &lhs, SiTracedVariable<T> const &rhs) {
lhs.assign (lhs.get () - rhs.get ());
return lhs;
}
template <typename T>
SiTracedVariable<T> &operator *= (SiTracedVariable<T> &lhs, SiTracedVariable<T> const &rhs) {
lhs.assign (lhs.get () * rhs.get ());
return lhs;
}
template <typename T>
SiTracedVariable<T> &operator /= (SiTracedVariable<T> &lhs, SiTracedVariable<T> const &rhs) {
lhs.assign (lhs.get () / rhs.get ());
return lhs;
}
template <typename T>
SiTracedVariable<T> &operator <<= (SiTracedVariable<T> &lhs, SiTracedVariable<T> const &rhs) {
lhs.assign (lhs.get () << rhs.get ());
return lhs;
}
template <typename T>
SiTracedVariable<T> &operator >>= (SiTracedVariable<T> &lhs, SiTracedVariable<T> const &rhs) {
lhs.assign (lhs.get () >> rhs.get ());
return lhs;
}
template <typename T>
SiTracedVariable<T> &operator &= (SiTracedVariable<T> &lhs, SiTracedVariable<T> const &rhs) {
lhs.assign (lhs.get () & rhs.get ());
return lhs;
}
template <typename T>
SiTracedVariable<T> &operator |= (SiTracedVariable<T> &lhs, SiTracedVariable<T> const &rhs) {
lhs.assign (lhs.get () | rhs.get ());
return lhs;
}
template <typename T>
SiTracedVariable<T> &operator ^= (SiTracedVariable<T> &lhs, SiTracedVariable<T> const &rhs) {
lhs.assign (lhs.get () ^ rhs.get ());
return lhs;
}
template <typename T, typename U>
SiTracedVariable<T> &operator += (SiTracedVariable<T> &lhs, U const &rhs) {
lhs.assign (lhs.get () + rhs);
return lhs;
}
template <typename T, typename U>
SiTracedVariable<T> &operator -= (SiTracedVariable<T> &lhs, U const &rhs) {
lhs.assign (lhs.get () - rhs);
return lhs;
}
template <typename T, typename U>
SiTracedVariable<T> &operator *= (SiTracedVariable<T> &lhs, U const &rhs) {
lhs.assign (lhs.get () * rhs);
return lhs;
}
template <typename T, typename U>
SiTracedVariable<T> &operator /= (SiTracedVariable<T> &lhs, U const &rhs) {
lhs.assign (lhs.get () / rhs);
return lhs;
}
template <typename T, typename U>
SiTracedVariable<T> &operator <<= (SiTracedVariable<T> &lhs, U const &rhs) {
lhs.assign (lhs.get () << rhs);
return lhs;
}
template <typename T, typename U>
SiTracedVariable<T> &operator >>= (SiTracedVariable<T> &lhs, U const &rhs) {
lhs.assign (lhs.get () >> rhs);
return lhs;
}
template <typename T, typename U>
SiTracedVariable<T> &operator &= (SiTracedVariable<T> &lhs, U const &rhs) {
lhs.assign (lhs.get () & rhs);
return lhs;
}
template <typename T, typename U>
SiTracedVariable<T> &operator |= (SiTracedVariable<T> &lhs, U const &rhs) {
lhs.assign (lhs.get () | rhs);
return lhs;
}
template <typename T, typename U>
SiTracedVariable<T> &operator ^= (SiTracedVariable<T> &lhs, U const &rhs) {
lhs.assign (lhs.get () ^ rhs);
return lhs;
}
}; // namespace yans
#endif /* TRACED_VARIABLE_TCC */

View File

@@ -0,0 +1,46 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "static-position.h"
namespace yans {
StaticPosition::StaticPosition ()
: m_x (0.0), m_y (0.0), m_z (0.0)
{}
StaticPosition::~StaticPosition ()
{}
void
StaticPosition::set (double x, double y, double z)
{
m_x = x;
m_y = y;
m_z = z;
}
void
StaticPosition::real_get (double &x, double &y, double &z) const
{
x = m_x;
y = m_y;
z = m_z;
}
}; // namespace yans

View File

@@ -0,0 +1,43 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef STATIC_POSITION_H
#define STATIC_POSITION_H
#include "position.h"
namespace yans {
class StaticPosition : public Position {
public:
StaticPosition ();
virtual ~StaticPosition ();
void set (double x, double y, double z);
private:
virtual void real_get (double &x, double &y, double &z) const;
double m_x;
double m_y;
double m_z;
};
}; // namespace yans
#endif /* STATIC_POSITION_H */

View File

@@ -0,0 +1,68 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "static-speed-position.h"
#include "yans/simulator.h"
namespace yans {
StaticSpeedPosition::StaticSpeedPosition ()
: m_x (0.0),
m_y (0.0),
m_z (0.0),
m_dx (0.0),
m_dy (0.0),
m_dz (0.0),
m_prev_us (0)
{}
StaticSpeedPosition::~StaticSpeedPosition ()
{}
void
StaticSpeedPosition::set (double x, double y, double z)
{
m_x = x;
m_y = y;
m_z = z;
}
void
StaticSpeedPosition::set_delta (double dx, double dy, double dz)
{
m_dx = dx / 1000000;
m_dy = dy / 1000000;
m_dz = dz / 1000000;
}
void
StaticSpeedPosition::real_get (double &x, double &y, double &z) const
{
uint64_t now_us = Simulator::now_us ();
uint64_t delta_us = now_us - m_prev_us;
m_x += m_dx * delta_us;
m_y += m_dy * delta_us;
m_z += m_dz * delta_us;
m_prev_us = now_us;
x = m_x;
y = m_y;
z = m_z;
}
}; // namespace yans

View File

@@ -0,0 +1,51 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef STATIC_SPEED_POSITION_H
#define STATIC_SPEED_POSITION_H
#include <stdint.h>
#include "position.h"
namespace yans {
class StaticSpeedPosition : public Position {
public:
StaticSpeedPosition ();
virtual ~StaticSpeedPosition ();
// m
void set (double x, double y, double z);
// m/s
void set_delta (double dx, double dy, double dz);
private:
virtual void real_get (double &x, double &y, double &z) const;
mutable double m_x;
mutable double m_y;
mutable double m_z;
double m_dx;
double m_dy;
double m_dz;
mutable uint64_t m_prev_us;
};
}; // namespace yans
#endif /* STATIC_SPEED_POSITION */

322
src/common/tags.cc Normal file
View File

@@ -0,0 +1,322 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "tags.h"
#include <string.h>
namespace yans {
TagsPrettyPrinterRegistry::PrettyPrinters TagsPrettyPrinterRegistry::g_pretty_printers;
void
TagsPrettyPrinterRegistry::record (uint32_t uid, void (*cb) (uint8_t [Tags::SIZE], std::ostream &))
{
for (PrettyPrintersI i = g_pretty_printers.begin ();
i != g_pretty_printers.end (); i++) {
if (i->first == uid) {
i->second = cb;
return;
}
}
g_pretty_printers.push_back (std::make_pair (uid, cb));
}
void
TagsPrettyPrinterRegistry::pretty_print (uint32_t uid, uint8_t buf[Tags::SIZE], std::ostream &os)
{
for (PrettyPrintersI i = g_pretty_printers.begin ();
i != g_pretty_printers.end (); i++) {
if (i->first == uid) {
if (i->second == 0) {
os << "tag uid="<<uid<<" null pretty printer."<<std::endl;
} else {
(*(i->second)) (buf, os);
}
return;
}
}
os << "tag uid="<<uid<<" no pretty printer registered."<< std::endl;
}
uint32_t
Tags::UidFactory::create (void)
{
static uint32_t uid = 0;
uid++;
return uid;
}
#ifdef USE_FREE_LIST
struct Tags::TagData *Tags::g_free = 0;
uint32_t Tags::g_n_free = 0;
struct Tags::TagData *
Tags::alloc_data (void)
{
struct Tags::TagData *retval;
if (g_free != 0) {
retval = g_free;
g_free = g_free->m_next;
g_n_free--;
} else {
retval = new struct Tags::TagData ();
}
return retval;
}
void
Tags::free_data (struct TagData *data)
{
if (g_n_free > 1000) {
delete data;
return;
}
g_n_free++;
data->m_next = g_free;
g_free = data;
}
#else
struct Tags::TagData *
Tags::alloc_data (void)
{
struct Tags::TagData *retval;
retval = new struct Tags::TagData ();
return retval;
}
void
Tags::free_data (struct TagData *data)
{
delete data;
}
#endif
bool
Tags::remove (uint32_t id)
{
bool found = false;
for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next) {
if (cur->m_id == id) {
found = true;
}
}
if (!found) {
return false;
}
struct TagData *start = 0;
struct TagData **prev_next = &start;
for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next) {
if (cur->m_id == id) {
/**
* XXX
* Note: I believe that we could optimize this to
* avoid copying each TagData located after the target id
* and just link the already-copied list to the next tag.
*/
continue;
}
struct TagData *copy = alloc_data ();
copy->m_id = cur->m_id;
copy->m_count = 1;
copy->m_next = 0;
memcpy (copy->m_data, cur->m_data, Tags::SIZE);
*prev_next = copy;
prev_next = &copy->m_next;
}
*prev_next = 0;
remove_all ();
m_next = start;
return true;
}
bool
Tags::update (uint8_t const*buffer, uint32_t id)
{
if (!remove (id)) {
return false;
}
struct TagData *new_start = alloc_data ();
new_start->m_count = 1;
new_start->m_next = 0;
new_start->m_id = id;
memcpy (new_start->m_data, buffer, Tags::SIZE);
new_start->m_next = m_next;
m_next = new_start;
return true;
}
void
Tags::pretty_print (std::ostream &os)
{
for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next) {
TagsPrettyPrinterRegistry::pretty_print (cur->m_id, cur->m_data, os);
}
}
}; // namespace yans
#ifdef RUN_SELF_TESTS
#include "yans/test.h"
#include <iomanip>
#include <iostream>
namespace yans {
class TagsTest : Test {
public:
TagsTest ();
virtual ~TagsTest ();
virtual bool run_tests (void);
};
struct my_tag_a {
uint8_t a;
};
struct my_tag_b {
uint32_t b;
};
struct my_tag_c {
uint8_t c [Tags::SIZE];
};
struct my_invalid_tag {
uint8_t invalid [Tags::SIZE+1];
};
static void
my_tag_a_pretty_printer_cb (struct my_tag_a *a, std::ostream &os)
{
os << "struct my_tag_a, a="<<(uint32_t)a->a<<std::endl;
}
static void
my_tag_b_pretty_printer_cb (struct my_tag_b *b, std::ostream &os)
{
os << "struct my_tag_b, b="<<b->b<<std::endl;
}
static void
my_tag_c_pretty_printer_cb (struct my_tag_c *c, std::ostream &os)
{
os << "struct my_tag_c, c="<<(uint32_t)c->c[0]<<std::endl;
}
static TagPrettyPrinter<struct my_tag_a> g_my_tag_a_pretty_printer (&my_tag_a_pretty_printer_cb);
static TagPrettyPrinter<struct my_tag_b> g_my_tag_b_pretty_printer (&my_tag_b_pretty_printer_cb);
static TagPrettyPrinter<struct my_tag_c> g_my_tag_c_pretty_printer (&my_tag_c_pretty_printer_cb);
TagsTest::TagsTest ()
: Test ("Tags")
{}
TagsTest::~TagsTest ()
{}
bool
TagsTest::run_tests (void)
{
bool ok = true;
// build initial tag.
Tags tags;
struct my_tag_a a;
a.a = 10;
tags.add (&a);
a.a = 0;
tags.peek (&a);
if (a.a != 10) {
ok = false;
}
//tags.pretty_print (std::cout);
struct my_tag_b b;
b.b = 0xff;
tags.add (&b);
b.b = 0;
tags.peek (&b);
if (b.b != 0xff) {
ok = false;
}
//tags.pretty_print (std::cout);
// make sure copy contains copy.
Tags other = tags;
//other.pretty_print (std::cout);
//tags.pretty_print (std::cout);
struct my_tag_a o_a;
o_a.a = 0;
other.peek (&o_a);
if (o_a.a != 10) {
ok = false;
}
struct my_tag_b o_b;
other.peek (&o_b);
if (o_b.b != 0xff) {
ok = false;
}
// remove data.
other.remove (&o_a);
if (other.peek (&o_a)) {
ok = false;
}
//other.pretty_print (std::cout);
if (!tags.peek (&o_a)) {
ok = false;
}
other.remove (&o_b);
if (other.peek (&o_b)) {
ok = false;
}
if (!tags.peek (&o_b)) {
ok = false;
}
other = tags;
Tags another = other;
struct my_tag_c c;
c.c[0] = 0x66;
another.add (&c);
c.c[0] = 0;
another.peek (&c);
if (!another.peek (&c)) {
ok = false;
}
if (tags.peek (&c)) {
ok = false;
}
other = other;
//other.pretty_print (std::cout);
//struct my_invalid_tag invalid;
//tags.add (&invalid);
return ok;
}
static TagsTest g_tags_test;
}; // namespace yans
#endif /* RUN_SELF_TESTS */

292
src/common/tags.h Normal file
View File

@@ -0,0 +1,292 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef TAGS_H
#define TAGS_H
#include <stdint.h>
#include <ostream>
#include <vector>
namespace yans {
template <typename T>
class TagPrettyPrinter;
class Tags {
public:
inline Tags ();
inline Tags (Tags const &o);
inline Tags &operator = (Tags const &o);
inline ~Tags ();
template <typename T>
void add (T const*tag);
template <typename T>
bool remove (T *tag);
template <typename T>
bool peek (T *tag) const;
template <typename T>
bool update (T const*tag);
void pretty_print (std::ostream &os);
inline void remove_all (void);
enum {
SIZE = 16
};
private:
struct TagData {
struct TagData *m_next;
uint32_t m_id;
uint32_t m_count;
uint8_t m_data[Tags::SIZE];
};
class UidFactory {
public:
static uint32_t create (void);
};
bool remove (uint32_t id);
bool update (uint8_t const*buffer, uint32_t id);
struct Tags::TagData *alloc_data (void);
void free_data (struct TagData *data);
static struct Tags::TagData *g_free;
static uint32_t g_n_free;
struct TagData *m_next;
};
/**
* This class is used to register a pretty-printer
* callback function to print in a nice user-friendly
* way the content of the target type. To register
* such a type, all you need to do is instantiate
* an instance of this type any number of times (at
* least once). Typical users will create static global
* variable of this type and construct it with
* the proper function pointer.
*/
template <typename T>
class TagPrettyPrinter {
public:
TagPrettyPrinter<T> (void(*) (T *, std::ostream &));
private:
TagPrettyPrinter<T> ();
static void pretty_print_cb (uint8_t *buf, std::ostream &os);
static void(*g_pretty_printer) (T *, std::ostream &);
};
class TagsPrettyPrinterRegistry {
public:
static void record (uint32_t uid, void (*cb) (uint8_t buf[Tags::SIZE], std::ostream &os));
static void pretty_print (uint32_t uid, uint8_t buf[Tags::SIZE], std::ostream &os);
private:
typedef std::vector<std::pair<uint32_t, void (*) (uint8_t [Tags::SIZE], std::ostream &)> > PrettyPrinters;
typedef std::vector<std::pair<uint32_t, void (*) (uint8_t [Tags::SIZE], std::ostream &)> >::iterator PrettyPrintersI;
static PrettyPrinters g_pretty_printers;
};
}; // namespace yans
#include <cassert>
#include <string.h>
namespace yans {
/**
* The TypeUid class is used to create a mapping Type --> uid
* Of course, this class is not perfect: the value of the uid
* associated to a given type could change accross multiple
* runs of the same program on the same platform or accross
* multiple platforms. There exist no generic portable
* workaround/solution to this problem also known as
* "type id management". The only other reliable solution
* is to ask programmers to assign themselves a uid to each
* type but this is painful from a management perspective.
*
* So, for now, this class is good enough provided you do
* not try to serialize to permanent storage the type uids
* generated by this class. Just don't try to do it. It might
* seem to work but it will fail spectacularily in certain
* use-cases and you will cry from debugging this. Hear me ?
*/
template <typename T>
class TypeUid {
public:
static const uint32_t get_uid (void);
private:
T real_type;
};
template <typename T>
const uint32_t TypeUid<T>::get_uid (void)
{
static const uint32_t uid = Tags::UidFactory::create ();
return uid;
}
/**
* Implementation of the TagPrettyPrinter registration class.
* It records a callback with the TagPrettyPrinterRegistry.
* This callback performs type conversion before forwarding
* the call to the user-provided function.
*/
template <typename T>
TagPrettyPrinter<T>::TagPrettyPrinter (void(*pretty_printer) (T *, std::ostream &))
{
g_pretty_printer = pretty_printer;
TagsPrettyPrinterRegistry::record (TypeUid<T>::get_uid (),
&TagPrettyPrinter<T>::pretty_print_cb);
}
template <typename T>
void
TagPrettyPrinter<T>::pretty_print_cb (uint8_t buf[Tags::SIZE], std::ostream &os)
{
assert (sizeof (T) <= Tags::SIZE);
T *tag = reinterpret_cast<T *> (buf);
(*g_pretty_printer) (tag, os);
}
template <typename T>
void (*TagPrettyPrinter<T>::g_pretty_printer) (T *, std::ostream &) = 0;
template <typename T>
void
Tags::add (T const*tag)
{
assert (sizeof (T) <= Tags::SIZE);
uint8_t const*buf = reinterpret_cast<uint8_t const*> (tag);
// ensure this id was not yet added
for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next) {
assert (cur->m_id != TypeUid<T>::get_uid ());
}
struct TagData *new_start = alloc_data ();
new_start->m_count = 1;
new_start->m_next = 0;
new_start->m_id = TypeUid<T>::get_uid ();
memcpy (new_start->m_data, buf, sizeof (T));
new_start->m_next = m_next;
m_next = new_start;
}
template <typename T>
bool
Tags::remove (T *tag)
{
assert (sizeof (T) <= Tags::SIZE);
return remove (TypeUid<T>::get_uid ());
}
template <typename T>
bool
Tags::peek (T *tag) const
{
assert (sizeof (T) <= Tags::SIZE);
uint8_t *buf = reinterpret_cast<uint8_t *> (tag);
for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next) {
if (cur->m_id == TypeUid<T>::get_uid ()) {
/* found tag */
memcpy (buf, cur->m_data, sizeof (T));
return true;
}
}
/* no tag found */
return false;
}
template <typename T>
bool
Tags::update (T const*tag)
{
assert (sizeof (T) <= Tags::SIZE);
uint8_t const*buf = reinterpret_cast<uint8_t const*> (tag);
return update (buf, TypeUid<T>::get_uid ());
}
Tags::Tags ()
: m_next ()
{}
Tags::Tags (Tags const &o)
: m_next (o.m_next)
{
if (m_next != 0) {
m_next->m_count++;
}
}
Tags &
Tags::operator = (Tags const &o)
{
// self assignment
if (m_next == o.m_next) {
return *this;
}
remove_all ();
m_next = o.m_next;
if (m_next != 0) {
m_next->m_count++;
}
return *this;
}
Tags::~Tags ()
{
remove_all ();
}
void
Tags::remove_all (void)
{
struct TagData *prev = 0;
for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next) {
cur->m_count--;
if (cur->m_count > 0) {
break;
}
if (prev != 0) {
free_data (prev);
}
prev = cur;
}
if (prev != 0) {
free_data (prev);
}
m_next = 0;
}
}; // namespace yans
#endif /* TAGS_H */

77
src/common/timeout.cc Normal file
View File

@@ -0,0 +1,77 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "timeout.h"
#include "yans/simulator.h"
#include "yans/event.tcc"
namespace yans {
Timeout::Timeout (ExpireCallback callback)
: m_interval_us (0),
m_count (0),
m_current_count (0),
m_stop (false),
m_callback (callback)
{}
Timeout::~Timeout ()
{}
void
Timeout::set_interval (uint64_t us)
{
m_interval_us = us;
}
void
Timeout::set_count (uint32_t count)
{
m_count = count;
}
void Timeout::start (void)
{
Simulator::schedule_rel_us (m_interval_us,
make_event (&Timeout::expire, this));
}
void Timeout::stop (void)
{
m_stop = true;
}
void Timeout::restart (void)
{
m_current_count = m_count;
}
void
Timeout::expire (void)
{
if (m_stop) {
return;
}
m_current_count--;
if (m_current_count == 0) {
m_callback ();
return;
}
Simulator::schedule_rel_us (m_interval_us,
make_event (&Timeout::expire, this));
}
}; // namespace yans

52
src/common/timeout.h Normal file
View File

@@ -0,0 +1,52 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef TIMEOUT_H
#define TIMEOUT_H
#include <stdint.h>
#include "yans/callback.h"
namespace yans {
class Timeout {
public:
typedef Callback<void> ExpireCallback;
Timeout (ExpireCallback callback);
~Timeout ();
void set_interval (uint64_t us);
void set_count (uint32_t count);
void start (void);
void stop (void);
void restart (void);
private:
Timeout ();
void expire (void);
uint64_t m_interval_us;
uint32_t m_count;
uint32_t m_current_count;
bool m_stop;
ExpireCallback m_callback;
};
}; // namespace yans
#endif /* TIMEOUT_H */

View File

@@ -0,0 +1,197 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "trace-container.h"
#include "packet-logger.h"
#include "trace-stream.h"
#include <utility>
#include <cassert>
namespace yans {
TraceContainer::TraceContainer ()
{}
TraceContainer::~TraceContainer ()
{
m_ui_list.erase (m_ui_list.begin (), m_ui_list.end ());
m_si_list.erase (m_si_list.begin (), m_si_list.end ());
m_f_list.erase (m_f_list.begin (), m_f_list.end ());
}
void
TraceContainer::set_ui_variable_callback (char const *name, Callback<void,uint64_t, uint64_t> callback)
{
for (UiListI i = m_ui_list.begin (); i != m_ui_list.end (); i++) {
if ((*i).second == name) {
(*i).first->set_callback (callback);
return;
}
}
assert (false);
}
void
TraceContainer::set_si_variable_callback (char const *name, Callback<void,int64_t, int64_t> callback)
{
for (SiListI i = m_si_list.begin (); i != m_si_list.end (); i++) {
if ((*i).second == name) {
(*i).first->set_callback (callback);
return;
}
}
assert (false);
}
void
TraceContainer::set_f_variable_callback (char const *name, Callback<void,double, double> callback)
{
assert (false);
}
void
TraceContainer::set_packet_logger_callback (char const *name, Callback<void,Packet const> callback)
{
for (PacketLoggerListI i = m_packet_logger_list.begin (); i != m_packet_logger_list.end (); i++) {
if ((*i).second == name) {
(*i).first->set_callback (callback);
return;
}
}
assert (false);
}
void
TraceContainer::set_stream (char const *name, std::ostream *os)
{
for (TraceStreamListI i = m_trace_stream_list.begin (); i != m_trace_stream_list.end (); i++) {
if ((*i).second == name) {
(*i).first->set_stream (os);
return;
}
}
assert (false);
}
void
TraceContainer::register_ui_variable (char const *name, UiTracedVariableBase *var)
{
// ensure unicity
for (UiListI i = m_ui_list.begin (); i != m_ui_list.end (); i++) {
if (i->second == name) {
m_ui_list.erase (i);
break;
}
}
m_ui_list.push_back (std::make_pair (var, name));
}
void
TraceContainer::register_si_variable (char const *name, SiTracedVariableBase *var)
{
// ensure unicity
for (SiListI i = m_si_list.begin (); i != m_si_list.end (); i++) {
if (i->second == name) {
m_si_list.erase (i);
break;
}
}
m_si_list.push_back (std::make_pair (var, name));
}
void
TraceContainer::register_f_variable (char const *name, FTracedVariableBase *var)
{
assert (false);
}
void
TraceContainer::register_packet_logger (char const *name, PacketLogger *logger)
{
// ensure unicity
for (PacketLoggerListI i = m_packet_logger_list.begin (); i != m_packet_logger_list.end (); i++) {
if (i->second == name) {
m_packet_logger_list.erase (i);
break;
}
}
m_packet_logger_list.push_back (std::make_pair (logger, name));
}
void
TraceContainer::register_stream (char const *name, TraceStream *stream)
{
// ensure unicity
for (TraceStreamListI i = m_trace_stream_list.begin (); i != m_trace_stream_list.end (); i++) {
if (i->second == name) {
m_trace_stream_list.erase (i);
break;
}
}
m_trace_stream_list.push_back (std::make_pair (stream,name));
}
void
TraceContainer::register_callback (char const *name, CallbackLoggerBase *logger)
{
for (CallbackListI i = m_callback_list.begin (); i != m_callback_list.end (); i++) {
if (i->second == name) {
m_callback_list.erase (i);
break;
}
}
m_callback_list.push_back (std::make_pair (logger, name));
}
}; // namespace yans
#include <iostream>
void
yans::TraceContainer::print_debug (void)
{
if (!m_ui_list.empty ()) {
std::cout << "ui var: " << std::endl;
for (UiListI i = m_ui_list.begin (); i != m_ui_list.end (); i++) {
std::cout << " \"" << (*i).second << "\""<<std::endl;
}
}
if (!m_si_list.empty ()) {
std::cout << "si var: " << std::endl;
for (SiListI i = m_si_list.begin (); i != m_si_list.end (); i++) {
std::cout << " \"" << (*i).second << "\""<<std::endl;
}
}
if (!m_f_list.empty ()) {
std::cout << "f var: " << std::endl;
for (FListI i = m_f_list.begin (); i != m_f_list.end (); i++) {
std::cout << " \"" << (*i).second << "\""<<std::endl;
}
}
if (!m_packet_logger_list.empty ()) {
std::cout << "packet logger: " << std::endl;
for (PacketLoggerListI i = m_packet_logger_list.begin (); i != m_packet_logger_list.end (); i++) {
std::cout << " \"" << (*i).second << "\""<<std::endl;
}
}
if (!m_callback_list.empty ()) {
std::cout << "callback list: "<<std::endl;
for (CallbackListI i = m_callback_list.begin (); i != m_callback_list.end (); i++) {
std::cout << " \"" << i->second << "\""<<std::endl;
}
}
}

View File

@@ -0,0 +1,299 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef TRACE_CONTAINER_H
#define TRACE_CONTAINER_H
#include "ui-traced-variable.tcc"
#include "si-traced-variable.tcc"
#include "f-traced-variable.tcc"
#include "callback-logger.h"
#include "yans/callback.h"
#include "packet.h"
#include <list>
#include <string>
namespace yans {
class PacketLogger;
class TraceStream;
/**
* \brief register every source of trace events
*
* Model authors use the TraceContainer class to register
* their trace event sources. Model users use the TraceContainer
* class to connect their trace event listeners to the
* model trace event sources.
*
* TraceContainer can be used to register the following event sources:
* - yans::PacketLogger : can be connected to yans::PcapWriter
* - yans::TraceStream : can be connected to any std::ostream
* - yans::CallbackLogger: can be connected to yans::Callback
* - yans::UiTracedVariable
* - yans::SiTracedVariable
* - yans::FTracedVariable
*
* The following sample code shows how you can:
* - create trace event sources
* - register the trace event sources in a trace container
* - set event sinks to each event source
*
* \include samples/main-trace.cc
*/
class TraceContainer {
public:
TraceContainer ();
~TraceContainer ();
/**
* \param name the name of the target event source
* \param callback the callback being connected to the target event source
*
* This method targets only event sources which are variables of any unsigned
* integer type.
*/
void set_ui_variable_callback (char const *name,
Callback<void,uint64_t, uint64_t> callback);
/**
* \param name the name of the target event source
* \param callback the callback being connected to the target event source
*
* This method targets only event sources which are variables of any signed
* integer type.
*/
void set_si_variable_callback (char const *name, Callback<void,int64_t, int64_t> callback);
/**
* \param name the name of the target event source
* \param callback the callback being connected to the target event source
*
* This method targets only event sources which are variables of any double type.
*/
void set_f_variable_callback (char const *name, Callback<void,double, double> callback);
/**
* \param name the name of the target event source
* \param callback the callback being connected to the target event source
*
* This method targets only event sources which are of type PacketLogger.
*/
void set_packet_logger_callback (char const *name, Callback<void,Packet const> callback);
/**
* \param name the name of the target event source
* \param os the output stream being connected to the source trace stream
*
* This method targets only event sources which are of type TraceStream.
*/
void set_stream (char const *name, std::ostream *os);
/**
* \param name the name of the target event source
* \param callback the callback being connected to the target event source.
*
* This method targets only event sources which are of type CallbackLogger<T1>
*/
template <typename T1>
void set_callback (char const *name, Callback<void,T1> callback);
/**
* \param name the name of the target event source
* \param callback the callback being connected to the target event source.
*
* This method targets only event sources which are of type CallbackLogger<T1,T2>
*/
template <typename T1, typename T2>
void set_callback (char const *name, Callback<void,T1,T2> callback);
/**
* \param name the name of the target event source
* \param callback the callback being connected to the target event source.
*
* This method targets only event sources which are of type CallbackLogger<T1,T2,T3>
*/
template <typename T1, typename T2, typename T3>
void set_callback (char const *name, Callback<void,T1,T2,T3> callback);
/**
* \param name the name of the target event source
* \param callback the callback being connected to the target event source.
*
* This method targets only event sources which are of type CallbackLogger<T1,T2,T3,T4>
*/
template <typename T1, typename T2, typename T3, typename T4>
void set_callback (char const *name, Callback<void,T1,T2,T3,T4> callback);
/**
* \param name the name of the target event source
* \param callback the callback being connected to the target event source.
*
* This method targets only event sources which are of type CallbackLogger<T1,T2,T3,T4,T5>
*/
template <typename T1, typename T2, typename T3, typename T4, typename T5>
void set_callback (char const *name, Callback<void,T1,T2,T3,T4,T5> callback);
/**
* \param name the name of the registered event source
* \param var the event source being registered
*
* This method registers only event sources of type "unsigned integer".
*/
void register_ui_variable (char const *name, UiTracedVariableBase *var);
/**
* \param name the name of the registered event source
* \param var the event source being registered
*
* This method registers only event sources of type "signed integer".
*/
void register_si_variable (char const *name, SiTracedVariableBase *var);
/**
* \param name the name of the registered event source
* \param var the event source being registered
*
* This method registers only event sources of type "double".
*/
void register_f_variable (char const *name, FTracedVariableBase *var);
/**
* \param name the name of the registered event source
* \param logger the event source being registered
*
* This method registers only event sources of type PacketLogger.
*/
void register_packet_logger (char const *name, PacketLogger *logger);
/**
* \param name the name of the registered event source
* \param stream the event source being registered
*
* This method registers only event sources of type TraceStream.
*/
void register_stream (char const *name, TraceStream *stream);
/**
* \param name the name of the registeref event source
* \param logger the callback logger being registered.
*
* This method registers only event sources of type CallbackLogger
*/
void register_callback (char const *name, CallbackLoggerBase*logger);
/**
* Print the list of registered event sources in this container only.
*/
void print_debug (void);
private:
typedef std::list<std::pair<UiTracedVariableBase *, std::string> > UiList;
typedef std::list<std::pair<UiTracedVariableBase *, std::string> >::iterator UiListI;
typedef std::list<std::pair<SiTracedVariableBase *, std::string> > SiList;
typedef std::list<std::pair<SiTracedVariableBase *, std::string> >::iterator SiListI;
typedef std::list<std::pair<FTracedVariableBase *, std::string> > FList;
typedef std::list<std::pair<FTracedVariableBase *, std::string> >::iterator FListI;
typedef std::list<std::pair<PacketLogger *, std::string> > PacketLoggerList;
typedef std::list<std::pair<PacketLogger *, std::string> >::iterator PacketLoggerListI;
typedef std::list<std::pair<TraceStream *, std::string> > TraceStreamList;
typedef std::list<std::pair<TraceStream *, std::string> >::iterator TraceStreamListI;
typedef std::list<std::pair<CallbackLoggerBase *, std::string> > CallbackList;
typedef std::list<std::pair<CallbackLoggerBase *, std::string> >::iterator CallbackListI;
UiList m_ui_list;
SiList m_si_list;
FList m_f_list;
PacketLoggerList m_packet_logger_list;
TraceStreamList m_trace_stream_list;
CallbackList m_callback_list;
};
}; // namespace yans
#ifndef NDEBUG
#include <cassert>
#endif
namespace yans {
template <typename T1>
void
TraceContainer::set_callback (char const *name, Callback<void,T1> callback)
{
for (CallbackListI i = m_callback_list.begin (); i != m_callback_list.end (); i++) {
if (i->second == name) {
static_cast<CallbackLogger<T1> *> (i->first)->set_callback (callback);
return;
}
}
#ifndef NDEBUG
assert (false);
#endif
}
template <typename T1, typename T2>
void
TraceContainer::set_callback (char const *name, Callback<void,T1,T2> callback)
{
for (CallbackListI i = m_callback_list.begin (); i != m_callback_list.end (); i++) {
if (i->second == name) {
static_cast<CallbackLogger<T1,T2> *> (i->first)->set_callback (callback);
return;
}
}
#ifndef NDEBUG
assert (false);
#endif
}
template <typename T1, typename T2, typename T3>
void
TraceContainer::set_callback (char const *name, Callback<void,T1,T2,T3> callback)
{
for (CallbackListI i = m_callback_list.begin (); i != m_callback_list.end (); i++) {
if (i->second == name) {
static_cast<CallbackLogger<T1,T2,T3> *> (i->first)->set_callback (callback);
return;
}
}
#ifndef NDEBUG
assert (false);
#endif
}
template <typename T1, typename T2, typename T3, typename T4>
void
TraceContainer::set_callback (char const *name, Callback<void,T1,T2,T3,T4> callback)
{
for (CallbackListI i = m_callback_list.begin (); i != m_callback_list.end (); i++) {
if (i->second == name) {
static_cast<CallbackLogger<T1,T2,T3,T4> *> (i->first)->set_callback (callback);
return;
}
}
#ifndef NDEBUG
assert (false);
#endif
}
template <typename T1, typename T2, typename T3, typename T4, typename T5>
void
TraceContainer::set_callback (char const *name, Callback<void,T1,T2,T3,T4,T5> callback)
{
for (CallbackListI i = m_callback_list.begin (); i != m_callback_list.end (); i++) {
if (i->second == name) {
static_cast<CallbackLogger<T1,T2,T3,T4,T5> *> (i->first)->set_callback (callback);
return;
}
}
#ifndef NDEBUG
assert (false);
#endif
}
}; // namespace yans
#endif /* TRACED_VARIABLE_CONTAINER_H */

View File

@@ -0,0 +1,68 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "trace-stream.h"
#include "yans/test.h"
#include <iostream>
#ifdef RUN_SELF_TESTS
namespace {
class TestTraceStream : public yans::Test {
public:
TestTraceStream ();
virtual bool run_tests (void);
};
static TestTraceStream g_test_stream;
TestTraceStream::TestTraceStream ()
: Test ("TraceStream")
{}
bool
TestTraceStream::run_tests (void)
{
bool ok = true;
yans::TraceStream trace;
//trace.set_stream (&std::cout);
trace << 1;
trace << " X ";
trace << 1.0;
trace << std::endl;
trace << "test ";
trace << 1 << " test";
trace << "test "
<< 1.0 << " "
<< 0xdeadbead
<< std::endl;
trace << "0x" << std::hex
<< 0xdeadbeaf
<< std::dec << " "
<< 0xdeadbeaf
<< std::endl;
return ok;
}
}; // namespace yans
#endif /* RUN_SELF_TESTS */

73
src/common/trace-stream.h Normal file
View File

@@ -0,0 +1,73 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef TRACE_STREAM_H
#define TRACE_STREAM_H
#include <ostream>
namespace yans {
/**
* \brief log arbitrary data to std::ostreams
*
* Whenever operator << is invoked on this class,
* it is forwarded to the stored std::ostream output
* stream (if there is one).
*/
class TraceStream {
public:
TraceStream ()
: m_os (0) {}
template <typename T>
TraceStream &operator << (T const&v) {
if (m_os != 0) {
(*m_os) << v;
}
return *this;
}
template <typename T>
TraceStream &operator << (T &v) {
if (m_os != 0) {
(*m_os) << v;
}
return *this;
}
TraceStream &operator << (std::ostream &(*v) (std::ostream &)) {
if (m_os != 0) {
(*m_os) << v;
}
return *this;
}
/**
* \param os the output stream to store
*/
void set_stream (std::ostream * os) {
m_os = os;
}
private:
std::ostream *m_os;
};
}; // namespace yans
#endif /* TRACE_STREAM_H */

View File

@@ -0,0 +1,252 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "ui-traced-variable.tcc"
#include "si-traced-variable.tcc"
#include "yans/test.h"
#include "yans/callback.h"
namespace yans {
class Foo {
public:
void notify (uint64_t old_val, uint64_t new_val) {}
};
class TracedVariableTest: public Test {
public:
TracedVariableTest ();
void run_unsigned_tests (void);
void run_signed_unsigned_tests (void);
virtual bool run_tests (void);
};
void
TracedVariableTest::run_unsigned_tests (void)
{
UiTracedVariable<uint32_t> var, ovar, tmp;
uint32_t utmp;
Foo *foo = new Foo ();
var.set_callback (make_callback (&Foo::notify, foo));
var = 10;
ovar = var;
if (var == ovar) {
}
if (var != ovar) {
}
if (var > ovar) {
}
if (var >= ovar) {
}
if (var < ovar) {
}
if (var <= ovar) {
}
if (var == 1) {
}
if (var != 1) {
}
if (var > 1) {
}
if (var >= 1) {
}
if (var < 1) {
}
if (var <= 1) {
}
if (1 == ovar) {
}
if (1 != ovar) {
}
if (1 > ovar) {
}
if (1 >= ovar) {
}
if (1 < ovar) {
}
if (1 <= ovar) {
}
var++;
++var;
var--;
--var;
tmp = var + ovar;
tmp = var - ovar;
tmp = var / ovar;
tmp = var * ovar;
tmp = var << ovar;
tmp = var >> ovar;
tmp = var & ovar;
tmp = var | ovar;
tmp = var ^ ovar;
tmp = var + 1;
tmp = var - 1;
tmp = var / 1;
tmp = var * 1;
tmp = var << 1;
tmp = var >> 1;
tmp = var & 1;
tmp = var | 1;
tmp = var ^ 1;
tmp = 1 + ovar;
tmp = 1 - ovar;
tmp = 1 / ovar;
tmp = 1 * ovar;
tmp = 1 << ovar;
tmp = 1 >> ovar;
tmp = 1 & ovar;
tmp = 1 | ovar;
tmp = 1 ^ ovar;
tmp += var;
tmp -= var;
tmp /= var;
tmp *= var;
tmp <<= var;
tmp >>= var;
tmp &= var;
tmp |= var;
tmp ^= var;
tmp += 1;
tmp -= 1;
tmp /= 1;
tmp *= 1;
tmp <<= 1;
tmp >>= 1;
tmp &= 1;
tmp |= 1;
tmp ^= 1;
utmp = var + ovar;
utmp = var - ovar;
utmp = var / ovar;
utmp = var * ovar;
utmp = var << ovar;
utmp = var >> ovar;
utmp = var & ovar;
utmp = var | ovar;
utmp = var ^ ovar;
utmp = var + 1;
utmp = var - 1;
utmp = var / 1;
utmp = var * 1;
utmp = var << 1;
utmp = var >> 1;
utmp = var & 1;
utmp = var | 1;
utmp = var ^ 1;
utmp = 1 + ovar;
utmp = 1 - ovar;
utmp = 1 / ovar;
utmp = 1 * ovar;
utmp = 1 << ovar;
utmp = 1 >> ovar;
utmp = 1 & ovar;
utmp = 1 | ovar;
utmp = 1 ^ ovar;
utmp += var;
utmp -= var;
utmp /= var;
utmp *= var;
utmp <<= var;
utmp >>= var;
utmp &= var;
utmp |= var;
utmp ^= var;
utmp += 1;
utmp -= 1;
utmp /= 1;
utmp *= 1;
utmp <<= 1;
utmp >>= 1;
utmp &= 1;
utmp |= 1;
utmp ^= 1;
}
void
TracedVariableTest::run_signed_unsigned_tests (void)
{
unsigned short utmp = 10;
unsigned int uitmp = 7;
short stmp = 5;
utmp = stmp;
utmp += stmp;
uitmp = utmp;
utmp = uitmp;
UiTracedVariable<unsigned short> uvar = 10;
UiTracedVariable<unsigned int> uivar = 5;
SiTracedVariable<short> svar = 5;
SiTracedVariable<int> sivar = 5;
uvar = svar;
svar = uvar;
uvar += svar;
svar += uvar;
uvar = sivar;
sivar = uvar;
uvar += sivar;
sivar += uvar;
uivar = uvar;
uvar = uivar;
uivar += uvar;
uvar += uivar;
sivar = svar;
svar = sivar;
sivar += svar;
svar += sivar;
}
bool
TracedVariableTest::run_tests (void)
{
run_unsigned_tests ();
run_signed_unsigned_tests ();
return true;
}
TracedVariableTest::TracedVariableTest ()
: Test ("TracedVariable") {}
static TracedVariableTest g_traced_variable_test;
}; // namespace yans

View File

@@ -0,0 +1,239 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef UI_TRACED_VARIABLE_TCC
#define UI_TRACED_VARIABLE_TCC
#include "yans/callback.h"
#include <stdint.h>
namespace yans {
class UiTracedVariableBase {
public:
typedef Callback<void, uint64_t, uint64_t> ChangeNotifyCallback;
UiTracedVariableBase ()
: m_callback () {}
/* We don't want to copy the base callback. Only set_callback on
* a specific instance will do something to it. */
UiTracedVariableBase (UiTracedVariableBase const &o)
: m_callback () {}
UiTracedVariableBase &operator = (UiTracedVariableBase const &o) {
return *this;
}
~UiTracedVariableBase () {}
void set_callback(ChangeNotifyCallback callback) {
m_callback = callback;
}
protected:
void notify (uint64_t old_val, uint64_t new_val) {
if (old_val != new_val && !m_callback.is_null ()) {
m_callback (old_val, new_val);
}
}
private:
ChangeNotifyCallback m_callback;
};
template <typename T>
class SiTracedVariable;
/**
* \brief trace variables of type "unsigned integer"
*
* This template class implements a POD type: it
* behaves like any other variable of type "unsigned integer"
* except that it also reports any changes to its
* value with its internal callback.
*
* To instantiate a 32-bit unsigned variable (to store
* a TCP counter for example), you would create a variable of type
* yans::UiTracedVariable<uint32_t> :
\code
#include <stdint.h>
#include "yans/ui-traced-variable.tcc"
yans::UiTracedVariable<uint32_t> var;
\endcode
* and you would use it like any other variable of type uint32_t:
\code
var += 12;
var = 10;
\endcode
*/
template <typename T>
class UiTracedVariable : public UiTracedVariableBase {
public:
UiTracedVariable ()
: m_var ()
{}
UiTracedVariable (T const &var)
: m_var (var)
{}
UiTracedVariable &operator = (UiTracedVariable const &o) {
assign (o.get ());
return *this;
}
template <typename TT>
UiTracedVariable &operator = (UiTracedVariable<TT> const &o) {
assign (o.get ());
return *this;
}
template <typename TT>
UiTracedVariable &operator = (SiTracedVariable<TT> const &o) {
assign (o.get ());
return *this;
}
UiTracedVariable &operator++ () {
assign (get () + 1);
return *this;
}
UiTracedVariable &operator-- () {
assign (get () - 1);
return *this;
}
UiTracedVariable operator++ (int) {
UiTracedVariable old (*this);
++*this;
return old;
}
UiTracedVariable operator-- (int) {
UiTracedVariable old (*this);
--*this;
return old;
}
operator T () const {
return get ();
}
void assign (T var) {
notify (m_var, var);
m_var = var;
}
T get (void) const {
return m_var;
}
private:
T m_var;
};
template <typename T>
UiTracedVariable<T> &operator += (UiTracedVariable<T> &lhs, UiTracedVariable<T> const &rhs) {
lhs.assign (lhs.get () + rhs.get ());
return lhs;
}
template <typename T>
UiTracedVariable<T> &operator -= (UiTracedVariable<T> &lhs, UiTracedVariable<T> const &rhs) {
lhs.assign (lhs.get () - rhs.get ());
return lhs;
}
template <typename T>
UiTracedVariable<T> &operator *= (UiTracedVariable<T> &lhs, UiTracedVariable<T> const &rhs) {
lhs.assign (lhs.get () * rhs.get ());
return lhs;
}
template <typename T>
UiTracedVariable<T> &operator /= (UiTracedVariable<T> &lhs, UiTracedVariable<T> const &rhs) {
lhs.assign (lhs.get () / rhs.get ());
return lhs;
}
template <typename T>
UiTracedVariable<T> &operator <<= (UiTracedVariable<T> &lhs, UiTracedVariable<T> const &rhs) {
lhs.assign (lhs.get () << rhs.get ());
return lhs;
}
template <typename T>
UiTracedVariable<T> &operator >>= (UiTracedVariable<T> &lhs, UiTracedVariable<T> const &rhs) {
lhs.assign (lhs.get () >> rhs.get ());
return lhs;
}
template <typename T>
UiTracedVariable<T> &operator &= (UiTracedVariable<T> &lhs, UiTracedVariable<T> const &rhs) {
lhs.assign (lhs.get () & rhs.get ());
return lhs;
}
template <typename T>
UiTracedVariable<T> &operator |= (UiTracedVariable<T> &lhs, UiTracedVariable<T> const &rhs) {
lhs.assign (lhs.get () | rhs.get ());
return lhs;
}
template <typename T>
UiTracedVariable<T> &operator ^= (UiTracedVariable<T> &lhs, UiTracedVariable<T> const &rhs) {
lhs.assign (lhs.get () ^ rhs.get ());
return lhs;
}
template <typename T, typename U>
UiTracedVariable<T> &operator += (UiTracedVariable<T> &lhs, U const &rhs) {
lhs.assign (lhs.get () + rhs);
return lhs;
}
template <typename T, typename U>
UiTracedVariable<T> &operator -= (UiTracedVariable<T> &lhs, U const &rhs) {
lhs.assign (lhs.get () - rhs);
return lhs;
}
template <typename T, typename U>
UiTracedVariable<T> &operator *= (UiTracedVariable<T> &lhs, U const &rhs) {
lhs.assign (lhs.get () * rhs);
return lhs;
}
template <typename T, typename U>
UiTracedVariable<T> &operator /= (UiTracedVariable<T> &lhs, U const &rhs) {
lhs.assign (lhs.get () / rhs);
return lhs;
}
template <typename T, typename U>
UiTracedVariable<T> &operator <<= (UiTracedVariable<T> &lhs, U const &rhs) {
lhs.assign (lhs.get () << rhs);
return lhs;
}
template <typename T, typename U>
UiTracedVariable<T> &operator >>= (UiTracedVariable<T> &lhs, U const &rhs) {
lhs.assign (lhs.get () >> rhs);
return lhs;
}
template <typename T, typename U>
UiTracedVariable<T> &operator &= (UiTracedVariable<T> &lhs, U const &rhs) {
lhs.assign (lhs.get () & rhs);
return lhs;
}
template <typename T, typename U>
UiTracedVariable<T> &operator |= (UiTracedVariable<T> &lhs, U const &rhs) {
lhs.assign (lhs.get () | rhs);
return lhs;
}
template <typename T, typename U>
UiTracedVariable<T> &operator ^= (UiTracedVariable<T> &lhs, U const &rhs) {
lhs.assign (lhs.get () ^ rhs);
return lhs;
}
}; // namespace yans
#endif /* UI_TRACED_VARIABLE_TCC */

293
src/common/utils.cc Normal file
View File

@@ -0,0 +1,293 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "utils.h"
namespace yans {
uint16_t
utils_hton_16 (uint16_t v)
{
uint8_t array[2];
array[0] = (v >> 8) & 0xff;
array[1] = (v >> 0) & 0xff;
return *((uint16_t *)array);
}
uint32_t
utils_hton_32 (uint32_t v)
{
uint8_t array[4];
array[0] = (v >> 24) & 0xff;
array[1] = (v >> 16) & 0xff;
array[2] = (v >> 8) & 0xff;
array[3] = (v >> 0) & 0xff;
return *((uint32_t *)array);
}
uint16_t
utils_ntoh_16 (uint16_t v)
{
uint16_t val;
uint8_t *array;
array = (uint8_t *)&v;
val = (array[0] << 8) | (array[1] << 0);
return val;
}
uint32_t
utils_ntoh_32 (uint32_t v)
{
uint32_t val = 0;
uint8_t *array = (uint8_t *)&v;
val |= array[0] << 24;
val |= array[1] << 16;
val |= array[2] << 8;
val |= array[3] << 0;
return val;
}
#define ASCII_DOT (0x2e)
#define ASCII_ZERO (0x30)
#define ASCII_A (0x41)
#define ASCII_Z (0x5a)
#define ASCII_a (0x61)
#define ASCII_z (0x7a)
#define ASCII_COLON (0x3a)
uint32_t
ascii_to_ipv4_host (char const *address)
{
uint32_t host = 0;
while (true) {
uint8_t byte = 0;
while (*address != ASCII_DOT &&
*address != 0) {
byte *= 10;
byte += *address - ASCII_ZERO;
address++;
}
host <<= 8;
host |= byte;
if (*address == 0) {
break;
}
address++;
}
return host;
}
char
ascii_to_low_case (char c)
{
if (c >= ASCII_a && c <= ASCII_z) {
return c;
} else if (c >= ASCII_A && c <= ASCII_Z) {
return c + (ASCII_a - ASCII_A);
} else {
return c;
}
}
void
ascii_to_mac_network (char const *str, uint8_t address[6])
{
uint8_t i = 0;
while (*str != 0 && i < 6) {
uint8_t byte = 0;
while (*str != ASCII_COLON && *str != 0) {
byte <<= 4;
char low = ascii_to_low_case (*str);
if (low >= ASCII_a) {
byte |= low - ASCII_a + 10;
} else {
byte |= low - ASCII_ZERO;
}
str++;
}
address[i] = byte;
str++;
i++;
}
}
uint16_t
utils_checksum_calculate (uint16_t checksum, uint8_t *buffer, uint16_t size)
{
/* see RFC 1071 to understand this code. */
uint32_t sum = checksum;
uint16_t *data = (uint16_t *) buffer;
for (uint16_t i = 0; i < (size/2); i++) {
sum += data[i];
}
if ((size % 2) != 0) {
uint8_t tmp_buf[2];
tmp_buf[0] = buffer[size-1];
tmp_buf[1] = 0;
data = (uint16_t *)tmp_buf;
sum += *data;
}
while (sum >> 16) {
sum = (sum & 0xffff) + (sum >> 16);
}
return sum;
}
uint16_t
utils_checksum_complete (uint16_t checksum)
{
return ~checksum;
}
}; // namespace yans
#ifdef RUN_SELF_TESTS
#include "yans/test.h"
namespace yans {
class UtilsTest : public Test {
public:
UtilsTest ();
virtual bool run_tests (void);
private:
bool test_ipv4_ascii_to_host (char const *str, uint32_t expected);
bool test_mac_ascii (char const *str, uint8_t expected[6]);
bool test_hton_16 (uint16_t v, uint8_t expected[2]);
};
bool
UtilsTest::test_ipv4_ascii_to_host (char const *str, uint32_t expected)
{
if (ascii_to_ipv4_host (str) != expected) {
failure () << "Utils ascii to host --"
<< " for: \"" << str << "\""
<< " expected: " << expected
<< " got: " << ascii_to_ipv4_host (str)
<< std::endl;
return false;
}
return true;
}
bool
UtilsTest::test_mac_ascii (char const *str, uint8_t expected[6])
{
uint8_t got[6];
ascii_to_mac_network (str, got);
for (uint8_t i = 0; i < 6; i++) {
if (got[i] != expected[i]) {
failure () << "Utils ascii to mac --"
<< " for: \"" << str << "\""
<< " expected: ";
failure ().setf (std::ios::hex, std::ios::basefield);
failure () << (uint32_t)expected[0] << ":"
<< (uint32_t)expected[1] << ":"
<< (uint32_t)expected[2] << ":"
<< (uint32_t)expected[3] << ":"
<< (uint32_t)expected[4] << ":"
<< (uint32_t)expected[5];
failure ().setf (std::ios::dec, std::ios::basefield);
failure () << " got: ";
failure ().setf (std::ios::hex, std::ios::basefield);
failure () << (uint32_t)got[0] << ":"
<< (uint32_t)got[1] << ":"
<< (uint32_t)got[2] << ":"
<< (uint32_t)got[3] << ":"
<< (uint32_t)got[4] << ":"
<< (uint32_t)got[5];
failure ().setf (std::ios::dec, std::ios::basefield);
failure () << std::endl;
return false;
}
}
return true;
}
bool
UtilsTest::test_hton_16 (uint16_t v, uint8_t expected[2])
{
uint16_t result = utils_hton_16 (v);
uint8_t *got = (uint8_t *)&result;
if (got[0] != expected[0] ||
got[1] != expected[1]) {
failure () << "Utils hton 16 --"
<< " for: \"" << v << "\""
<< " expected: ";
failure ().setf (std::ios::hex, std::ios::basefield);
failure () << (uint32_t)expected[0] << ":"
<< (uint32_t)expected[1];
failure () << " got: ";
failure () << (uint32_t)got[0] << ":"
<< (uint32_t)got[1];
failure ().setf (std::ios::dec, std::ios::basefield);
failure () << std::endl;
return false;
}
return true;
}
#define TEST_IPV4_ASCII_TO_HOST(a,b) \
if (!test_ipv4_ascii_to_host (a,b)) { \
ok = false; \
}
#define TEST_MAC_ASCII(ad, a, b, c, d, e, f) \
{ \
uint8_t expected[6] = {a, b, c, d, e, f}; \
if (!test_mac_ascii (ad, expected)) { \
ok = false; \
} \
}
#define TEST_HTON_16(v, a, b) \
{ \
uint8_t expected[2] = {a, b}; \
if (!test_hton_16 (v, expected)) { \
ok = false; \
} \
}
UtilsTest::UtilsTest ()
: Test ("Utils") {}
bool
UtilsTest::run_tests (void)
{
bool ok = true;
TEST_IPV4_ASCII_TO_HOST ("255.255.255.255", 0xffffffff);
TEST_IPV4_ASCII_TO_HOST ("255.255.255.0", 0xffffff00);
TEST_IPV4_ASCII_TO_HOST ("255.255.255.00", 0xffffff00);
TEST_IPV4_ASCII_TO_HOST ("255.255.255.000", 0xffffff00);
TEST_IPV4_ASCII_TO_HOST ("255.255.255.0000", 0xffffff00);
TEST_IPV4_ASCII_TO_HOST ("255.255.0.255", 0xffff00ff);
TEST_IPV4_ASCII_TO_HOST ("192.168.0.1", 0xc0a80001);
TEST_IPV4_ASCII_TO_HOST ("0.168.0.1", 0x00a80001);
TEST_MAC_ASCII ("00:00:00:00:00:00", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
TEST_MAC_ASCII ("00:00:00:00:00:01", 0x00, 0x00, 0x00, 0x00, 0x00, 0x01);
TEST_MAC_ASCII ("01:00:00:00:00:01", 0x01, 0x00, 0x00, 0x00, 0x00, 0x01);
TEST_MAC_ASCII ("ff:00:00:ff:00:01", 0xff, 0x00, 0x00, 0xff, 0x00, 0x01);
TEST_MAC_ASCII ("f0:00:00:00:5d:01", 0xf0, 0x00, 0x00, 0x00, 0x5d, 0x01);
TEST_HTON_16 (0xf00f, 0xf0, 0x0f);
return ok;
}
static UtilsTest g_utils_test;
}; //namespace yans
#endif /* RUN_SELF_TESTS */

43
src/common/utils.h Normal file
View File

@@ -0,0 +1,43 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef UTILS_H
#define UTILS_H
#include <stdint.h>
namespace yans {
uint16_t utils_hton_16 (uint16_t v);
uint32_t utils_hton_32 (uint32_t v);
uint16_t utils_ntoh_16 (uint16_t v);
uint32_t utils_ntoh_32 (uint32_t v);
uint32_t ascii_to_ipv4_host (char const *address);
void ascii_to_mac_network (char const *str, uint8_t address[6]);
/* call with checksum = 0 the first time. */
uint16_t utils_checksum_calculate (uint16_t checksum, uint8_t *buffer, uint16_t size);
uint16_t utils_checksum_complete (uint16_t checksum);
}; // namespace yans
#endif /* UTILS_H */

197
src/core/callback-test.cc Normal file
View File

@@ -0,0 +1,197 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005,2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "test.h"
#include "callback.h"
#include <stdint.h>
#ifdef RUN_SELF_TESTS
namespace yans {
static bool g_test5 = false;
static bool g_test6 = false;
static bool g_test7 = false;
void test5 (void)
{
g_test5 = true;
}
void test6 (int)
{
g_test6 = true;
}
int test7 (int a)
{
g_test7 = true;
return a;
}
class CallbackTest : public yans::Test {
private:
bool m_test1;
bool m_test2;
bool m_test3;
bool m_test4;
public:
CallbackTest ();
virtual bool run_tests (void);
void reset (void);
bool is_wrong (void);
void test1 (void);
int test2 (void);
void test3 (double a);
int test4 (double a, int b);
void test8 (Callback<void, int> callback);
};
CallbackTest::CallbackTest ()
: yans::Test ("Callback"),
m_test1 (false),
m_test2 (false),
m_test3 (false),
m_test4 (false)
{}
void
CallbackTest::test1 (void)
{
m_test1 = true;
}
int
CallbackTest::test2 (void)
{
m_test2 = true;
return 2;
}
void
CallbackTest::test3 (double a)
{
m_test3 = true;
}
int
CallbackTest::test4 (double a, int b)
{
m_test4 = true;
return 4;
}
void
CallbackTest::test8 (Callback<void,int> callback)
{
callback (3);
}
bool
CallbackTest::is_wrong (void)
{
if (!m_test1 ||
!m_test2 ||
!m_test3 ||
!m_test4 ||
!g_test5 ||
!g_test6 ||
!g_test7) {
return true;
}
return false;
}
void
CallbackTest::reset (void)
{
m_test1 = false;
m_test2 = false;
m_test3 = false;
m_test4 = false;
g_test5 = false;
g_test6 = false;
g_test7 = false;
}
bool
CallbackTest::run_tests (void)
{
bool ok = true;
typedef yans::Callback<void> A;
typedef yans::Callback<int> B;
typedef yans::Callback<void, double> C;
typedef yans::Callback<int, double, int> D;
typedef yans::Callback<void> E;
typedef yans::Callback<void,int> F;
typedef yans::Callback<int,int> G;
A a0 (this, &CallbackTest::test1);
B b0;
b0 = B (this, &CallbackTest::test2);
C c0 = C (this, &CallbackTest::test3);
D d0 = D (this, &CallbackTest::test4);
E e0 = E (&test5);
F f0 = F (&test6);
G g0 = G (&test7);
a0 ();
b0 ();
c0 (0.0);
d0 (0.0, 1);
e0 ();
f0 (1);
g0 (1);
if (is_wrong ()) {
ok = false;
}
reset ();
A a1 = yans::make_callback (&CallbackTest::test1, this);
B b1 = yans::make_callback (&CallbackTest::test2, this);
C c1 = yans::make_callback (&CallbackTest::test3, this);
D d1 = yans::make_callback (&CallbackTest::test4, this);
E e1 = yans::make_callback (&test5);
F f1 = yans::make_callback (&test6);
G g1 = yans::make_callback (&test7);
a1 ();
b1 ();
c1 (0.0);
d1 (0.0, 1);
e1 ();
f1 (1);
g1 (2);
test8 (f1);
Callback<void, int64_t,int64_t> a2;
if (is_wrong ()) {
ok = false;
}
return ok;
}
static CallbackTest g_callback_test;
}; // namespace
#endif /* RUN_SELF_TESTS */

518
src/core/callback.h Normal file
View File

@@ -0,0 +1,518 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005,2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef CALLBACK_H
#define CALLBACK_H
#include "reference-list.h"
namespace yans {
/***
* \internal
* This code was originally written based on the techniques
* described in http://www.codeproject.com/cpp/TTLFunction.asp
* It was subsequently rewritten to follow the architecture
* outlined in "Modern C++ Design" by Andrei Alexandrescu in
* chapter 5, "Generalized Functors".
*
* This code uses:
* - default template parameters to saves users from having to
* specify empty parameters when the number of parameters
* is smaller than the maximum supported number
* - the pimpl idiom: the Callback class is passed around by
* value and delegates the crux of the work to its pimpl
* pointer.
* - two pimpl implementations which derive from CallbackImpl
* FunctorCallbackImpl can be used with any functor-type
* while MemPtrCallbackImpl can be used with pointers to
* member functions.
* - a reference list implementation to implement the Callback's
* value semantics.
*
* This code most notably departs from the alexandrescu
* implementation in that it does not use type lists to specify
* and pass around the types of the callback arguments.
* Of course, it also does not use copy-destruction semantics
* and relies on a reference list rather than auto_ptr to hold
* the pointer.
*/
class empty {};
// declare the CallbackImpl class
template <typename R, typename T1, typename T2, typename T3, typename T4, typename T5>
class CallbackImpl;
// define CallbackImpl for 0 params
template <typename R>
class CallbackImpl<R,empty,empty,empty,empty,empty> {
public:
virtual ~CallbackImpl () {}
virtual R operator() (void) = 0;
};
// define CallbackImpl for 1 params
template <typename R, typename T1>
class CallbackImpl<R,T1,empty,empty,empty,empty> {
public:
virtual ~CallbackImpl () {}
virtual R operator() (T1) = 0;
};
// define CallbackImpl for 2 params
template <typename R, typename T1, typename T2>
class CallbackImpl<R,T1,T2,empty,empty,empty> {
public:
virtual ~CallbackImpl () {}
virtual R operator() (T1, T2) = 0;
};
// define CallbackImpl for 3 params
template <typename R, typename T1, typename T2, typename T3>
class CallbackImpl<R,T1,T2,T3,empty,empty> {
public:
virtual ~CallbackImpl () {}
virtual R operator() (T1, T2, T3) = 0;
};
// define CallbackImpl for 4 params
template <typename R, typename T1, typename T2, typename T3, typename T4>
class CallbackImpl<R,T1,T2,T3,T4,empty> {
public:
virtual ~CallbackImpl () {}
virtual R operator() (T1, T2, T3, T4) = 0;
};
// define CallbackImpl for 5 params
template <typename R, typename T1, typename T2, typename T3, typename T4, typename T5>
class CallbackImpl {
public:
virtual ~CallbackImpl () {}
virtual R operator() (T1, T2, T3, T4, T5) = 0;
};
// an impl for Functors:
template <typename T, typename R, typename T1, typename T2, typename T3, typename T4,typename T5>
class FunctorCallbackImpl : public CallbackImpl<R,T1,T2,T3,T4,T5> {
public:
FunctorCallbackImpl (T const &functor)
: m_functor (functor) {}
virtual ~FunctorCallbackImpl () {}
R operator() (void) {
return m_functor ();
}
R operator() (T1 a1) {
return m_functor (a1);
}
R operator() (T1 a1,T2 a2) {
return m_functor (a1,a2);
}
R operator() (T1 a1,T2 a2,T3 a3) {
return m_functor (a1,a2,a3);
}
R operator() (T1 a1,T2 a2,T3 a3,T4 a4) {
return m_functor (a1,a2,a3,a4);
}
R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5) {
return m_functor (a1,a2,a3,a4,a5);
}
private:
T m_functor;
};
// an impl for Bound Functors:
template <typename T, typename R, typename TX, typename T1, typename T2, typename T3, typename T4,typename T5>
class BoundFunctorCallbackImpl : public CallbackImpl<R,T1,T2,T3,T4,T5> {
public:
BoundFunctorCallbackImpl (T const &functor, TX a)
: m_functor (functor), m_a (a) {}
virtual ~BoundFunctorCallbackImpl () {}
R operator() (void) {
return m_functor (m_a);
}
R operator() (T1 a1) {
return m_functor (m_a,a1);
}
R operator() (T1 a1,T2 a2) {
return m_functor (m_a,a1,a2);
}
R operator() (T1 a1,T2 a2,T3 a3) {
return m_functor (m_a,a1,a2,a3);
}
R operator() (T1 a1,T2 a2,T3 a3,T4 a4) {
return m_functor (m_a,a1,a2,a3,a4);
}
R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5) {
return m_functor (m_a,a1,a2,a3,a4,a5);
}
private:
T m_functor;
TX m_a;
};
// an impl for pointer to member functions
template <typename OBJ_PTR, typename MEM_PTR, typename R, typename T1, typename T2, typename T3, typename T4, typename T5>
class MemPtrCallbackImpl : public CallbackImpl<R,T1,T2,T3,T4,T5> {
public:
MemPtrCallbackImpl (OBJ_PTR const&obj_ptr, MEM_PTR mem_ptr)
: m_obj_ptr (obj_ptr), m_mem_ptr (mem_ptr) {}
virtual ~MemPtrCallbackImpl () {}
R operator() (void) {
return ((*m_obj_ptr).*m_mem_ptr) ();
}
R operator() (T1 a1) {
return ((*m_obj_ptr).*m_mem_ptr) (a1);
}
R operator() (T1 a1,T2 a2) {
return ((*m_obj_ptr).*m_mem_ptr) (a1,a2);
}
R operator() (T1 a1,T2 a2,T3 a3) {
return ((*m_obj_ptr).*m_mem_ptr) (a1,a2,a3);
}
R operator() (T1 a1,T2 a2,T3 a3,T4 a4) {
return ((*m_obj_ptr).*m_mem_ptr) (a1,a2,a3,a4);
}
R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5) {
return ((*m_obj_ptr).*m_mem_ptr) (a1,a2,a3,a4,a5);
}
private:
OBJ_PTR const m_obj_ptr;
MEM_PTR m_mem_ptr;
};
/**
* \brief Callback template class
*
* This class template implements the Functor Design Pattern.
* It is used to declare the type of a Callback:
* - the first non-optional template argument represents
* the return type of the callback.
* - the second optional template argument represents
* the type of the first argument to the callback.
* - the third optional template argument represents
* the type of the second argument to the callback.
* - the fourth optional template argument represents
* the type of the third argument to the callback.
* - the fifth optional template argument represents
* the type of the fourth argument to the callback.
* - the sixth optional template argument represents
* the type of the fifth argument to the callback.
*
* Callback instances are built with the \ref make_callback
* template functions. Callback instances have POD semantics:
* the memory they allocate is managed automatically, without
* user intervention which allows you to pass around Callback
* instances by value.
*
* Sample code which shows how to use this class template
* as well as the function templates \ref make_callback :
* \include samples/main-callback.cc
*/
template<typename R,
typename T1 = empty, typename T2 = empty,
typename T3 = empty, typename T4 = empty,
typename T5 = empty>
class Callback {
public:
template <typename FUNCTOR>
Callback (FUNCTOR const &functor)
: m_impl (new FunctorCallbackImpl<FUNCTOR,R,T1,T2,T3,T4,T5> (functor))
{}
template <typename OBJ_PTR, typename MEM_PTR>
Callback (OBJ_PTR const &obj_ptr, MEM_PTR mem_ptr)
: m_impl (new MemPtrCallbackImpl<OBJ_PTR,MEM_PTR,R,T1,T2,T3,T4,T5> (obj_ptr, mem_ptr))
{}
Callback (ReferenceList<CallbackImpl<R,T1,T2,T3,T4,T5> *> const &impl)
: m_impl (impl)
{}
bool is_null (void) {
return (m_impl.get () == 0)?true:false;
}
Callback () : m_impl () {}
R operator() (void) {
return (*(m_impl.get ())) ();
}
R operator() (T1 a1) {
return (*(m_impl.get ())) (a1);
}
R operator() (T1 a1, T2 a2) {
return (*(m_impl).get ()) (a1,a2);
}
R operator() (T1 a1, T2 a2, T3 a3) {
return (*(m_impl).get ()) (a1,a2,a3);
}
R operator() (T1 a1, T2 a2, T3 a3, T4 a4) {
return (*(m_impl).get ()) (a1,a2,a3,a4);
}
R operator() (T1 a1, T2 a2, T3 a3, T4 a4,T5 a5) {
return (*(m_impl).get ()) (a1,a2,a3,a4,a5);
}
private:
ReferenceList<CallbackImpl<R,T1,T2,T3,T4,T5>*> m_impl;
};
/**
* \defgroup make_callback make_callback
*
*/
/**
* \ingroup make_callback
* \param mem_ptr class method member pointer
* \param obj_ptr class instance
* \return a wrapper Callback
* Build Callbacks for class method members which takes no arguments
* and potentially return a value.
*/
template <typename OBJ, typename R>
Callback<R> make_callback (R (OBJ::*mem_ptr) (), OBJ *const obj_ptr) {
return Callback<R> (obj_ptr, mem_ptr);
}
/**
* \ingroup make_callback
* \param mem_ptr class method member pointer
* \param obj_ptr class instance
* \return a wrapper Callback
* Build Callbacks for class method members which takes one argument
* and potentially return a value.
*/
template <typename OBJ, typename R, typename T1>
Callback<R,T1> make_callback (R (OBJ::*mem_ptr) (T1), OBJ *const obj_ptr) {
return Callback<R,T1> (obj_ptr, mem_ptr);
}
/**
* \ingroup make_callback
* \param mem_ptr class method member pointer
* \param obj_ptr class instance
* \return a wrapper Callback
* Build Callbacks for class method members which takes two arguments
* and potentially return a value.
*/
template <typename OBJ, typename R, typename T1, typename T2>
Callback<R,T1,T2> make_callback (R (OBJ::*mem_ptr) (T1,T2), OBJ *const obj_ptr) {
return Callback<R,T1,T2> (obj_ptr, mem_ptr);
}
/**
* \ingroup make_callback
* \param mem_ptr class method member pointer
* \param obj_ptr class instance
* \return a wrapper Callback
* Build Callbacks for class method members which takes three arguments
* and potentially return a value.
*/
template <typename OBJ, typename R, typename T1,typename T2, typename T3>
Callback<R,T1,T2,T3> make_callback (R (OBJ::*mem_ptr) (T1,T2,T3), OBJ *const obj_ptr) {
return Callback<R,T1,T2,T3> (obj_ptr, mem_ptr);
}
/**
* \ingroup make_callback
* \param mem_ptr class method member pointer
* \param obj_ptr class instance
* \return a wrapper Callback
* Build Callbacks for class method members which takes four arguments
* and potentially return a value.
*/
template <typename OBJ, typename R, typename T1, typename T2, typename T3, typename T4>
Callback<R,T1,T2,T3,T4> make_callback (R (OBJ::*mem_ptr) (T1,T2,T3,T4), OBJ *const obj_ptr) {
return Callback<R,T1,T2,T3,T4> (obj_ptr, mem_ptr);
}
/**
* \ingroup make_callback
* \param mem_ptr class method member pointer
* \param obj_ptr class instance
* \return a wrapper Callback
* Build Callbacks for class method members which takes five arguments
* and potentially return a value.
*/
template <typename OBJ, typename R, typename T1, typename T2, typename T3, typename T4,typename T5>
Callback<R,T1,T2,T3,T4,T5> make_callback (R (OBJ::*mem_ptr) (T1,T2,T3,T4,T5), OBJ *const obj_ptr) {
return Callback<R,T1,T2,T3,T4,T5> (obj_ptr, mem_ptr);
}
/**
* \ingroup make_callback
* \param fn_ptr function pointer
* \return a wrapper Callback
* Build Callbacks for functions which takes no arguments
* and potentially return a value.
*/
template <typename R>
Callback<R> make_callback (R (*fn_ptr) ()) {
return Callback<R> (fn_ptr);
}
/**
* \ingroup make_callback
* \param fn_ptr function pointer
* \return a wrapper Callback
* Build Callbacks for functions which takes one argument
* and potentially return a value.
*/
template <typename R, typename T1>
Callback<R,T1> make_callback (R (*fn_ptr) (T1)) {
return Callback<R,T1> (fn_ptr);
}
/**
* \ingroup make_callback
* \param fn_ptr function pointer
* \return a wrapper Callback
* Build Callbacks for functions which takes two arguments
* and potentially return a value.
*/
template <typename R, typename T1, typename T2>
Callback<R,T1,T2> make_callback (R (*fn_ptr) (T1,T2)) {
return Callback<R,T1,T2> (fn_ptr);
}
/**
* \ingroup make_callback
* \param fn_ptr function pointer
* \return a wrapper Callback
* Build Callbacks for functions which takes three arguments
* and potentially return a value.
*/
template <typename R, typename T1, typename T2,typename T3>
Callback<R,T1,T2,T3> make_callback (R (*fn_ptr) (T1,T2,T3)) {
return Callback<R,T1,T2,T3> (fn_ptr);
}
/**
* \ingroup make_callback
* \param fn_ptr function pointer
* \return a wrapper Callback
* Build Callbacks for functions which takes four arguments
* and potentially return a value.
*/
template <typename R, typename T1, typename T2,typename T3,typename T4>
Callback<R,T1,T2,T3,T4> make_callback (R (*fn_ptr) (T1,T2,T3,T4)) {
return Callback<R,T1,T2,T3,T4> (fn_ptr);
}
/**
* \ingroup make_callback
* \param fn_ptr function pointer
* \return a wrapper Callback
* Build Callbacks for functions which takes five arguments
* and potentially return a value.
*/
template <typename R, typename T1, typename T2,typename T3,typename T4,typename T5>
Callback<R,T1,T2,T3,T4,T5> make_callback (R (*fn_ptr) (T1,T2,T3,T4,T5)) {
return Callback<R,T1,T2,T3,T4,T5> (fn_ptr);
}
/**
* \ingroup make_callback
* \return a wrapper Callback
* Build a null callback which takes no arguments
* and potentially return a value.
*/
template <typename R>
Callback<R> make_null_callback (void) {
return Callback<R> ();
}
/**
* \ingroup make_callback
* \return a wrapper Callback
* Build a null callback which takes one argument
* and potentially return a value.
*/
template <typename R, typename T1>
Callback<R,T1> make_null_callback (void) {
return Callback<R,T1> ();
}
/**
* \ingroup make_callback
* \return a wrapper Callback
* Build a null callback which takes two arguments
* and potentially return a value.
*/
template <typename R, typename T1, typename T2>
Callback<R,T1,T2> make_null_callback (void) {
return Callback<R,T1,T2> ();
}
/**
* \ingroup make_callback
* \return a wrapper Callback
* Build a null callback which takes three arguments
* and potentially return a value.
*/
template <typename R, typename T1, typename T2,typename T3>
Callback<R,T1,T2,T3> make_null_callback (void) {
return Callback<R,T1,T2,T3> ();
}
/**
* \ingroup make_callback
* \return a wrapper Callback
* Build a null callback which takes four arguments
* and potentially return a value.
*/
template <typename R, typename T1, typename T2,typename T3,typename T4>
Callback<R,T1,T2,T3,T4> make_null_callback (void) {
return Callback<R,T1,T2,T3,T4> ();
}
/**
* \ingroup make_callback
* \return a wrapper Callback
* Build a null callback which takes five arguments
* and potentially return a value.
*/
template <typename R, typename T1, typename T2,typename T3,typename T4,typename T5>
Callback<R,T1,T2,T3,T4,T5> make_null_callback (void) {
return Callback<R,T1,T2,T3,T4,T5> ();
}
template <typename R, typename TX, typename T1>
Callback<R,T1> make_bound_callback (R (*fn_ptr) (TX,T1), TX a) {
ReferenceList<CallbackImpl<R,T1,empty,empty,empty,empty>*> impl =
ReferenceList<CallbackImpl<R,T1,empty,empty,empty,empty>*> (
new BoundFunctorCallbackImpl<R (*) (TX,T1),R,TX,T1,empty,empty,empty,empty> (fn_ptr, a)
);
return Callback<R,T1> (impl);
}
template <typename R, typename TX, typename T1, typename T2>
Callback<R,T1,T2> make_bound_callback (R (*fn_ptr) (TX,T1,T2), TX a) {
ReferenceList<CallbackImpl<R,T1,T2,empty,empty,empty>*> impl =
ReferenceList<CallbackImpl<R,T1,T2,empty,empty,empty>*> (
new BoundFunctorCallbackImpl<R (*) (TX,T1,T2),R,TX,T1,T2,empty,empty,empty> (fn_ptr, a)
);
return Callback<R,T1,T2> (impl);
}
template <typename R, typename TX, typename T1, typename T2,typename T3,typename T4>
Callback<R,T1,T2,T3,T4> make_bound_callback (R (*fn_ptr) (TX,T1,T2,T3,T4), TX a) {
ReferenceList<CallbackImpl<R,T1,T2,T3,T4,empty>*> impl =
ReferenceList<CallbackImpl<R,T1,T2,T3,T4,empty>*> (
new BoundFunctorCallbackImpl<R (*) (TX,T1,T2,T3,T4),R,TX,T1,T2,T3,T4,empty> (fn_ptr, a)
);
return Callback<R,T1,T2,T3,T4> (impl);
}
template <typename R, typename TX, typename T1, typename T2,typename T3,typename T4,typename T5>
Callback<R,T1,T2,T3,T4,T5> make_bound_callback (R (*fn_ptr) (TX,T1,T2,T3,T4,T5), TX a) {
ReferenceList<CallbackImpl<R,T1,T2,T3,T4,T5>*> impl =
ReferenceList<CallbackImpl<R,T1,T2,T3,T4,T5>*> (
new BoundFunctorCallbackImpl<R (*) (TX,T1,T2,T3,T4,T5),R,TX,T1,T2,T3,T4,T5> (fn_ptr, a)
);
return Callback<R,T1,T2,T3,T4,T5> (impl);
}
}; // namespace yans
#endif /* CALLBACK_H */

58
src/core/exec-commands.h Normal file
View File

@@ -0,0 +1,58 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef EXEC_COMMANDS_H
#define EXEC_COMMANDS_H
#include <stdint.h>
#include <string>
#include <vector>
#include "callback.h"
namespace yans {
class ExecCommandsPrivate;
class Command {
public:
void reset (void);
void append (std::string arg);
uint32_t get_n (void);
char const *get (uint32_t i);
private:
typedef std::vector<std::string> Args;
Args m_args;
};
class ExecCommands {
public:
typedef Callback<void,char const *,uint32_t> CommandCallback;
ExecCommands (uint32_t pool_size);
void enable_log (char const *main_log);
void add (Command command, char const *id);
void start (void);
uint32_t get_size (void);
private:
ExecCommandsPrivate *m_priv;
};
};
#endif /* EXEC_COMMANDS_H */

View File

@@ -0,0 +1,120 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "reference-list.h"
#include "test.h"
#ifdef RUN_SELF_TESTS
#define noREFTEST_DEBUG 1
#ifdef REFTEST_DEBUG
#include <iostream>
#define TRACE(x) \
std::cout << x << std::endl;
#else
#define TRACE(x)
#endif
namespace {
class A {
public:
A () {
TRACE ("constructor");
}
~A () {
TRACE ("destructor");
}
void trace (void) {
TRACE ("trace");
}
};
class RefTest : public yans::Test {
public:
RefTest ();
virtual bool run_tests (void);
private:
void test (yans::ReferenceList<A *>);
};
RefTest::RefTest ()
: yans::Test ("ReferenceList")
{}
void
RefTest::test (yans::ReferenceList<A *> a)
{
a->trace ();
}
bool
RefTest::run_tests (void)
{
bool ok = true;
{
yans::ReferenceList<A *> tmp;
{
yans::ReferenceList<A *> a (new A ());
test (a);
tmp = a;
test (tmp);
a = tmp;
test (a);
TRACE ("leave inner scope");
}
test (tmp);
TRACE ("leave outer scope");
}
{
yans::ReferenceList<A *> tmp;
}
{
yans::ReferenceList<A *> tmp (new A ());
}
{
yans::ReferenceList<A *> tmp;
tmp.set (new A ());
}
{
TRACE ("test assignement");
yans::ReferenceList<A *> a0 (new A ());
yans::ReferenceList<A *> a1 (new A ());
a0 = a1;
}
return ok;
}
static RefTest g_ref_test = RefTest ();
}; // namespace
#endif /* RUN_SELF_TESTS */

117
src/core/reference-list.h Normal file
View File

@@ -0,0 +1,117 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef REFERENCE_LIST_H
#define REFERENCE_LIST_H
/* This is a reference list implementation. The technique underlying
* this code was first described in 1995 by Risto Lankinen on Usenet
* but I have never been able to find his original posting. Instead,
* this code is based on the description of the technique found in
* "Modern C++ design" by Andrei Alexandrescu in chapter 7.
*/
namespace yans {
template <typename OBJ_PTR>
class ReferenceList;
template <typename OBJ_PTR>
class ReferenceList {
public:
ReferenceList ()
: m_obj_ptr (),
m_prev (),
m_next ()
{
m_prev = this;
m_next = this;
}
ReferenceList (ReferenceList &o)
: m_obj_ptr (),
m_prev (),
m_next ()
{
m_prev = this;
m_next = this;
insert_self_in_other (o);
}
ReferenceList (ReferenceList const&o)
: m_obj_ptr (),
m_prev (),
m_next ()
{
m_prev = this;
m_next = this;
insert_self_in_other (o);
}
ReferenceList (OBJ_PTR const &obj_ptr)
: m_obj_ptr (obj_ptr),
m_prev (),
m_next ()
{
m_prev = this;
m_next = this;
}
~ReferenceList () {
remove_from_list ();
}
ReferenceList & operator= (ReferenceList const&o) {
remove_from_list ();
insert_self_in_other (o);
return *this;
}
OBJ_PTR operator-> () {
return m_obj_ptr;
}
void set (OBJ_PTR obj_ptr) {
remove_from_list ();
m_obj_ptr = obj_ptr;
}
OBJ_PTR get (void) {
// explicit conversion to raw pointer type.
return m_obj_ptr;
}
private:
void insert_self_in_other (ReferenceList const&o) {
m_prev = &o;
m_next = o.m_next;
m_next->m_prev = this;
o.m_next = this;
m_obj_ptr = o.m_obj_ptr;
}
void remove_from_list (void) {
if (m_prev == this) {
//assert (m_next == this);
delete m_obj_ptr;
m_obj_ptr = OBJ_PTR ();
}
m_prev->m_next = m_next;
m_next->m_prev = m_prev;
}
OBJ_PTR m_obj_ptr;
mutable ReferenceList const*m_prev;
mutable ReferenceList const*m_next;
};
}; // namespace yans
#endif /* REFERENCE_LIST_H */

44
src/core/system-file.h Normal file
View File

@@ -0,0 +1,44 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef SYSTEM_FILE_H
#define SYSTEM_FILE_H
#include <stdint.h>
namespace yans {
class SystemFilePrivate;
class SystemFile {
public:
SystemFile ();
~SystemFile ();
void open (char const *filename);
void write (uint8_t *buffer, uint32_t size);
private:
SystemFilePrivate *m_priv;
};
}; //namespace yans
#endif /* SYSTEM_FILE_H */

42
src/core/system-mutex.h Normal file
View File

@@ -0,0 +1,42 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef SYSTEM_MUTEX_H
#define SYSTEM_MUTEX_H
#include <stdint.h>
namespace yans {
class SystemMutexPrivate;
class SystemMutex {
public:
SystemMutex ();
~SystemMutex ();
void lock (void);
void unlock (void);
private:
SystemMutexPrivate *m_priv;
};
}; // namespace yans
#endif /* SYSTEM_MUTEX_H */

View File

@@ -0,0 +1,44 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef SYSTEM_SEMAPHORE_H
#define SYSTEM_SEMAPHORE_H
#include <stdint.h>
namespace yans {
class SystemSemaphorePrivate;
class SystemSemaphore {
public:
SystemSemaphore (uint32_t init);
~SystemSemaphore ();
void post (void);
void post (uint32_t n);
void wait (void);
void wait (uint32_t n);
private:
SystemSemaphorePrivate *m_priv;
};
}; // namespace yans
#endif /* SYSTEM_SEMAPHORE_H */

41
src/core/system-thread.h Normal file
View File

@@ -0,0 +1,41 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef SYSTEM_THREAD_H
#define SYSTEM_THREAD_H
namespace yans {
class SystemThreadPrivate;
class SystemThread {
public:
SystemThread ();
virtual ~SystemThread ();
private:
friend class SystemThreadPrivate;
SystemThreadPrivate *m_priv;
virtual void real_run (void) = 0;
};
}; // namespace yans
#endif /* SYSTEM_THREAD_H */

107
src/core/test.cc Normal file
View File

@@ -0,0 +1,107 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "test.h"
#ifdef RUN_SELF_TESTS
#include <iostream>
namespace yans {
TestManager *
TestManager::get (void)
{
static TestManager manager;
return &manager;
}
TestManager::TestManager ()
: m_verbose (false)
{}
TestManager::~TestManager ()
{
TestsI i = m_tests.begin ();
while (i != m_tests.end ()) {
delete (*i).second;
i = m_tests.erase (i);
}
}
void
TestManager::add (Test *test, char const *name)
{
get ()->m_tests.push_back (std::make_pair (test, new std::string (name)));
}
void
TestManager::enable_verbose (void)
{
get ()->m_verbose = true;
}
std::ostream &
TestManager::failure (void)
{
return std::cerr;
}
bool
TestManager::run_tests (void)
{
return get ()->real_run_tests ();
}
bool
TestManager::real_run_tests (void)
{
bool is_success = true;
for (TestsCI i = m_tests.begin (); i != m_tests.end (); i++) {
std::string *test_name = (*i).second;
if (!(*i).first->run_tests ()) {
is_success = false;
if (m_verbose) {
std::cerr << "FAIL " << *test_name << std::endl;
}
} else {
if (m_verbose) {
std::cerr << "PASS "<<*test_name << std::endl;
}
}
}
if (!is_success) {
std::cerr << "FAIL" << std::endl;
}
return is_success;
}
Test::Test (char const *name)
{
TestManager::add (this, name);
}
Test::~Test ()
{}
std::ostream &
Test::failure (void)
{
return TestManager::failure ();
}
}; // namespace yans
#endif /* RUN_SELF_TESTS */

75
src/core/test.h Normal file
View File

@@ -0,0 +1,75 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef TEST_H
#define TEST_H
#include <list>
#include <string>
#include <utility>
#include <ostream>
#ifdef RUN_SELF_TESTS
namespace yans {
class TestManager;
class Test {
public:
Test (char const *name);
virtual ~Test ();
virtual bool run_tests (void) = 0;
protected:
std::ostream &failure (void);
};
class TestManager {
public:
// main methods the test runner is supposed to
// invoke.
static void enable_verbose (void);
static bool run_tests (void);
// helper methods
static void add (Test *test, char const *name);
static std::ostream &failure (void);
private:
static TestManager *get (void);
bool real_run_tests (void);
TestManager ();
~TestManager ();
typedef std::list<std::pair<Test *,std::string *> > Tests;
typedef std::list<std::pair<Test *,std::string *> >::iterator TestsI;
typedef std::list<std::pair<Test *,std::string *> >::const_iterator TestsCI;
Tests m_tests;
bool m_verbose;
};
}; // namespace yans
#endif /* RUN_SELF_TESTS */
#endif /* TEST_H */

View File

@@ -0,0 +1,516 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "exec-commands.h"
#include "system-thread.h"
#include "system-semaphore.h"
#include "system-mutex.h"
#include "callback.h"
#include <cassert>
#include <vector>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <iostream>
#include <sys/select.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define noTRACE_COMMAND 1
#ifdef TRACE_COMMAND
#include <iostream>
# define TRACE(x) \
std::cout << "COMMAND TRACE " << x << std::endl;
#else /* TRACE_COMMAND */
# define TRACE(format,...)
#endif /* TRACE_COMMAND */
namespace yans {
class LogThread : public SystemThread {
public:
LogThread (int main_log);
virtual ~LogThread ();
void add (int in, int out);
private:
virtual void real_run (void);
void write_to (int fd, char *buffer, int size);
typedef std::vector<int> Fds;
typedef std::vector<int>::iterator FdsI;
int m_main_log;
Fds m_input_fds;
Fds m_output_fds;
SystemMutex m_fds_mutex;
};
LogThread::LogThread (int main_log)
: m_main_log (main_log)
{}
LogThread::~LogThread ()
{}
void
LogThread::add (int in, int out)
{
m_fds_mutex.lock ();
m_input_fds.push_back (in);
m_output_fds.push_back (out);
m_fds_mutex.unlock ();
}
void
LogThread::write_to (int fd, char *buffer, int to_write)
{
while (to_write > 0) {
int written = write (fd, buffer, to_write);
to_write -= written;
buffer += written;
assert (written >= 0);
}
}
void
LogThread::real_run (void)
{
char buffer[1024];
while (true) {
fd_set in;
struct timeval tv;
int retval;
TRACE ("prepare fd set");
m_fds_mutex.lock ();
assert (m_input_fds.size () == m_output_fds.size ());
FD_ZERO (&in);
int max_fd = 0;
for (uint32_t i = 0; i < m_input_fds.size (); i++) {
if (m_input_fds[i] > max_fd) {
max_fd = m_input_fds[i];
}
FD_SET (m_input_fds[i], &in);
}
m_fds_mutex.unlock ();
TRACE ("fd set prepared");
tv.tv_sec = 1;
tv.tv_usec = 0;
retval = select (max_fd+1, &in, NULL, NULL, &tv);
TRACE ("selected");
for (uint32_t i = 0; i < m_input_fds.size (); i++) {
if (FD_ISSET (m_input_fds[i], &in)) {
retval = read (m_input_fds[i], buffer, 1024);
if (retval == 0) {
close (m_output_fds[i]);
TRACE ("closed input");
m_fds_mutex.lock ();
FdsI cur = m_input_fds.begin ();
cur += i;
m_input_fds.erase (cur);
cur = m_output_fds.begin ();
cur += i;
m_output_fds.erase (cur);
m_fds_mutex.unlock ();
continue;
}
assert (retval > 0);
write_to (m_output_fds[i], buffer, retval);
write_to (m_main_log, buffer, retval);
}
}
TRACE ("written");
}
}
class CommandSystemThread : public SystemThread {
public:
typedef Callback<void, CommandSystemThread *, int, std::string> DoneLogCallback;
typedef Callback<void, CommandSystemThread *> DoneNoLogCallback;
CommandSystemThread ();
void start_log (Command command, std::string id, DoneLogCallback callback);
void start_no_log (Command command, DoneNoLogCallback callback);
void stop (void);
private:
virtual void real_run (void);
void run_exec (void);
SystemSemaphore m_sem;
bool m_stop;
Command m_command;
std::string m_id;
DoneLogCallback m_done_log;
DoneNoLogCallback m_done_no_log;
bool m_no_log;
};
CommandSystemThread::CommandSystemThread ()
: m_sem (0),
m_stop (false)
{}
void
CommandSystemThread::start_no_log (Command command, DoneNoLogCallback done)
{
m_no_log = true;
m_command = command;
m_done_no_log = done;
m_sem.post ();
}
void
CommandSystemThread::start_log (Command command, std::string id, DoneLogCallback done)
{
m_no_log = false;
m_command = command;
m_id = id;
m_done_log = done;
m_sem.post ();
}
void
CommandSystemThread::stop (void)
{
m_stop = true;
m_sem.post ();
}
void
CommandSystemThread::run_exec (void)
{
char ** args = (char **)malloc (sizeof (char *) * (m_command.get_n ()+1));
char const *file = m_command.get (0);
args[0] = strdup (m_command.get (0));
for (uint32_t i = 1; i < m_command.get_n (); i++) {
args[i] = strdup (m_command.get (i));
//std::cout << "arg " << args[i-1] << std::endl;
}
args[m_command.get_n ()] = (char *)NULL;
int retval = execvp (file, args);
if (retval != 0) {
std::cout << strerror (errno) << std::endl;
exit (1);
}
// NOTREACHED
assert (false);
}
void
CommandSystemThread::real_run (void)
{
while (true) {
m_sem.wait ();
if (m_stop) {
break;
}
int retval;
int filedes[2];
if (m_no_log) {
pid_t pid = fork ();
if (pid == -1) {
assert (false);
// error in parent fork.
} else if (pid == 0) {
retval = open ("/dev/null", O_WRONLY);
dup2 (retval, 1);
close (retval);
// success, child.
run_exec ();
} else {
// success, parent.
m_done_no_log (this);
}
} else {
retval = pipe (filedes);
assert (retval == 0);
pid_t pid = fork ();
if (pid == -1) {
assert (false);
// error in parent fork.
} else if (pid == 0) {
// success, child.
TRACE ("child");
close (1);
close (filedes[0]);
dup2 (filedes[1], 1);
run_exec ();
} else {
TRACE ("parent");
// success, parent.
close (filedes[1]);
m_done_log (this, filedes[0], m_id);
}
}
}
}
class ExecCommandsPrivate {
public:
ExecCommandsPrivate (uint32_t pool_size);
~ExecCommandsPrivate ();
void enable_log (char const *main_log);
void add (Command command, std::string id);
void start (void);
uint32_t get_size (void);
private:
struct CommandRequest {
Command m_command;
std::string m_id;
};
typedef std::vector<CommandSystemThread *> Threads;
typedef std::vector<CommandSystemThread *>::iterator ThreadsI;
typedef std::vector<CommandRequest> Requests;
typedef std::vector<CommandRequest>::iterator RequestsI;
void command_done_log (CommandSystemThread *thread, int fd, std::string id);
void command_done_no_log (CommandSystemThread *thread);
Requests m_requests;
SystemSemaphore m_n_threads;
uint32_t m_pool_size;
Threads m_threads;
SystemMutex m_threads_mutex;
int m_main_log;
LogThread *m_log;
};
ExecCommandsPrivate::ExecCommandsPrivate (uint32_t pool_size)
: m_n_threads (0),
m_pool_size (pool_size),
m_main_log (0),
m_log (0)
{
m_threads_mutex.lock ();
for (uint32_t i = 0; i < pool_size; i++) {
m_threads.push_back (new CommandSystemThread ());
}
m_threads_mutex.unlock ();
m_n_threads.post (m_pool_size);
}
ExecCommandsPrivate::~ExecCommandsPrivate ()
{
m_threads_mutex.lock ();
for (ThreadsI i = m_threads.begin (); i != m_threads.end (); i++) {
(*i)->stop ();
delete *i;
}
m_threads.erase (m_threads.begin (), m_threads.end ());
m_threads_mutex.unlock ();
delete m_log;
}
void
ExecCommandsPrivate::enable_log (char const *main_log)
{
m_main_log = open (main_log, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
m_log = new LogThread (m_main_log);
assert (m_main_log != -1);
}
void
ExecCommandsPrivate::add (Command command, std::string id)
{
struct CommandRequest request;
request.m_command = command;
request.m_id = id;
m_requests.push_back (request);
}
void
ExecCommandsPrivate::start (void)
{
for (RequestsI i = m_requests.begin (); i != m_requests.end (); i++) {
TRACE ("wait for thread");
m_n_threads.wait ();
m_threads_mutex.lock ();
CommandSystemThread *thread = m_threads.back ();
m_threads.pop_back ();
m_threads_mutex.unlock ();
TRACE ("start command");
if (m_main_log != 0) {
thread->start_log (i->m_command, i->m_id,
make_callback (&ExecCommandsPrivate::command_done_log, this));
} else {
thread->start_no_log (i->m_command,
make_callback (&ExecCommandsPrivate::command_done_no_log, this));
}
}
}
void
ExecCommandsPrivate::command_done_log (CommandSystemThread *thread, int in, std::string id)
{
TRACE ("command done");
m_threads_mutex.lock ();
m_threads.push_back (thread);
m_threads_mutex.unlock ();
m_n_threads.post ();
std::string out_filename = id;
out_filename.append (".log");
int out_fd = open (out_filename.c_str (), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
assert (out_fd != -1);
m_log->add (in, out_fd);
TRACE ("notify command done");
}
void
ExecCommandsPrivate::command_done_no_log (CommandSystemThread *thread)
{
TRACE ("command done");
m_threads_mutex.lock ();
m_threads.push_back (thread);
m_threads_mutex.unlock ();
m_n_threads.post ();
TRACE ("notify command done");
}
uint32_t
ExecCommandsPrivate::get_size (void)
{
return m_requests.size ();
}
void
Command::reset (void)
{
m_args.erase (m_args.begin (), m_args.end ());
}
void
Command::append (std::string arg)
{
m_args.push_back (arg);
}
uint32_t
Command::get_n (void)
{
return m_args.size ();
}
char const*
Command::get (uint32_t i)
{
return m_args[i].c_str ();
}
ExecCommands::ExecCommands (uint32_t pool_size)
: m_priv (new ExecCommandsPrivate (pool_size))
{
assert (pool_size != 0);
}
void
ExecCommands::enable_log (char const *main_log)
{
m_priv->enable_log (main_log);
}
void
ExecCommands::add (Command command, char const *id)
{
m_priv->add (command, id);
}
void
ExecCommands::start (void)
{
m_priv->start ();
}
uint32_t
ExecCommands::get_size (void)
{
return m_priv->get_size ();
}
}; // namespace yans
#ifdef RUN_SELF_TESTS
#include "test.h"
#include <iomanip>
#include <iostream>
namespace yans {
class ExecCommandsTest: public Test {
public:
ExecCommandsTest ();
virtual ~ExecCommandsTest ();
virtual bool run_tests (void);
private:
void command_output (char const *data, uint32_t size);
};
ExecCommandsTest::ExecCommandsTest ()
: Test ("ExecCommands")
{}
ExecCommandsTest::~ExecCommandsTest ()
{}
void
ExecCommandsTest::command_output (char const *data, uint32_t size)
{
for (uint32_t i = 0; i < size; i++) {
std::cout << data[i];
};
}
bool
ExecCommandsTest::run_tests (void)
{
bool ok = true;
#if 0
ExecCommands commands = ExecCommands (2);
Command command;
command.append ("ls");
command.append ("-l");
commands.add (command, "ls");
command.reset ();
command.append ("ls");
command.append ("-l");
command.append ("src");
commands.add (command, "ls-src");
command.reset ();
command.append ("ls");
command.append ("-l");
command.append ("/usr/bin");
commands.add (command, "ls-usr-bin");
commands.enable_log ("main.log");
commands.start ();
sleep (5);
#endif
return ok;
}
static ExecCommandsTest g_exec_commands_test;
}; // namespace yans
#endif /* RUN_SELF_TESTS */

View File

@@ -0,0 +1,119 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "system-file.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/poll.h>
#include <fcntl.h>
#include <unistd.h>
#include <cassert>
#include <string.h>
#include <list>
#define noTRACE_SYS_FILE 1
#ifdef TRACE_SYS_FILE
#include <iostream>
# define TRACE(x) \
std::cout << "SYS FILE TRACE " << this << " " << x << std::endl;
#else /* TRACE_SYS_FILE */
# define TRACE(format,...)
#endif /* TRACE_SYS_FILE */
#define BUFFER_SIZE (4096)
namespace yans {
class SystemFilePrivate {
public:
SystemFilePrivate ();
~SystemFilePrivate ();
void open (char const *filename);
void write (uint8_t *buffer, uint32_t size);
private:
uint8_t m_data[BUFFER_SIZE];
uint32_t m_current;
int m_fd;
};
SystemFilePrivate::SystemFilePrivate ()
: m_current (0)
{}
SystemFilePrivate::~SystemFilePrivate ()
{
::write (m_fd, m_data, m_current);
::close (m_fd);
}
void
SystemFilePrivate::open (char const *filename)
{
m_fd = ::open (filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
assert (m_fd != -1);
}
#ifndef min
#define min(a,b) ((a)<(b)?(a):(b))
#endif /* min */
void
SystemFilePrivate::write (uint8_t *buffer, uint32_t size)
{
while (size > 0) {
uint32_t to_copy = min (BUFFER_SIZE - m_current, size);
memcpy (m_data + m_current, buffer, to_copy);
size -= to_copy;
m_current += to_copy;
buffer += to_copy;
if (m_current == BUFFER_SIZE) {
ssize_t written = 0;
written = ::write (m_fd, m_data, BUFFER_SIZE);
assert (written == BUFFER_SIZE);
m_current = 0;
}
}
}
SystemFile::SystemFile ()
: m_priv (new SystemFilePrivate ())
{}
SystemFile::~SystemFile ()
{
delete m_priv;
m_priv = 0;
}
void
SystemFile::open (char const *filename)
{
m_priv->open (filename);
}
void
SystemFile::write (uint8_t *buffer, uint32_t size)
{
m_priv->write (buffer, size);
}
}; // namespace

View File

@@ -0,0 +1,82 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "system-mutex.h"
#include <pthread.h>
#include <cassert>
namespace yans {
class SystemMutexPrivate {
public:
SystemMutexPrivate ();
~SystemMutexPrivate ();
void lock (void);
void unlock (void);
private:
pthread_mutex_t m_mutex;
};
SystemMutexPrivate::SystemMutexPrivate ()
{
int retval;
retval = pthread_mutex_init (&m_mutex, NULL);
assert (retval == 0);
}
SystemMutexPrivate::~SystemMutexPrivate ()
{
int retval;
retval = pthread_mutex_destroy (&m_mutex);
assert (retval == 0);
}
void
SystemMutexPrivate::lock (void)
{
pthread_mutex_lock (&m_mutex);
}
void
SystemMutexPrivate::unlock (void)
{
pthread_mutex_unlock (&m_mutex);
}
SystemMutex::SystemMutex ()
: m_priv (new SystemMutexPrivate ())
{}
SystemMutex::~SystemMutex ()
{
delete m_priv;
}
void
SystemMutex::lock (void)
{
m_priv->lock ();
}
void
SystemMutex::unlock (void)
{
m_priv->unlock ();
}
}; // namespace yans

View File

@@ -0,0 +1,114 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "system-semaphore.h"
#include <semaphore.h>
#include <cassert>
#include <iostream>
#include "errno.h"
#include "string.h"
namespace yans {
class SystemSemaphorePrivate {
public:
SystemSemaphorePrivate (uint32_t init);
void post (void);
void post (uint32_t n);
void wait (void);
void wait (uint32_t n);
private:
sem_t m_sem;
};
SystemSemaphorePrivate::SystemSemaphorePrivate (uint32_t init)
{
int retval = sem_init (&m_sem, 0, init);
if (retval == -1) {
std::cout << "sem init " << this << " " << strerror (errno) << std::endl;
}
}
void
SystemSemaphorePrivate::post (void)
{
int retval = sem_post (&m_sem);
if (retval == -1) {
std::cout << "sem post " << this << " " << strerror (errno) << std::endl;
}
}
void
SystemSemaphorePrivate::wait (void)
{
int retval;
do {
retval = sem_wait (&m_sem);
} while (retval == -1 && errno == EINTR);
if (retval == -1) {
std::cout << "sem wait " << this << " " << strerror (errno) << std::endl;
}
}
void
SystemSemaphorePrivate::post (uint32_t n)
{
for (uint32_t i = 0; i < n; i++) {
post ();
}
}
void
SystemSemaphorePrivate::wait (uint32_t n)
{
for (uint32_t i = 0; i < n; i++) {
wait ();
}
}
SystemSemaphore::SystemSemaphore (uint32_t init)
: m_priv (new SystemSemaphorePrivate (init))
{}
SystemSemaphore::~SystemSemaphore ()
{
delete m_priv;
}
void
SystemSemaphore::post (void)
{
m_priv->post ();
}
void
SystemSemaphore::post (uint32_t n)
{
m_priv->post (n);
}
void
SystemSemaphore::wait (void)
{
m_priv->wait ();
}
void
SystemSemaphore::wait (uint32_t n)
{
m_priv->wait (n);
}
}; // namespace yans

View File

@@ -0,0 +1,69 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "system-thread.h"
#include <pthread.h>
#include <cassert>
namespace yans {
class SystemThreadPrivate {
public:
SystemThreadPrivate (SystemThread *thread);
~SystemThreadPrivate ();
private:
static void *pthread_run (void *thread);
pthread_t m_system_thread;
SystemThread *m_thread;
};
SystemThreadPrivate::SystemThreadPrivate (SystemThread *thread)
: m_thread (thread)
{
int retval;
retval = pthread_create (&m_system_thread,
NULL,
SystemThreadPrivate::pthread_run,
this);
assert (retval == 0);
}
SystemThreadPrivate::~SystemThreadPrivate ()
{}
void *
SystemThreadPrivate::pthread_run (void *thread)
{
SystemThreadPrivate *self = reinterpret_cast<SystemThreadPrivate *> (thread);
self->m_thread->real_run ();
return thread;
}
SystemThread::SystemThread ()
: m_priv (new SystemThreadPrivate (this))
{}
SystemThread::~SystemThread ()
{
delete m_priv;
}
}; // namespace yans

View File

@@ -0,0 +1,74 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage.inria.fr>
*/
#include "wall-clock-ms.h"
#include <sys/time.h>
namespace yans {
class WallClockMsPrivate {
public:
void start (void);
unsigned long long end (void);
private:
struct timeval m_start_tv;
struct timeval m_end_tv;
};
void
WallClockMsPrivate::start (void)
{
struct timezone tz;
gettimeofday (&m_start_tv, &tz);
}
unsigned long long
WallClockMsPrivate::end (void)
{
struct timezone tz;
gettimeofday (&m_end_tv, &tz);
unsigned long long end = m_end_tv.tv_sec *1000 + m_end_tv.tv_usec / 1000;
unsigned long long start = m_start_tv.tv_sec *1000 + m_start_tv.tv_usec / 1000;
return end - start;
}
WallClockMs::WallClockMs ()
: m_priv (new WallClockMsPrivate ())
{}
WallClockMs::~WallClockMs ()
{
delete m_priv;
m_priv = 0;
}
void
WallClockMs::start (void)
{
m_priv->start ();
}
unsigned long long
WallClockMs::end (void)
{
return m_priv->end ();
}
}; // namespace yans

40
src/core/wall-clock-ms.h Normal file
View File

@@ -0,0 +1,40 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage.inria.fr>
*/
#ifndef WALL_CLOCK_MS_H
#define WALL_CLOCK_MS_H
namespace yans {
class WallClockMs {
public:
WallClockMs ();
~WallClockMs ();
void start (void);
unsigned long long end (void);
private:
class WallClockMsPrivate *m_priv;
};
}; // namespace yans
#endif /* WALL_CLOCK_MS_H */

View File

@@ -0,0 +1,86 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "system-file.h"
#define noTRACE_SYS_FILE 1
#ifdef TRACE_SYS_FILE
#include <iostream>
# define TRACE(x) \
std::cout << "SYS FILE TRACE " << this << " " << x << std::endl;
#else /* TRACE_SYS_FILE */
# define TRACE(format,...)
#endif /* TRACE_SYS_FILE */
#define BUFFER_SIZE (4096)
namespace yans {
class SystemFilePrivate {
public:
SystemFilePrivate ();
~SystemFilePrivate ();
void open (char const *filename);
void write (uint8_t *buffer, uint32_t size);
private:
};
SystemFilePrivate::SystemFilePrivate ()
{}
SystemFilePrivate::~SystemFilePrivate ()
{
}
void
SystemFilePrivate::open (char const *filename)
{
}
void
SystemFilePrivate::write (uint8_t *buffer, uint32_t size)
{
}
SystemFile::SystemFile ()
: m_priv (new SystemFilePrivate ())
{}
SystemFile::~SystemFile ()
{
delete m_priv;
m_priv = 0;
}
void
SystemFile::open (char const *filename)
{
m_priv->open (filename);
}
void
SystemFile::write (uint8_t *buffer, uint32_t size)
{
m_priv->write (buffer, size);
}
}; // namespace

View File

@@ -0,0 +1,78 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "system-mutex.h"
#include <windows.h>
#include <cassert>
namespace yans {
class SystemMutexPrivate {
public:
SystemMutexPrivate ();
~SystemMutexPrivate ();
void lock (void);
void unlock (void);
private:
HANDLE m_mutex;
};
SystemMutexPrivate::SystemMutexPrivate ()
{
m_mutex = CreateMutex(NULL, FALSE, "mutex");
}
SystemMutexPrivate::~SystemMutexPrivate ()
{
CloseHandle (m_mutex);
}
void
SystemMutexPrivate::lock (void)
{
WaitForSingleObject (m_mutex,INFINITE);
}
void
SystemMutexPrivate::unlock (void)
{
ReleaseMutex (m_mutex);
}
SystemMutex::SystemMutex ()
: m_priv (new SystemMutexPrivate ())
{}
SystemMutex::~SystemMutex ()
{
delete m_priv;
}
void
SystemMutex::lock (void)
{
m_priv->lock ();
}
void
SystemMutex::unlock (void)
{
m_priv->unlock ();
}
}; // namespace yans

View File

@@ -0,0 +1,103 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "system-semaphore.h"
#include <windows.h>
#include <cassert>
#include <iostream>
namespace yans {
class SystemSemaphorePrivate {
public:
SystemSemaphorePrivate (uint32_t init);
~SystemSemaphorePrivate ();
void post (void);
void post (uint32_t n);
void wait (void);
void wait (uint32_t n);
private:
HANDLE m_sem;
};
SystemSemaphorePrivate::SystemSemaphorePrivate (uint32_t init)
{
m_sem = CreateSemaphore(NULL, init, 0, "semaphore");
}
SystemSemaphorePrivate::~SystemSemaphorePrivate ()
{
CloseHandle (m_sem);
}
void
SystemSemaphorePrivate::post (void)
{
ReleaseSemaphore(m_sem,1,NULL);
}
void
SystemSemaphorePrivate::wait (void)
{
WaitForSingleObject (m_sem, INFINITE);
}
void
SystemSemaphorePrivate::post (uint32_t n)
{
ReleaseSemaphore(m_sem,n,NULL);
}
void
SystemSemaphorePrivate::wait (uint32_t n)
{
for (uint32_t i = 0; i < n; i++) {
wait ();
}
}
SystemSemaphore::SystemSemaphore (uint32_t init)
: m_priv (new SystemSemaphorePrivate (init))
{}
SystemSemaphore::~SystemSemaphore ()
{
delete m_priv;
}
void
SystemSemaphore::post (void)
{
m_priv->post ();
}
void
SystemSemaphore::post (uint32_t n)
{
m_priv->post (n);
}
void
SystemSemaphore::wait (void)
{
m_priv->wait ();
}
void
SystemSemaphore::wait (uint32_t n)
{
m_priv->wait (n);
}
}; // namespace yans

View File

@@ -0,0 +1,66 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "system-thread.h"
#include <windows.h>
#include <cassert>
namespace yans {
class SystemThreadPrivate {
public:
SystemThreadPrivate (SystemThread *thread);
~SystemThreadPrivate ();
private:
static void *thread_run (void *thread);
SystemThread *m_thread;
HANDLE m_system_thread;
};
SystemThreadPrivate::SystemThreadPrivate (SystemThread *thread)
: m_thread (thread)
{
m_system_thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)SystemThreadPrivate::thread_run,
this, 0, 0);
assert (m_system_thread != NULL);
}
SystemThreadPrivate::~SystemThreadPrivate ()
{}
void *
SystemThreadPrivate::thread_run (void *thread)
{
SystemThreadPrivate *self = reinterpret_cast<SystemThreadPrivate *> (thread);
self->m_thread->real_run ();
return thread;
}
SystemThread::SystemThread ()
: m_priv (new SystemThreadPrivate (this))
{}
SystemThread::~SystemThread ()
{
delete m_priv;
}
}; // namespace yans

View File

@@ -0,0 +1,65 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage.inria.fr>
*/
#include "wall-clock-ms.h"
namespace yans {
class WallClockMsPrivate {
public:
void start (void);
unsigned long long end (void);
private:
};
void
WallClockMsPrivate::start (void)
{
}
unsigned long long
WallClockMsPrivate::end (void)
{
return 0;
}
WallClockMs::WallClockMs ()
: m_priv (new WallClockMsPrivate ())
{}
WallClockMs::~WallClockMs ()
{
delete m_priv;
m_priv = 0;
}
void
WallClockMs::start (void)
{
m_priv->start ();
}
unsigned long long
WallClockMs::end (void)
{
return m_priv->end ();
}
}; // namespace yans

View File

@@ -0,0 +1,67 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "event-impl.h"
namespace yans {
EventImpl::~EventImpl ()
{}
EventImpl::EventImpl ()
: m_id (0),
m_count (1),
m_cancel (0),
m_running (1)
{}
void
EventImpl::invoke (void)
{
if (m_cancel == 0) {
notify ();
}
m_running = 0;
}
void
EventImpl::set_tag (void *tag)
{
m_id = tag;
}
void *
EventImpl::get_tag (void) const
{
return m_id;
}
void
EventImpl::cancel (void)
{
m_cancel = 1;
m_running = 0;
}
bool
EventImpl::is_running (void)
{
return (m_running == 1);
}
}; // namespace yans

View File

@@ -0,0 +1,49 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005,2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef EVENT_IMPL_H
#define EVENT_IMPL_H
#include <stdint.h>
namespace yans {
class EventImpl {
public:
EventImpl ();
virtual ~EventImpl () = 0;
void invoke (void);
void set_tag (void *tag);
void *get_tag (void) const;
void cancel (void);
bool is_running (void);
protected:
virtual void notify (void) = 0;
private:
friend class Event;
void *m_id;
uint32_t m_count;
uint32_t m_cancel : 1;
uint32_t m_running : 1;
};
}; // namespace yans
#endif /* EVENT_IMPL_H */

View File

@@ -0,0 +1,110 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "event.tcc"
#include "yans/test.h"
#ifdef RUN_SELF_TESTS
#define ENSURE(got,expected) \
if (got != expected) { \
g_error = true; \
}
namespace {
bool g_error = false;
void null_cb (void)
{}
void one_cb (int a)
{
ENSURE (a, 1);
}
void two_cb (int a,int b)
{
ENSURE (a, 1);
ENSURE (b, 2);
}
void three_cb (int a,int b,int c)
{
ENSURE (a, 1);
ENSURE (b, 2);
ENSURE (c, 3);
}
void four_cb (int a,int b,int c,int d)
{
ENSURE (a, 1);
ENSURE (b, 2);
ENSURE (c, 3);
ENSURE (d, 4);
}
void five_cb (int a,int b,int c,int d,int e)
{
ENSURE (a, 1);
ENSURE (b, 2);
ENSURE (c, 3);
ENSURE (d, 4);
ENSURE (e, 5);
}
};
namespace yans {
class EventTest : public Test {
public:
EventTest ();
virtual bool run_tests (void);
};
EventTest::EventTest ()
: Test ("Event")
{}
bool
EventTest::run_tests (void)
{
Event ev;
ev = yans::make_event (&null_cb);
ev ();
ev = yans::make_event (&one_cb, 1);
ev ();
ev = yans::make_event (&two_cb, 1, 2);
ev ();
ev = yans::make_event (&three_cb, 1, 2, 3);
ev ();
ev = yans::make_event (&four_cb, 1, 2, 3, 4);
ev ();
ev = yans::make_event (&five_cb, 1, 2, 3, 4, 5);
ev ();
if (g_error) {
return false;
}
return true;
}
static EventTest g_test;
};
#endif /* RUN_SELF_TESTS */

View File

@@ -0,0 +1,47 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "event-impl.h"
#include "event.h"
namespace yans {
class EventFunctionImpl0 : public EventImpl {
public:
typedef void (*F)(void);
EventFunctionImpl0 (F function)
: m_function (function)
{}
virtual ~EventFunctionImpl0 () {}
private:
virtual void notify (void) {
(*m_function) ();
}
private:
F m_function;
};
Event make_event(void (*f) (void))
{
return Event (new EventFunctionImpl0 (f));
}
}; // namespace yans

140
src/simulator/event.h Normal file
View File

@@ -0,0 +1,140 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef EVENT_H
#define EVENT_H
#include <algorithm>
#include "event-impl.h"
namespace yans {
class EventImpl;
/**
* \brief Simulation events.
*
* The Event class has POD semantics: it can and should
* be passed around by value. The Event class is a mere
* wrapper around the EventImpl class and performs
* memory management of EventImpl object instances.
*
* While users could create Events by instanciating
* subclasses of the EventImpl class and storing them
* in an Event instance, they are advised to use the
* template functions \ref make_event instead.
*/
class Event {
public:
Event ()
: m_impl (0)
{}
Event (EventImpl *impl)
: m_impl (impl)
{}
Event (Event const &o)
: m_impl (o.m_impl)
{
if (m_impl != 0) {
m_impl->m_count++;
}
}
~Event ()
{
if (m_impl != 0) {
m_impl->m_count--;
if (m_impl->m_count == 0) {
delete m_impl;
}
}
m_impl = 0;
}
Event &operator = (Event const&o)
{
if (m_impl != 0) {
m_impl->m_count--;
if (m_impl->m_count == 0) {
delete m_impl;
}
}
m_impl = o.m_impl;
if (m_impl != 0) {
m_impl->m_count++;
}
return *this;
}
void operator () (void)
{
m_impl->invoke ();
}
/**
* Cancel an event. This operation has O(1)
* complexity since it merely sets a "cancel" bit
* to on and does not remove the Event from the
* scheduler's event list. When the event expires,
* the scheduler checks this cancel bit and, if set,
* does not execute the event.
*/
void cancel (void)
{
if (m_impl != 0) {
m_impl->cancel ();
}
}
/**
* Return true if the event is in RUNNING state.
* Return false otherwise.
*
* An Event is created in RUNNING state and switches
* to NON_RUNNING state upon one of:
* - cancel bit is set to on
* - Event execution is completed.
* It is important to note that an event is in RUNNING
* state while being executed.
*/
bool is_running (void)
{
if (m_impl != 0 && m_impl->is_running ()) {
return true;
} else {
return false;
}
}
private:
friend class SchedulerHeap;
friend class SchedulerList;
friend class SchedulerMap;
void set_tag (void *tag)
{
return m_impl->set_tag (tag);
}
void *get_tag (void) const
{
return m_impl->get_tag ();
}
EventImpl *m_impl;
};
}; // namespace yans
#endif /* EVENT_H */

454
src/simulator/event.tcc Normal file
View File

@@ -0,0 +1,454 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef EVENT_TCC
#define EVENT_TCC
#include "event.h"
#include "event-impl.h"
/**
* yans namespace
*/
namespace yans {
/**
* \defgroup make_event make_event
*
* Every make_event template function returns a newly-created Event
* which holds a pointer to a special subclass of the EventImpl
* base class. Each of these subclasses holds information about which
* function or method to call and which parameters must be forwarded
* to this function or method.
*
* Sample code is shown below:
* \include samples/main-event.cc
*/
template<typename T>
class EventMemberImpl0 : public EventImpl {
public:
typedef void (T::*F)(void);
EventMemberImpl0 (T *obj, F function)
: m_obj (obj),
m_function (function)
{}
virtual ~EventMemberImpl0 () {}
private:
virtual void notify (void) {
(m_obj->*m_function) ();
}
T* m_obj;
F m_function;
};
template<typename T, typename T1>
class EventMemberImpl1 : public EventImpl {
public:
typedef void (T::*F)(T1);
EventMemberImpl1 (T *obj, F function, T1 a1)
: m_obj (obj),
m_function (function),
m_a1 (a1)
{ }
virtual ~EventMemberImpl1 () {}
private:
virtual void notify (void) {
(m_obj->*m_function) (m_a1);
}
T* m_obj;
F m_function;
T1 m_a1;
};
template<typename T, typename T1, typename T2>
class EventMemberImpl2 : public EventImpl {
public:
typedef void (T::*F)(T1, T2);
EventMemberImpl2 (T *obj, F function, T1 a1, T2 a2)
: m_obj (obj),
m_function (function),
m_a1 (a1),
m_a2 (a2)
{ }
virtual ~EventMemberImpl2 () {}
private:
virtual void notify (void) {
(m_obj->*m_function) (m_a1, m_a2);
}
T* m_obj;
F m_function;
T1 m_a1;
T2 m_a2;
};
template<typename T, typename T1, typename T2, typename T3>
class EventMemberImpl3 : public EventImpl {
public:
typedef void (T::*F)(T1, T2, T3);
EventMemberImpl3 (T *obj, F function, T1 a1, T2 a2, T3 a3)
: m_obj (obj),
m_function (function),
m_a1 (a1),
m_a2 (a2),
m_a3 (a3)
{ }
virtual ~EventMemberImpl3 () {}
private:
virtual void notify (void) {
(m_obj->*m_function) (m_a1, m_a2, m_a3);
}
T* m_obj;
F m_function;
T1 m_a1;
T2 m_a2;
T3 m_a3;
};
template<typename T, typename T1, typename T2, typename T3, typename T4>
class EventMemberImpl4 : public EventImpl {
public:
typedef void (T::*F)(T1, T2, T3, T4);
EventMemberImpl4 (T *obj, F function, T1 a1, T2 a2, T3 a3, T4 a4)
: m_obj (obj),
m_function (function),
m_a1 (a1),
m_a2 (a2),
m_a3 (a3),
m_a4 (a4)
{ }
virtual ~EventMemberImpl4 () {}
private:
virtual void notify (void) {
(m_obj->*m_function) (m_a1, m_a2, m_a3, m_a4);
}
T* m_obj;
F m_function;
T1 m_a1;
T2 m_a2;
T3 m_a3;
T4 m_a4;
};
template<typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
class EventMemberImpl5 : public EventImpl {
public:
typedef void (T::*F)(T1, T2, T3, T4, T5);
EventMemberImpl5 (T *obj, F function, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
: m_obj (obj),
m_function (function),
m_a1 (a1),
m_a2 (a2),
m_a3 (a3),
m_a4 (a4),
m_a5 (a5)
{ }
virtual ~EventMemberImpl5 () {}
private:
virtual void notify (void) {
(m_obj->*m_function) (m_a1, m_a2, m_a3, m_a4, m_a5);
}
T* m_obj;
F m_function;
T1 m_a1;
T2 m_a2;
T3 m_a3;
T4 m_a4;
T5 m_a5;
};
/**
* \ingroup make_event
* \param f class method member pointer
* \param t class instance
* \return a wrapper Event
* Build Events for class method members which take no arguments.
*/
template<typename T>
Event make_event(void (T::*f) (void), T* t) {
return Event (new EventMemberImpl0<T>(t, f));
}
/**
* \ingroup make_event
* \param f class method member pointer
* \param t class instance
* \param a1 first argument to pass to the target method when the event expires
* \return a wrapper Event
* Build Events for class method members which take only one argument
*/
template<typename T, typename T1>
Event make_event(void (T::*f) (T1), T* t, T1 a1) {
return Event (new EventMemberImpl1<T, T1>(t, f, a1));
}
/**
* \ingroup make_event
* \param f class method member pointer
* \param t class instance
* \param a1 first argument to pass to the target method when the event expires
* \param a2 second argument to pass to the target method when the event expires
* \return a wrapper Event
* Build Events for class method members which take two arguments
*/
template<typename T, typename T1, typename T2>
Event make_event(void (T::*f) (T1, T2), T* t, T1 a1, T2 a2) {
return Event (new EventMemberImpl2<T, T1, T2>(t, f, a1, a2));
}
/**
* \ingroup make_event
* \param f class method member pointer
* \param t class instance
* \param a1 first argument to pass to the target method when the event expires
* \param a2 second argument to pass to the target method when the event expires
* \param a3 third argument to pass to the target method when the event expires
* \return a wrapper Event
* Build Events for class method members which take three arguments
*/
template<typename T, typename T1, typename T2, typename T3>
Event make_event(void (T::*f) (T1, T2, T3), T* t, T1 a1, T2 a2, T3 a3) {
return Event (new EventMemberImpl3<T, T1, T2, T3>(t, f, a1, a2, a3));
}
/**
* \ingroup make_event
* \param f class method member pointer
* \param t class instance
* \param a1 first argument to pass to the target method when the event expires
* \param a2 second argument to pass to the target method when the event expires
* \param a3 third argument to pass to the target method when the event expires
* \param a4 fourth argument to pass to the target method when the event expires
* \return a wrapper Event
* Build Events for class method members which take four arguments
*/
template<typename T, typename T1, typename T2, typename T3, typename T4>
Event make_event(void (T::*f) (T1, T2, T3, T4), T* t, T1 a1, T2 a2, T3 a3, T4 a4) {
return Event (new EventMemberImpl4<T, T1, T2, T3, T4>(t, f, a1, a2, a3, a4));
}
/**
* \ingroup make_event
* \param f class method member pointer
* \param t class instance
* \param a1 first argument to pass to the target method when the event expires
* \param a2 second argument to pass to the target method when the event expires
* \param a3 third argument to pass to the target method when the event expires
* \param a4 fourth argument to pass to the target method when the event expires
* \param a5 fifth argument to pass to the target method when the event expires
* \return a wrapper Event
* Build Events for class method members which take five arguments.
*/
template<typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
Event make_event(void (T::*f) (T1, T2, T3, T4, T5), T* t, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) {
return Event (new EventMemberImpl5<T, T1, T2, T3, T4, T5>(t, f, a1, a2, a3, a4, a5));
}
template<typename T1>
class EventFunctionImpl1 : public EventImpl {
public:
typedef void (*F)(T1);
EventFunctionImpl1 (F function, T1 a1)
: m_function (function),
m_a1 (a1)
{ }
virtual ~EventFunctionImpl1 () {}
private:
virtual void notify (void) {
(*m_function) (m_a1);
}
F m_function;
T1 m_a1;
};
template<typename T1, typename T2>
class EventFunctionImpl2 : public EventImpl {
public:
typedef void (*F)(T1, T2);
EventFunctionImpl2 (F function, T1 a1, T2 a2)
: m_function (function),
m_a1 (a1),
m_a2 (a2)
{ }
virtual ~EventFunctionImpl2 () {}
private:
virtual void notify (void) {
(*m_function) (m_a1, m_a2);
}
F m_function;
T1 m_a1;
T2 m_a2;
};
template<typename T1, typename T2, typename T3>
class EventFunctionImpl3 : public EventImpl {
public:
typedef void (*F)(T1, T2, T3);
EventFunctionImpl3 (F function, T1 a1, T2 a2, T3 a3)
: m_function (function),
m_a1 (a1),
m_a2 (a2),
m_a3 (a3)
{ }
virtual ~EventFunctionImpl3 () {}
private:
virtual void notify (void) {
(*m_function) (m_a1, m_a2, m_a3);
}
F m_function;
T1 m_a1;
T2 m_a2;
T3 m_a3;
};
template<typename T1, typename T2, typename T3, typename T4>
class EventFunctionImpl4 : public EventImpl {
public:
typedef void (*F)(T1, T2, T3, T4);
EventFunctionImpl4 (F function, T1 a1, T2 a2, T3 a3, T4 a4)
: m_function (function),
m_a1 (a1),
m_a2 (a2),
m_a3 (a3),
m_a4 (a4)
{ }
virtual ~EventFunctionImpl4 () {}
private:
virtual void notify (void) {
(*m_function) (m_a1, m_a2, m_a3, m_a4);
}
F m_function;
T1 m_a1;
T2 m_a2;
T3 m_a3;
T4 m_a4;
};
template<typename T1, typename T2, typename T3, typename T4, typename T5>
class EventFunctionImpl5 : public EventImpl {
public:
typedef void (*F)(T1, T2, T3, T4, T5);
EventFunctionImpl5 (F function, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
: m_function (function),
m_a1 (a1),
m_a2 (a2),
m_a3 (a3),
m_a4 (a4),
m_a5 (a5)
{ }
virtual ~EventFunctionImpl5 () {}
private:
virtual void notify (void) {
(*m_function) (m_a1, m_a2, m_a3, m_a4, m_a5);
}
F m_function;
T1 m_a1;
T2 m_a2;
T3 m_a3;
T4 m_a4;
T5 m_a5;
};
/**
* \ingroup make_event
* \param f function pointer
* \return a wrapper Event
* Build Events for function pointers which take no arguments
*/
Event make_event(void (*f) (void));
/**
* \ingroup make_event
* \param f function pointer
* \param a1 first argument to pass to the target function when the event expires
* \return a wrapper Event
* Build Events for function pointers which take one argument
*/
template<typename T1>
Event make_event(void (*f) (T1), T1 a1) {
return Event (new EventFunctionImpl1<T1>(f, a1));
}
/**
* \ingroup make_event
* \param f function pointer
* \param a1 first argument to pass to the target function when the event expires
* \param a2 second argument to pass to the target function when the event expires
* \return a wrapper Event
* Build Events for function pointers which take two argument
*/
template<typename T1, typename T2>
Event make_event(void (*f) (T1, T2), T1 a1, T2 a2) {
return Event (new EventFunctionImpl2<T1, T2>(f, a1, a2));
}
/**
* \ingroup make_event
* \param f function pointer
* \param a1 first argument to pass to the target function when the event expires
* \param a2 second argument to pass to the target function when the event expires
* \param a3 third argument to pass to the target function when the event expires
* \return a wrapper Event
* Build Events for function pointers which take three argument
*/
template<typename T1, typename T2, typename T3>
Event make_event(void (*f) (T1, T2, T3), T1 a1, T2 a2, T3 a3) {
return Event (new EventFunctionImpl3<T1, T2, T3>(f, a1, a2, a3));
}
/**
* \ingroup make_event
* \param f function pointer
* \param a1 first argument to pass to the target function when the event expires
* \param a2 second argument to pass to the target function when the event expires
* \param a3 third argument to pass to the target function when the event expires
* \param a4 fourth argument to pass to the target function when the event expires
* \return a wrapper Event
* Build Events for function pointers which take four argument
*/
template<typename T1, typename T2, typename T3, typename T4>
Event make_event(void (*f) (T1, T2, T3, T4), T1 a1, T2 a2, T3 a3, T4 a4) {
return Event (new EventFunctionImpl4<T1, T2, T3, T4>(f, a1, a2, a3, a4));
}
/**
* \ingroup make_event
* \param f function pointer
* \param a1 first argument to pass to the target function when the event expires
* \param a2 second argument to pass to the target function when the event expires
* \param a3 third argument to pass to the target function when the event expires
* \param a4 fourth argument to pass to the target function when the event expires
* \param a5 fifth argument to pass to the target function when the event expires
* \return a wrapper Event
* Build Events for function pointers which take five argument
*/
template<typename T1, typename T2, typename T3, typename T4, typename T5>
Event make_event(void (*f) (T1, T2, T3, T4, T5), T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) {
return Event (new EventFunctionImpl5<T1, T2, T3, T4, T5>(f, a1, a2, a3, a4, a5));
}
}; // namespace yans
#endif /* EVENT_TCC */

View File

@@ -0,0 +1,243 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* Copyright (c) 2005 Mathieu Lacage
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*
* This code started as a c++ translation of a java-based code written in 2005
* to implement a heap sort. Which explains the Copyright Mathieu Lacage at the
* top of this file.
*
* What is smart about this code ?
* - it does not use the index 0 in the array to avoid having to convert
* C-style array indexes (which start at zero) and heap-style indexes
* (which start at 1). This is why _all_ indexes start at 1, and that
* the index of the root is 1.
* - It uses a slightly non-standard while loop for top-down heapify
* to move one if statement out of the loop.
*/
#include "scheduler-heap.h"
#include "event.h"
#include <cassert>
#define noTRACE_HEAP 1
#ifdef TRACE_HEAP
#include <iostream>
# define TRACE(x) \
std::cout << "HEAP TRACE " << x << std::endl;
#else /* TRACE_HEAP */
# define TRACE(format,...)
#endif /* TRACE_HEAP */
namespace yans {
SchedulerHeap::SchedulerHeap ()
{
// we purposedly waste an item at the start of
// the array to make sure the indexes in the
// array start at one.
Scheduler::EventKey empty_key = {0,0};
m_heap.push_back (std::make_pair ((Event )0, empty_key));
}
SchedulerHeap::~SchedulerHeap ()
{}
void
SchedulerHeap::store_in_event (Event ev, uint32_t index) const
{
ev.set_tag ((void *)index);
}
uint32_t
SchedulerHeap::get_from_event (Event const ev) const
{
return (uint32_t)ev.get_tag ();
}
uint32_t
SchedulerHeap::parent (uint32_t id) const
{
return id / 2;
}
uint32_t
SchedulerHeap::sibling (uint32_t id) const
{
return id + 1;
}
uint32_t
SchedulerHeap::left_child (uint32_t id) const
{
return id * 2;
}
uint32_t
SchedulerHeap::right_child (uint32_t id) const
{
return id * 2 + 1;
}
uint32_t
SchedulerHeap::root (void) const
{
return 1;
}
bool
SchedulerHeap::is_root (uint32_t id) const
{
return (id == root ())?true:false;
}
uint32_t
SchedulerHeap::last (void) const
{
return m_heap.size () - 1;
}
bool
SchedulerHeap::is_bottom (uint32_t id) const
{
return (id >= m_heap.size ())?true:false;
}
void
SchedulerHeap::exch (uint32_t a, uint32_t b)
{
assert (b < m_heap.size () && a < m_heap.size ());
TRACE ("exch " << a << ", " << b);
#if 1
std::swap (m_heap[a].second, m_heap[b].second);
std::swap (m_heap[a].first.m_impl, m_heap[b].first.m_impl);
#else
std::pair<Event , Scheduler::EventKey> tmp (m_heap[a]);
m_heap[a] = m_heap[b];
m_heap[b] = tmp;
#endif
store_in_event (m_heap[a].first, a);
store_in_event (m_heap[b].first, b);
}
bool
SchedulerHeap::is_less (uint32_t a, uint32_t b)
{
Scheduler::EventKeyCompare compare;
return compare (m_heap[a].second, m_heap[b].second);
}
uint32_t
SchedulerHeap::smallest (uint32_t a, uint32_t b)
{
return is_less (a,b)?a:b;
}
bool
SchedulerHeap::is_empty (void) const
{
return (m_heap.size () == 1)?true:false;
}
void
SchedulerHeap::bottom_up (void)
{
uint32_t index = last ();
while (!is_root (index) &&
is_less (index, parent (index))) {
exch(index, parent (index));
index = parent (index);
}
}
void
SchedulerHeap::top_down (void)
{
uint32_t index = root ();
uint32_t right = right_child (index);
while (!is_bottom (right)) {
uint32_t left = left_child (index);
uint32_t tmp = smallest (left, right);
if (is_less (index, tmp)) {
return;
}
exch (index, tmp);
index = tmp;
right = right_child (index);
}
if (is_bottom (index)) {
return;
}
assert (!is_bottom (index));
uint32_t left = left_child (index);
if (is_bottom (left)) {
return;
}
if (is_less (index, left)) {
return;
}
exch (index, left);
}
Event
SchedulerHeap::insert (Event event, Scheduler::EventKey key)
{
m_heap.push_back (std::make_pair (event, key));
store_in_event (event, last ());
bottom_up ();
return event;
}
Event
SchedulerHeap::peek_next (void) const
{
assert (!is_empty ());
return m_heap[root ()].first;
}
Scheduler::EventKey
SchedulerHeap::peek_next_key (void) const
{
assert (!is_empty ());
return m_heap[root ()].second;
}
void
SchedulerHeap::remove_next (void)
{
assert (!is_empty ());
exch (root (), last ());
m_heap.pop_back ();
top_down ();
}
Scheduler::EventKey
SchedulerHeap::remove (Event const ev)
{
uint32_t i = get_from_event (ev);
EventKey key = m_heap[i].second;
exch (i, last ());
m_heap.pop_back ();
top_down ();
return key;
}
}; // namespace yans

View File

@@ -0,0 +1,71 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef SCHEDULER_HEAP_H
#define SCHEDULER_HEAP_H
#include "scheduler.h"
#include <stdint.h>
#include <vector>
namespace yans {
class Event;
class EventHolder;
class SchedulerHeap : public Scheduler {
public:
SchedulerHeap ();
virtual ~SchedulerHeap ();
virtual Event insert (Event event, Scheduler::EventKey key);
virtual bool is_empty (void) const;
virtual Event peek_next (void) const;
virtual Scheduler::EventKey peek_next_key (void) const;
virtual void remove_next (void);
virtual Scheduler::EventKey remove (Event const ev);
private:
typedef std::vector<std::pair<Event, Scheduler::EventKey> > BinaryHeap;
inline void store_in_event (Event ev, uint32_t index) const;
uint32_t get_from_event (Event const ev) const;
inline uint32_t parent (uint32_t id) const;
uint32_t sibling (uint32_t id) const;
inline uint32_t left_child (uint32_t id) const;
inline uint32_t right_child (uint32_t id) const;
inline uint32_t root (void) const;
uint32_t last (void) const;
inline bool is_root (uint32_t id) const;
inline bool is_bottom (uint32_t id) const;
inline bool is_less (uint32_t a, uint32_t b);
inline uint32_t smallest (uint32_t a, uint32_t b);
inline void exch (uint32_t a, uint32_t b);
void bottom_up (void);
void top_down (void);
BinaryHeap m_heap;
};
}; // namespace yans
#endif /* SCHEDULER_HEAP_H */

View File

@@ -0,0 +1,107 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "scheduler-list.h"
#include "event.h"
#include <utility>
#include <cassert>
namespace yans {
SchedulerList::SchedulerList ()
{}
SchedulerList::~SchedulerList ()
{}
/* !! WARNING !!
* This is a very nasty piece of code but it really should work
* with pretty much any implementation of a std::list.
* it relies on the fact that a std::list<>::iterator has a single
* member variable, a pointer.
*/
void
SchedulerList::store_in_event (Event ev, EventsI i)
{
assert (sizeof (i) <= sizeof (Event));
void *tag;
strncpy ((char *)&(tag), (char *)&i, sizeof (void *));
ev.set_tag (tag);
}
SchedulerList::EventsI
SchedulerList::get_from_event (Event const ev)
{
SchedulerList::EventsI i;
assert (sizeof (i) <= sizeof (Event));
void *tag = ev.get_tag ();
strncpy ((char *)&i, (char *)&(tag), sizeof (void *));
return i;
}
Event
SchedulerList::insert (Event event, Scheduler::EventKey key)
{
Scheduler::EventKeyCompare compare;
for (EventsI i = m_events.begin (); i != m_events.end (); i++) {
if (compare (key, i->second)) {
m_events.insert (i, std::make_pair (event, key));
store_in_event (event, i);
return event;
}
}
m_events.push_back (std::make_pair (event, key));
store_in_event (event, --(m_events.end ()));
return event;
}
bool
SchedulerList::is_empty (void) const
{
return m_events.empty ();
}
Event
SchedulerList::peek_next (void) const
{
assert (!is_empty ());
return m_events.front ().first;
}
Scheduler::EventKey
SchedulerList::peek_next_key (void) const
{
assert (!is_empty ());
return m_events.front ().second;
}
void
SchedulerList::remove_next (void)
{
m_events.pop_front ();
}
Scheduler::EventKey
SchedulerList::remove (Event const ev)
{
EventsI i = get_from_event (ev);
EventKey key = (*i).second;
m_events.erase (get_from_event (ev));
return key;
}
}; // namespace yans

View File

@@ -0,0 +1,57 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef SCHEDULER_LIST_H
#define SCHEDULER_LIST_H
#include "scheduler.h"
#include <list>
#include <utility>
#include <stdint.h>
namespace yans {
class Event;
class SchedulerList : public Scheduler {
public:
SchedulerList ();
virtual ~SchedulerList ();
virtual Event insert (Event event, EventKey key);
virtual bool is_empty (void) const;
virtual Event peek_next (void) const;
virtual Scheduler::EventKey peek_next_key (void) const;
virtual void remove_next (void);
virtual Scheduler::EventKey remove (Event const ev);
private:
typedef std::list<std::pair<Event, EventKey> > Events;
typedef std::list<std::pair<Event, EventKey> >::iterator EventsI;
void store_in_event (Event ev, EventsI i);
EventsI get_from_event (Event const ev);
Events m_events;
};
}; // namespace yans
#endif /* SCHEDULER_LIST_H */

View File

@@ -0,0 +1,112 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
* The idea to use a std c++ map came from GTNetS
*/
#include "scheduler-map.h"
#include "event.h"
#include <cassert>
#define noTRACE_MAP 1
#ifdef TRACE_MAP
#include <iostream>
# define TRACE(x) \
std::cout << "MAP TRACE " << x << std::endl;
#else /* TRACE_MAP */
# define TRACE(format,...)
#endif /* TRACE_MAP */
namespace yans {
SchedulerMap::SchedulerMap ()
{}
SchedulerMap::~SchedulerMap ()
{}
void
SchedulerMap::store_in_event (Event ev, EventMapI i) const
{
void *tag;
memcpy (&(tag), &i, sizeof (tag));
ev.set_tag (tag);
}
SchedulerMap::EventMapI
SchedulerMap::get_from_event (Event const ev) const
{
EventMapI i;
void *tag = ev.get_tag ();
memcpy (&i, &(tag), sizeof (i));
return i;
}
Event
SchedulerMap::insert (Event event, Scheduler::EventKey key)
{
std::pair<EventMapI,bool> result = m_list.insert (std::make_pair (key, event));
assert (result.second);
store_in_event (event, result.first);
return event;
}
bool
SchedulerMap::is_empty (void) const
{
return m_list.empty ();
}
Event
SchedulerMap::peek_next (void) const
{
assert (!is_empty ());
EventMapCI i = m_list.begin ();
assert (i != m_list.end ());
return (*i).second;
}
Scheduler::EventKey
SchedulerMap::peek_next_key (void) const
{
assert (!is_empty ());
EventMapCI i = m_list.begin ();
assert (i != m_list.end ());
return (*i).first;
}
void
SchedulerMap::remove_next (void)
{
assert (!is_empty ());
m_list.erase (m_list.begin ());
}
Scheduler::EventKey
SchedulerMap::remove (Event const ev)
{
assert (!is_empty ());
EventMapI i = get_from_event (ev);
EventKey key = (*i).first;
m_list.erase (i);
return key;
}
}; // namespace yans

View File

@@ -0,0 +1,59 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef SCHEDULER_MAP_H
#define SCHEDULER_MAP_H
#include "scheduler.h"
#include <stdint.h>
#include <map>
#include <utility>
namespace yans {
class SchedulerMap : public Scheduler {
public:
SchedulerMap ();
virtual ~SchedulerMap ();
virtual Event insert (Event event, Scheduler::EventKey key);
virtual bool is_empty (void) const;
virtual Event peek_next (void) const;
virtual Scheduler::EventKey peek_next_key (void) const;
virtual void remove_next (void);
virtual Scheduler::EventKey remove (Event const ev);
private:
typedef std::map<Scheduler::EventKey, Event, Scheduler::EventKeyCompare> EventMap;
typedef std::map<Scheduler::EventKey, Event, Scheduler::EventKeyCompare>::iterator EventMapI;
typedef std::map<Scheduler::EventKey, Event, Scheduler::EventKeyCompare>::const_iterator EventMapCI;
void store_in_event (Event ev, EventMapI i) const;
EventMapI get_from_event (Event const ev) const;
EventMap m_list;
uint32_t m_uid;
};
}; // namespace yans
#endif /* SCHEDULER_MAP_H */

View File

@@ -0,0 +1,46 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "scheduler.h"
#include <cassert>
yans::Scheduler::~Scheduler ()
{}
/* Note the invariants which this function must provide:
* - irreflexibility: f (x,x) is false)
* - antisymmetry: f(x,y) = !f(y,x)
* - transitivity: f(x,y) and f(y,z) => f(x,z)
*/
bool
yans::Scheduler::EventKeyCompare::operator () (struct EventKey a, struct EventKey b)
{
assert (a.m_uid != b.m_uid);
if (a.m_time < b.m_time) {
return true;
} else if (a.m_time == b.m_time && a.m_uid < b.m_uid) {
return true;
} else {
return false;
}
}

54
src/simulator/scheduler.h Normal file
View File

@@ -0,0 +1,54 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef SCHEDULER_H
#define SCHEDULER_H
#include <stdint.h>
#include "event.h"
namespace yans {
class Scheduler {
public:
struct EventKey {
uint64_t m_time;
uint32_t m_uid;
};
class EventKeyCompare {
public:
bool operator () (struct EventKey a, struct EventKey b);
};
virtual ~Scheduler () = 0;
virtual Event insert (Event event, EventKey key) = 0;
virtual bool is_empty (void) const = 0;
virtual Event peek_next (void) const = 0;
virtual EventKey peek_next_key (void) const = 0;
virtual void remove_next (void) = 0;
virtual EventKey remove (Event const ev) = 0;
};
}; // namespace yans
#endif /* SCHEDULER_H */

544
src/simulator/simulator.cc Normal file
View File

@@ -0,0 +1,544 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005,2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "simulator.h"
#include "scheduler.h"
#include "event.h"
#include "event.tcc"
#include "yans/system-semaphore.h"
#include <math.h>
#include <cassert>
#include <fstream>
#include <list>
#include <vector>
#include <iostream>
#define noTRACE_SIMU 1
#ifdef TRACE_SIMU
#include <iostream>
# define TRACE(x) \
std::cout << "SIMU TRACE " << Simulator::now_s () << " " << x << std::endl;
# define TRACE_S(x) \
std::cout << "SIMU TRACE " << x << std::endl;
#else /* TRACE_SIMU */
# define TRACE(format,...)
# define TRACE_S(format,...)
#endif /* TRACE_SIMU */
namespace yans {
class ParallelSimulatorQueuePrivate {
public:
ParallelSimulatorQueuePrivate (SimulatorPrivate *priv);
~ParallelSimulatorQueuePrivate ();
void set_queue (ParallelSimulatorQueue *queue);
void schedule_abs_us (Event ev, uint64_t at);
void send_null_message (void);
private:
void remove_event (Event ev);
uint32_t m_n;
SimulatorPrivate *m_simulator;
ParallelSimulatorQueue *m_queue;
};
class SimulatorPrivate {
public:
SimulatorPrivate (Scheduler *events);
~SimulatorPrivate ();
void enable_log_to (char const *filename);
void add_queue (ParallelSimulatorQueuePrivate *queue);
void notify_queue_not_empty (void);
void notify_queue_empty (void);
void wait_until_no_queue_empty (void);
bool is_parallel (void);
bool is_finished (void) const;
uint64_t next_us (void) const;
void run_serial (void);
void run_parallel (void);
void stop (void);
void stop_at_us (uint64_t at);
Event schedule_rel_us (Event event, uint64_t delta);
Event schedule_rel_s (Event event, double delta);
Event schedule_abs_us (Event event, uint64_t time);
Event schedule_abs_s (Event event, double time);
Event remove (Event const ev);
uint64_t now_us (void);
double now_s (void);
void schedule_now (Event event);
void schedule_destroy (Event event);
private:
void process_one_event (void);
typedef std::list<std::pair<Event,uint32_t> > Events;
typedef std::vector<ParallelSimulatorQueuePrivate *> Queues;
typedef std::vector<ParallelSimulatorQueuePrivate *>::iterator QueuesI;
Events m_destroy;
uint64_t m_stop_at;
bool m_stop;
Scheduler *m_events;
uint32_t m_uid;
uint32_t m_current_uid;
uint64_t m_current_us;
std::ofstream m_log;
std::ifstream m_input_log;
bool m_log_enable;
uint32_t m_n_full_queues;
uint32_t m_n_queues;
SystemSemaphore *m_all_queues;
Queues m_queues;
};
ParallelSimulatorQueuePrivate::ParallelSimulatorQueuePrivate (SimulatorPrivate *simulator)
: m_simulator (simulator)
{}
ParallelSimulatorQueuePrivate::~ParallelSimulatorQueuePrivate ()
{}
void
ParallelSimulatorQueuePrivate::schedule_abs_us (Event ev, uint64_t at)
{
m_n++;
if (m_n == 1) {
m_simulator->notify_queue_not_empty ();
}
m_simulator->schedule_abs_us (make_event (&ParallelSimulatorQueuePrivate::remove_event, this, ev), at);
}
void
ParallelSimulatorQueuePrivate::remove_event (Event ev)
{
m_n--;
if (m_n == 0) {
m_simulator->notify_queue_empty ();
}
ev ();
}
void
ParallelSimulatorQueuePrivate::set_queue (ParallelSimulatorQueue *queue)
{
m_queue = queue;
}
void
ParallelSimulatorQueuePrivate::send_null_message (void)
{
m_queue->send_null_message ();
}
SimulatorPrivate::SimulatorPrivate (Scheduler *events)
{
m_stop = false;
m_stop_at = 0;
m_events = events;
m_uid = 0;
m_log_enable = false;
m_current_us = 0;
m_all_queues = new SystemSemaphore (0);
m_n_queues = 0;
m_n_full_queues = 0;
}
SimulatorPrivate::~SimulatorPrivate ()
{
while (!m_destroy.empty ()) {
Event ev = m_destroy.front ().first;
m_destroy.pop_front ();
TRACE ("handle destroy " << ev);
ev ();
}
delete m_events;
m_events = (Scheduler *)0xdeadbeaf;
delete m_all_queues;
m_queues.erase (m_queues.begin (), m_queues.end ());
}
bool
SimulatorPrivate::is_parallel (void)
{
return (m_n_queues > 0);
}
void
SimulatorPrivate::enable_log_to (char const *filename)
{
m_log.open (filename);
m_log_enable = true;
}
void
SimulatorPrivate::notify_queue_not_empty (void)
{
m_n_full_queues++;
if (m_n_full_queues == m_n_queues) {
m_all_queues->post ();
}
}
void
SimulatorPrivate::notify_queue_empty (void)
{
m_n_full_queues--;
}
void
SimulatorPrivate::wait_until_no_queue_empty (void)
{
while (m_n_full_queues < m_n_queues) {
m_all_queues->wait ();
}
}
void
SimulatorPrivate::add_queue (ParallelSimulatorQueuePrivate *queue)
{
m_n_queues++;
m_queues.push_back (queue);
}
void
SimulatorPrivate::process_one_event (void)
{
Event next_ev = m_events->peek_next ();
Scheduler::EventKey next_key = m_events->peek_next_key ();
m_events->remove_next ();
TRACE ("handle " << next_ev);
m_current_us = next_key.m_time;
m_current_uid = next_key.m_uid;
if (m_log_enable) {
m_log << "e "<<next_key.m_uid << " " << next_key.m_time << std::endl;
}
next_ev ();
}
bool
SimulatorPrivate::is_finished (void) const
{
return m_events->is_empty ();
}
uint64_t
SimulatorPrivate::next_us (void) const
{
assert (!m_events->is_empty ());
Scheduler::EventKey next_key = m_events->peek_next_key ();
return next_key.m_time;
}
void
SimulatorPrivate::run_serial (void)
{
while (!m_events->is_empty () && !m_stop &&
(m_stop_at == 0 || m_stop_at > next_us ())) {
process_one_event ();
}
m_log.close ();
}
void
SimulatorPrivate::run_parallel (void)
{
TRACE ("run parallel");
while (!m_stop &&
(m_stop_at == 0 || m_stop_at >= next_us ())) {
TRACE ("send null messages");
for (QueuesI i = m_queues.begin (); i != m_queues.end (); i++) {
(*i)->send_null_message ();
}
TRACE ("sent null messages");
wait_until_no_queue_empty ();
TRACE ("no queue empty");
process_one_event();
TRACE ("processed event");
}
m_log.close ();
TRACE ("done run parallel");
}
void
SimulatorPrivate::stop (void)
{
m_stop = true;
}
void
SimulatorPrivate::stop_at_us (uint64_t at)
{
m_stop_at = at;
}
Event
SimulatorPrivate::schedule_rel_us (Event event, uint64_t delta)
{
uint64_t current = now_us ();
return schedule_abs_us (event, current+delta);
}
Event
SimulatorPrivate::schedule_abs_us (Event event, uint64_t time)
{
assert (time >= now_us ());
Scheduler::EventKey key = {time, m_uid};
if (m_log_enable) {
m_log << "i "<<m_current_uid<<" "<<now_us ()<<" "
<<m_uid<<" "<<time << std::endl;
}
m_uid++;
return m_events->insert (event, key);
}
uint64_t
SimulatorPrivate::now_us (void)
{
return m_current_us;
}
Event
SimulatorPrivate::schedule_rel_s (Event event, double delta)
{
int64_t delta_us = (int64_t)(delta * 1000000.0);
uint64_t us = now_us () + delta_us;
return schedule_abs_us (event, us);
}
Event
SimulatorPrivate::schedule_abs_s (Event event, double time)
{
int64_t us = (int64_t)(time * 1000000.0);
assert (us >= 0);
return schedule_abs_us (event, (uint64_t)us);
}
double
SimulatorPrivate::now_s (void)
{
double us = m_current_us;
us /= 1000000;
return us;
}
void
SimulatorPrivate::schedule_now (Event event)
{
schedule_abs_us (event, now_us ());
}
void
SimulatorPrivate::schedule_destroy (Event event)
{
m_destroy.push_back (std::make_pair (event, m_uid));
if (m_log_enable) {
m_log << "id " << m_current_uid << " " << now_us () << " "
<< m_uid << std::endl;
}
m_uid++;
}
Event
SimulatorPrivate::remove (Event const ev)
{
Scheduler::EventKey key = m_events->remove (ev);
if (m_log_enable) {
m_log << "r " << m_current_uid << " " << now_us () << " "
<< key.m_uid << " " << key.m_time << std::endl;
}
return Event (ev);
}
}; // namespace yans
#include "scheduler-list.h"
#include "scheduler-heap.h"
#include "scheduler-map.h"
namespace yans {
SimulatorPrivate *Simulator::m_priv = 0;
Simulator::ListType Simulator::m_list_type = LINKED_LIST;
void Simulator::set_linked_list (void)
{
m_list_type = LINKED_LIST;
}
void Simulator::set_binary_heap (void)
{
m_list_type = BINARY_HEAP;
}
void Simulator::set_std_map (void)
{
m_list_type = STD_MAP;
}
void Simulator::enable_log_to (char const *filename)
{
get_priv ()->enable_log_to (filename);
}
SimulatorPrivate *
Simulator::get_priv (void)
{
if (m_priv == 0) {
Scheduler *events;
switch (m_list_type) {
case LINKED_LIST:
events = new SchedulerList ();
break;
case BINARY_HEAP:
events = new SchedulerHeap ();
break;
case STD_MAP:
events = new SchedulerMap ();
break;
default: // not reached
events = 0;
assert (false);
break;
}
m_priv = new SimulatorPrivate (events);
}
TRACE_S ("priv " << m_priv);
return m_priv;
}
void
Simulator::destroy (void)
{
delete m_priv;
m_priv = 0;
}
void
Simulator::add_parallel_queue (ParallelSimulatorQueue *queue)
{
ParallelSimulatorQueuePrivate *priv = new ParallelSimulatorQueuePrivate (get_priv ());
priv->set_queue (queue);
queue->set_priv (priv);
return get_priv ()->add_queue (priv);
}
bool
Simulator::is_finished (void)
{
return get_priv ()->is_finished ();
}
uint64_t
Simulator::next_us (void)
{
return get_priv ()->next_us ();
}
void
Simulator::run (void)
{
if (get_priv ()->is_parallel ()) {
get_priv ()->run_parallel ();
} else {
get_priv ()->run_serial ();
}
}
void
Simulator::stop (void)
{
TRACE ("stop");
get_priv ()->stop ();
}
void
Simulator::stop_at_us (uint64_t at)
{
get_priv ()->stop_at_us (at);
}
Event
Simulator::schedule_rel_us (uint64_t delta, Event event)
{
TRACE ("insert " << event << " in " << delta << "us");
return get_priv ()->schedule_rel_us (event, delta);
}
Event
Simulator::schedule_abs_us (uint64_t time, Event event)
{
TRACE ("insert " << event << " at " << time << "us");
return get_priv ()->schedule_abs_us (event, time);
}
uint64_t
Simulator::now_us (void)
{
return get_priv ()->now_us ();
}
Event
Simulator::schedule_rel_s (double delta, Event event)
{
TRACE ("insert " << event << " in " << delta << "s");
return get_priv ()->schedule_rel_s (event, delta);
}
Event
Simulator::schedule_abs_s (double time, Event event)
{
TRACE ("insert " << event << " at " << time << "s");
return get_priv ()->schedule_abs_s (event, time);
}
double
Simulator::now_s (void)
{
return get_priv ()->now_s ();
}
void
Simulator::schedule_now (Event event)
{
TRACE ("insert later " << event);
return get_priv ()->schedule_now (event);
}
void
Simulator::schedule_destroy (Event event)
{
TRACE ("insert at destroy " << event);
return get_priv ()->schedule_destroy (event);
}
Event
Simulator::remove (Event const ev)
{
return get_priv ()->remove (ev);
}
}; // namespace yans
namespace yans {
ParallelSimulatorQueue::ParallelSimulatorQueue ()
{}
ParallelSimulatorQueue::~ParallelSimulatorQueue ()
{
delete m_priv;
}
void
ParallelSimulatorQueue::schedule_abs_us (uint64_t at, Event ev)
{
m_priv->schedule_abs_us (ev, at);
}
void
ParallelSimulatorQueue::set_priv (ParallelSimulatorQueuePrivate *priv)
{
m_priv = priv;
}
};

Some files were not shown because too many files have changed in this diff Show More