diff --git a/SConstruct b/SConstruct index 210ebca0b..44f168c6b 100644 --- a/SConstruct +++ b/SConstruct @@ -411,6 +411,12 @@ sample_trace.add_dep('common') sample_trace.set_executable() sample_trace.add_source('main-trace.cc') +sample_query_interface = build.Ns3Module('sample-query-interface', 'samples') +ns3.add(sample_query_interface) +sample_query_interface.add_dep('common') +sample_query_interface.set_executable() +sample_query_interface.add_source('main-query-interface.cc') + sample_simu = build.Ns3Module('sample-simulator', 'samples') ns3.add(sample_simu) sample_simu.set_executable() diff --git a/samples/main-query-interface.cc b/samples/main-query-interface.cc new file mode 100644 index 000000000..20da36ff3 --- /dev/null +++ b/samples/main-query-interface.cc @@ -0,0 +1,280 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007 University of Washington + * Authors: Tom Henderson, Craig Dowell + * + * 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 + */ + +#include "ns3/debug.h" +#include "ns3/object.h" +#include "ns3/component-manager.h" + +using namespace ns3; + +// +// This sample file shows examples of how to use QueryInterface. +// +// QueryInterface is a templated method of class Object, defined in +// src/core/object.h. ns-3 objects that derive from class Object +// can have QueryInterface invoked on them. +// +// QueryInterface is a type-safe way to ask an object, at run-time, +// "Do you support the interface identified by the given InterfaceId?" +// It avoids deprecated techniques of having to downcast pointers to +// an object to ask questions about its type. One or more interfaces +// may be associated with a given object. +// +// QueryInterface is of most use when working with base class +// pointers of objects that may be subclassed. For instance, +// one may have a pointer to a Node, but not know whether it has +// an IPv4 stack. Another example might be to determine whether +// a Node has an EnergyModel, to which calls to decrement energy +// from the node's battery might be made. +// + + +// +// Object is the base class for ns-3 node-related objects used at +// the public API. Object provides reference counting implementations +// and the QueryInterface. +// +// A common design paradigm for an ns-3 node object, such as a Queue, +// is that we provide an abstract base class that inherits from +// Object. This class is assigned an interface ID (iid) and +// contains the basic API for objects in this class and subclasses. +// This base class is specialized to provide implementations of +// the object in question (such as a DropTailQueue). +// +// The design pattern commonly used is known as the "non-virtual +// public interface" pattern, whereby the public API for this +// object is a set of public non-virtual functions that forward +// to private virtual functions. The forwarding functions can +// impose pre- and post-conditions on the forwarding call at +// the base class level. +// +// We'll call this base class "AnInterface" in the example below. +// +// +class AnInterface : public Object +{ +public: + static const InterfaceId iid; + void methodA (void); +private: + virtual void domethodA (void) = 0; +}; + +void +AnInterface::methodA (void) +{ + // pre-dispatch asserts + NS_DEBUG_UNCOND("AnInterface pre-condition::methodA"); + domethodA (); + NS_DEBUG_UNCOND("AnInterface post-condition::methodA\n"); + // post-dispatch asserts +} + +// +// The below assignment assigns the InterfaceId of the class AnInterface, +// and declares that the parent iid is that of class Object. +// +const InterfaceId AnInterface::iid = MakeInterfaceId ("AnInterface", Object::iid); + +// +// AnImplementation is an implementation of the abstract base class +// defined above. It provides implementation for the virtual functions +// in the base class. It defines one ClassId for each constructor, +// and can also provide an interface itself (in this example, +// a methodImpl is available) +// +class AnImplementation : public AnInterface +{ +public: + static const InterfaceId iid; + static const ClassId cid; + + AnImplementation (); + void methodImpl (void); +private: + virtual void domethodA (void); +}; + +void +AnImplementation::methodImpl (void) +{ + NS_DEBUG_UNCOND("AnImplementation::methodImpl\n"); +} + + +AnImplementation::AnImplementation (void) +{ + // enable our interface + SetInterfaceId (AnImplementation::iid); +} + +void +AnImplementation::domethodA () +{ + NS_DEBUG_UNCOND("AnImplementation::domethodA"); +} + +// +// The below assignment assigns the InterfaceId of the class AnImplementation, +// and declares that the parent iid is that of class Object. +// +const InterfaceId AnImplementation::iid = + MakeInterfaceId ("AnImplementation", AnInterface::iid); + +// +// The next few lines are used by the component manager. They +// state that the component manager can create a new object +// AnImplementation and return an interface corresponding to +// the AnImplementation iid. +// +const ClassId AnImplementation::cid = + MakeClassId + ("AnImplementation", AnImplementation::iid); + + +// +// Extending interfaces +// ================== +// What if AnInterface doesn't provide enough API for your +// object type? +// - if you aren't concerned about backward compatibility and +// don't mind recompiling, you just add new methods to AnInterface +// and recompile. +// - if you want to address backward compatibiliy, or allow part +// of the system to use the old interface, you have to do more. +// You have to declare a new interface with the new functionality. +// + +class AnExtendedInterface : public AnInterface +{ +public: + static const InterfaceId iid; + void methodB (void); +private: + virtual void domethodB (void) = 0; +}; + +const InterfaceId AnExtendedInterface::iid = + MakeInterfaceId ("AnExtendedInterface", AnInterface::iid); + +// +// Then you need provide an implementation for the virtual +// methods. If you are providing a new implementation for +// everything, the answer is straightforward +// + +class ANewImplementation : public AnExtendedInterface +{ +public: + static const InterfaceId iid; + static const ClassId cid; + + ANewImplementation (); + void methodImpl (void); +private: + virtual void domethodA (void) { /* new-implementation-behavior (); */} + virtual void domethodB (void) { /* new-implementation-behavior (); */} +}; + +ANewImplementation::ANewImplementation (void) +{ + // enable our interface + SetInterfaceId (ANewImplementation::iid); +} + +void +ANewImplementation::methodImpl (void) +{ + NS_DEBUG_UNCOND("ANewImplementation::methodImpl\n"); +} + +const InterfaceId ANewImplementation::iid = + MakeInterfaceId ("ANewImplementation", AnExtendedInterface::iid); + +// +// If you want to extend an existing implementation, you can use +// the existing class to instantiate an implementation of its +// methods (hasa) and do the following if you can use stuff from +// the existing class. +// + +class AnExtendedImplementation : public AnExtendedInterface +{ +public: + static const InterfaceId iid; + static const ClassId cid; + + AnExtendedImplementation (); + void methodImpl (void) { /* pImpl->methodImpl (); */ } + void methodExtendedImpl (void); +private: + virtual void domethodA (void) { /* new-implementation-behavior (); */} + virtual void domethodB (void) { /* new-implementation-behavior (); */} + Ptr pImpl; +}; + +AnExtendedImplementation::AnExtendedImplementation (void) +{ + pImpl = Create (); + SetInterfaceId (AnExtendedImplementation::iid); +} + +void +AnExtendedImplementation::methodExtendedImpl (void) +{ + NS_DEBUG_UNCOND("AnExtendedImplementation::methodExtendedImpl\n"); +} + +const InterfaceId AnExtendedImplementation::iid = + MakeInterfaceId ("AnExtendedImplementation", AnExtendedInterface::iid); + +// +// Inheriting from an existing implementation (isa) and an extended +// interface is tricky, because of the diamond multiple inheritance +// problem. If the pImpl method above is not desirable, it may +// be that the implementation extension could be aggregated. +// +// The extension will not have access to the base implementation, +// so this design pattern may be more appropriate if the extension +// is very modular (e.g., add an EnergyModel to a wireless interface) +// +// EXAMPLE NOT YET PROVIDED + +int main (int argc, char *argv[]) +{ + + Ptr aBase = ComponentManager::Create + (AnImplementation::cid, AnInterface::iid); + NS_ASSERT (aBase != 0); + + aBase->methodA (); + //aBase->methodImpl (); // XXX won't compile, aBase not right ptr type + + Ptr aBaseImplPtr = + aBase-> QueryInterface (AnImplementation::iid); + aBaseImplPtr->methodImpl (); + aBaseImplPtr->methodA(); + + // Test symmetric property of QueryInterface + Ptr aBase2 = + aBaseImplPtr-> QueryInterface (AnInterface::iid); + aBase2->methodA (); + + return 0; +} diff --git a/src/applications/wscript b/src/applications/wscript index e6f9582bd..85fa0513b 100644 --- a/src/applications/wscript +++ b/src/applications/wscript @@ -1,6 +1,10 @@ ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- +def configure(conf): + conf.env.append_value('NS3_MODULES', 'ns3-applications') + + def build(bld): obj = bld.create_obj('cpp', 'shlib') obj.name = 'ns3-applications' diff --git a/src/common/packet.cc b/src/common/packet.cc index 459cdae39..4acc7fe0e 100644 --- a/src/common/packet.cc +++ b/src/common/packet.cc @@ -119,3 +119,58 @@ Packet::Print (std::ostream &os) const {} }; // namespace ns3 + + + +#ifdef RUN_SELF_TESTS + +#include "ns3/test.h" +#include + +namespace ns3 { + +class PacketTest: public Test { +public: + virtual bool RunTests (void); + PacketTest (); +}; + + +PacketTest::PacketTest () + : Test ("Packet") {} + + +bool +PacketTest::RunTests (void) +{ + bool ok = true; + + Packet pkt1 (reinterpret_cast ("hello"), 5); + Packet pkt2 (reinterpret_cast (" world"), 6); + Packet packet; + packet.AddAtEnd (pkt1); + packet.AddAtEnd (pkt2); + + if (packet.GetSize () != 11) + { + Failure () << "expected size 11, got " << packet.GetSize () << std::endl; + ok = false; + } + + std::string msg = std::string (reinterpret_cast(packet.PeekData ()), + packet.GetSize ()); + if (msg != "hello world") + { + Failure () << "expected size 'hello world', got " << msg << std::endl; + ok = false; + } + + return ok; +} + + +static PacketTest gPacketTest; + +}; // namespace ns3 + +#endif /* RUN_SELF_TESTS */ diff --git a/src/common/wscript b/src/common/wscript index b62e204b2..65753d930 100644 --- a/src/common/wscript +++ b/src/common/wscript @@ -1,5 +1,7 @@ ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- +def configure(conf): + conf.env.append_value('NS3_MODULES', 'ns3-common') def build(bld): common = bld.create_obj('cpp', 'shlib') diff --git a/src/core/wscript b/src/core/wscript index 222539171..ce9795c8e 100644 --- a/src/core/wscript +++ b/src/core/wscript @@ -3,6 +3,8 @@ import sys def configure(conf): + conf.env.append_value('NS3_MODULES', 'ns3-core') + e = conf.create_header_configurator() e.mandatory = False e.name = 'stdlib.h' diff --git a/src/devices/p2p/wscript b/src/devices/p2p/wscript index 73b27d061..c4c0f7952 100644 --- a/src/devices/p2p/wscript +++ b/src/devices/p2p/wscript @@ -1,6 +1,10 @@ ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- +def configure(conf): + conf.env.append_value('NS3_MODULES', 'ns3-p2p') + + def build(bld): p2p = bld.create_obj('cpp', 'shlib') p2p.name = 'ns3-p2p' diff --git a/src/internet-node/wscript b/src/internet-node/wscript index bf3236159..806861fd3 100644 --- a/src/internet-node/wscript +++ b/src/internet-node/wscript @@ -1,6 +1,10 @@ ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- +def configure(conf): + conf.env.append_value('NS3_MODULES', 'ns3-internet-node') + + def build(bld): obj = bld.create_obj('cpp', 'shlib') obj.name = 'ns3-internet-node' diff --git a/src/node/wscript b/src/node/wscript index b39d6fa1e..c608945c7 100644 --- a/src/node/wscript +++ b/src/node/wscript @@ -1,5 +1,8 @@ ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- +def configure(conf): + conf.env.append_value('NS3_MODULES', 'ns3-node') + def build(bld): node = bld.create_obj('cpp', 'shlib') diff --git a/src/simulator/cairo-wideint.c b/src/simulator/cairo-wideint.c index 354183fe7..957de8e51 100644 --- a/src/simulator/cairo-wideint.c +++ b/src/simulator/cairo-wideint.c @@ -658,7 +658,7 @@ _cairo_int128_divrem (cairo_int128_t num, cairo_int128_t den) * Compute a 32 bit quotient and 64 bit remainder of a 96 bit unsigned * dividend and 64 bit divisor. If the quotient doesn't fit into 32 * bits then the returned remainder is equal to the divisor, and the - * qoutient is the largest representable 64 bit integer. It is an + * quotient is the largest representable 64 bit integer. It is an * error to call this function with the high 32 bits of @num being * non-zero. */ cairo_uquorem64_t @@ -776,7 +776,7 @@ _cairo_int_96by64_32x64_divrem (cairo_int128_t num, cairo_int64_t den) { int num_neg = _cairo_int128_negative (num); int den_neg = _cairo_int64_negative (den); - cairo_int64_t nonneg_den = den; + cairo_uint64_t nonneg_den; cairo_uquorem64_t uqr; cairo_quorem64_t qr; @@ -784,9 +784,11 @@ _cairo_int_96by64_32x64_divrem (cairo_int128_t num, cairo_int64_t den) num = _cairo_int128_negate (num); if (den_neg) nonneg_den = _cairo_int64_negate (den); + else + nonneg_den = den; uqr = _cairo_uint_96by64_32x64_divrem (num, nonneg_den); - if (_cairo_uint64_eq (uqr.rem, nonneg_den)) { + if (_cairo_uint64_eq (uqr.rem, _cairo_int64_to_uint64 (nonneg_den))) { /* bail on overflow. */ qr.quo = _cairo_uint32s_to_uint64 (0x7FFFFFFF, -1U);; qr.rem = den; diff --git a/src/simulator/wscript b/src/simulator/wscript index b18ec3802..3f038d813 100644 --- a/src/simulator/wscript +++ b/src/simulator/wscript @@ -13,6 +13,8 @@ def set_options(opt): def configure(conf): + conf.env.append_value('NS3_MODULES', 'ns3-simulator') + if Params.g_options.high_precision_as_double: conf.add_define('USE_HIGH_PRECISION_DOUBLE', 1) conf.env['USE_HIGH_PRECISION_DOUBLE'] = 1 diff --git a/src/wscript b/src/wscript index ae5647577..2e2349f10 100644 --- a/src/wscript +++ b/src/wscript @@ -29,6 +29,7 @@ def configure(conf): blddir = os.path.abspath(os.path.join(conf.m_blddir, conf.env.variant())) for module in all_modules: + conf.sub_config(module) conf.env.append_value('NS3_MODULE_PATH', os.path.join(blddir, 'src', module)) diff --git a/utils/wscript b/utils/wscript index cc0755526..27c509c01 100644 --- a/utils/wscript +++ b/utils/wscript @@ -1,23 +1,23 @@ ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- -import sys -import Params def build(bld): + env = bld.env_of_name('default') def create_ns_prog(name, source): obj = bld.create_obj('cpp', 'program') obj.target = name - obj.uselib_local = "ns3-core ns3-common ns3-simulator" obj.source = source return obj unit_tests = create_ns_prog('run-tests', 'run-tests.cc') unit_tests.install_var = 0 # do not install unit_tests.unit_test = 1 # runs on 'waf check' + ## link unit test program with all ns3 modules + unit_tests.uselib_local = env['NS3_MODULES'] - #if sys.platform != 'win32': obj = create_ns_prog('bench-simulator', 'bench-simulator.cc') + obj.uselib_local = "ns3-core ns3-common ns3-simulator" + obj = create_ns_prog('replay-simulation', 'replay-simulation.cc') - ## bench-packets requires missing header files - #obj = create_ns_prog('bench-packets', 'bench-packets.cc') + obj.uselib_local = "ns3-core ns3-common ns3-simulator" diff --git a/wscript b/wscript index 75bca783c..779c3c136 100644 --- a/wscript +++ b/wscript @@ -79,6 +79,7 @@ def configure(conf): conf.setenv(variant_name) variant_env.append_value('CXXDEFINES', 'RUN_SELF_TESTS') + variant_env.append_value('CXXFLAGS', ['-Wall', '-Werror']) if 'debug' in Params.g_options.debug_level.lower(): variant_env.append_value('CXXDEFINES', 'NS3_DEBUG_ENABLE') variant_env.append_value('CXXDEFINES', 'NS3_ASSERT_ENABLE')