import from yans
This commit is contained in:
595
src/common/buffer.cc
Normal file
595
src/common/buffer.cc
Normal 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
690
src/common/buffer.h
Normal 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 */
|
||||
84
src/common/callback-logger.h
Normal file
84
src/common/callback-logger.h
Normal 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 */
|
||||
63
src/common/chunk-constant-data.cc
Normal file
63
src/common/chunk-constant-data.cc
Normal 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
|
||||
47
src/common/chunk-constant-data.h
Normal file
47
src/common/chunk-constant-data.h
Normal 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 */
|
||||
94
src/common/chunk-llc-snap.cc
Normal file
94
src/common/chunk-llc-snap.cc
Normal 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
|
||||
55
src/common/chunk-llc-snap.h
Normal file
55
src/common/chunk-llc-snap.h
Normal 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
49
src/common/chunk-utils.cc
Normal 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
38
src/common/chunk-utils.h
Normal 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
65
src/common/chunk.cc
Normal 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
89
src/common/chunk.h
Normal 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 */
|
||||
70
src/common/count-ptr-holder.tcc
Normal file
70
src/common/count-ptr-holder.tcc
Normal 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
119
src/common/data-writer.cc
Normal 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
44
src/common/data-writer.h
Normal 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 */
|
||||
58
src/common/f-traced-variable.tcc
Normal file
58
src/common/f-traced-variable.tcc
Normal 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
203
src/common/ipv4-address.cc
Normal 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
107
src/common/ipv4-address.h
Normal 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 */
|
||||
82
src/common/ipv4-network-interface.cc
Normal file
82
src/common/ipv4-network-interface.cc
Normal 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
|
||||
59
src/common/ipv4-network-interface.h
Normal file
59
src/common/ipv4-network-interface.h
Normal 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 */
|
||||
89
src/common/llc-snap-encapsulation.cc
Normal file
89
src/common/llc-snap-encapsulation.cc
Normal 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
|
||||
52
src/common/llc-snap-encapsulation.h
Normal file
52
src/common/llc-snap-encapsulation.h
Normal 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 */
|
||||
46
src/common/mac-address-factory.cc
Normal file
46
src/common/mac-address-factory.cc
Normal 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
|
||||
40
src/common/mac-address-factory.h
Normal file
40
src/common/mac-address-factory.h
Normal 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
187
src/common/mac-address.cc
Normal 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
72
src/common/mac-address.h
Normal 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 */
|
||||
96
src/common/mac-network-interface.cc
Normal file
96
src/common/mac-network-interface.cc
Normal 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
|
||||
68
src/common/mac-network-interface.h
Normal file
68
src/common/mac-network-interface.h
Normal 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 */
|
||||
42
src/common/packet-logger.cc
Normal file
42
src/common/packet-logger.cc
Normal 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
|
||||
|
||||
53
src/common/packet-logger.h
Normal file
53
src/common/packet-logger.h
Normal 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
127
src/common/packet.cc
Normal 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
90
src/common/packet.h
Normal 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
99
src/common/pcap-writer.cc
Normal 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
73
src/common/pcap-writer.h
Normal 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 */
|
||||
94
src/common/population-analysis.cc
Normal file
94
src/common/population-analysis.cc
Normal 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
|
||||
55
src/common/population-analysis.h
Normal file
55
src/common/population-analysis.h
Normal 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
47
src/common/position.cc
Normal 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
38
src/common/position.h
Normal 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 */
|
||||
137
src/common/random-uniform-mrg32k3a.cc
Normal file
137
src/common/random-uniform-mrg32k3a.cc
Normal 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
|
||||
|
||||
57
src/common/random-uniform.h
Normal file
57
src/common/random-uniform.h
Normal 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
139
src/common/ref-ptr.h
Normal 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
336
src/common/rng-mrg32k3a.cc
Normal 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
65
src/common/rng-mrg32k3a.h
Normal 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 */
|
||||
61
src/common/seed-generator-mrg32k3a.cc
Normal file
61
src/common/seed-generator-mrg32k3a.cc
Normal 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
|
||||
40
src/common/seed-generator.h
Normal file
40
src/common/seed-generator.h
Normal 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
32
src/common/sgi-hashmap.h
Normal 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 */
|
||||
237
src/common/si-traced-variable.tcc
Normal file
237
src/common/si-traced-variable.tcc
Normal 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 */
|
||||
46
src/common/static-position.cc
Normal file
46
src/common/static-position.cc
Normal 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
|
||||
43
src/common/static-position.h
Normal file
43
src/common/static-position.h
Normal 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 */
|
||||
68
src/common/static-speed-position.cc
Normal file
68
src/common/static-speed-position.cc
Normal 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
|
||||
51
src/common/static-speed-position.h
Normal file
51
src/common/static-speed-position.h
Normal 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
322
src/common/tags.cc
Normal 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 = ©->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
292
src/common/tags.h
Normal 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
77
src/common/timeout.cc
Normal 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
52
src/common/timeout.h
Normal 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 */
|
||||
197
src/common/trace-container.cc
Normal file
197
src/common/trace-container.cc
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
299
src/common/trace-container.h
Normal file
299
src/common/trace-container.h
Normal 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 */
|
||||
68
src/common/trace-stream-test.cc
Normal file
68
src/common/trace-stream-test.cc
Normal 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
73
src/common/trace-stream.h
Normal 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 */
|
||||
252
src/common/traced-variable-test.cc
Normal file
252
src/common/traced-variable-test.cc
Normal 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
|
||||
|
||||
|
||||
239
src/common/ui-traced-variable.tcc
Normal file
239
src/common/ui-traced-variable.tcc
Normal 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
293
src/common/utils.cc
Normal 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
43
src/common/utils.h
Normal 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
197
src/core/callback-test.cc
Normal 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
518
src/core/callback.h
Normal 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
58
src/core/exec-commands.h
Normal 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 */
|
||||
120
src/core/reference-list-test.cc
Normal file
120
src/core/reference-list-test.cc
Normal 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
117
src/core/reference-list.h
Normal 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
44
src/core/system-file.h
Normal 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
42
src/core/system-mutex.h
Normal 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 */
|
||||
44
src/core/system-semaphore.h
Normal file
44
src/core/system-semaphore.h
Normal 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
41
src/core/system-thread.h
Normal 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
107
src/core/test.cc
Normal 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
75
src/core/test.h
Normal 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 */
|
||||
516
src/core/unix-exec-commands.cc
Normal file
516
src/core/unix-exec-commands.cc
Normal 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 */
|
||||
|
||||
|
||||
119
src/core/unix-system-file.cc
Normal file
119
src/core/unix-system-file.cc
Normal 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
|
||||
82
src/core/unix-system-mutex.cc
Normal file
82
src/core/unix-system-mutex.cc
Normal 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
|
||||
114
src/core/unix-system-semaphore.cc
Normal file
114
src/core/unix-system-semaphore.cc
Normal 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
|
||||
69
src/core/unix-system-thread.cc
Normal file
69
src/core/unix-system-thread.cc
Normal 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
|
||||
|
||||
74
src/core/unix-wall-clock-ms.cc
Normal file
74
src/core/unix-wall-clock-ms.cc
Normal 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
40
src/core/wall-clock-ms.h
Normal 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 */
|
||||
86
src/core/win32-system-file.cc
Normal file
86
src/core/win32-system-file.cc
Normal 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
|
||||
78
src/core/win32-system-mutex.cc
Normal file
78
src/core/win32-system-mutex.cc
Normal 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
|
||||
103
src/core/win32-system-semaphore.cc
Normal file
103
src/core/win32-system-semaphore.cc
Normal 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
|
||||
66
src/core/win32-system-thread.cc
Normal file
66
src/core/win32-system-thread.cc
Normal 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
|
||||
|
||||
65
src/core/win32-wall-clock-ms.cc
Normal file
65
src/core/win32-wall-clock-ms.cc
Normal 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
|
||||
67
src/simulator/event-impl.cc
Normal file
67
src/simulator/event-impl.cc
Normal 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
|
||||
49
src/simulator/event-impl.h
Normal file
49
src/simulator/event-impl.h
Normal 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 */
|
||||
110
src/simulator/event-tcc-test.cc
Normal file
110
src/simulator/event-tcc-test.cc
Normal 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 */
|
||||
47
src/simulator/event-tcc.cc
Normal file
47
src/simulator/event-tcc.cc
Normal 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
140
src/simulator/event.h
Normal 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
454
src/simulator/event.tcc
Normal 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 */
|
||||
243
src/simulator/scheduler-heap.cc
Normal file
243
src/simulator/scheduler-heap.cc
Normal 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
|
||||
71
src/simulator/scheduler-heap.h
Normal file
71
src/simulator/scheduler-heap.h
Normal 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 */
|
||||
107
src/simulator/scheduler-list.cc
Normal file
107
src/simulator/scheduler-list.cc
Normal 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
|
||||
57
src/simulator/scheduler-list.h
Normal file
57
src/simulator/scheduler-list.h
Normal 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 */
|
||||
112
src/simulator/scheduler-map.cc
Normal file
112
src/simulator/scheduler-map.cc
Normal 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
|
||||
59
src/simulator/scheduler-map.h
Normal file
59
src/simulator/scheduler-map.h
Normal 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 */
|
||||
46
src/simulator/scheduler.cc
Normal file
46
src/simulator/scheduler.cc
Normal 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
54
src/simulator/scheduler.h
Normal 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
544
src/simulator/simulator.cc
Normal 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
Reference in New Issue
Block a user