Models.cpp
// Models.cpp
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2009
@import "Ceda/cxPython/cxPython.h"
@import "CedaExamples/lxOperation/Shapes.h"
@import "Ceda/cxObject/Object.h"
@import "Ceda/cxObject/IObjectVisitor.h"
@import "Ceda/cxObject/WCSpace.h"
#include "Ceda/cxUtils/TracerUtils.h"
/*
todo
----
[Daniel Paull]
I am running Python scripts as part of the recalculation of dependant nodes (an agent
actually). It seems that data source read barriers are not invoked when accessing
datasource model members (a feature you added recently).
For the moment I have modified GetPyObjectFromReflectedModelVariable() in
WrapModelStructVar.cpp to call ceda::DataSourceReadBarrier( data, datasource );
at the start of the function, though I am not sure that this is the right way to
do this, nor if it is the only place I need to invoke read barriers from.
For example, I think some methods in WrapVectorStructVar.cpp will need to invoke
read barriers when elements of a vector are accessed.
I'm not sure about write barriers - they seem to be being invoked (at least in
the vector append case), but I could be wrong.
[DBL]
Write barriers : Note however that I currently don't support dynamic arrays, maps
or sets. Also Python doesn't yet support move operations on mvectors.
[DBL]
I'm in a quandary as far as read barriers are concerned. Either it's fully automatic,
but potentially inefficient, or else there's some explicit syntax to declare read
access to a data model member.
If the read barriers are called automatically then there are going to be examples
such as where millions of redundant dependency graph edges are created because a
vector is accessed in a loop. To check for redundant edges would seem to require
iteration through the linked list of edges.
I was wondering about a 'touch' function that allows the programmer explicit
control over read barrier loops...
Eg
void bar(const xvector<int>& v) { ... }
void foo(MyDataSource* ds)
{
ds->v.touch(); // declare read access to member v.
// We don't want to invoke read barrier in the loop!
for (int i=0 ; i < ds->v.size() ; ++i)
{
foo(ds->v[i]);
}
// We want to be able to access v as an xvector<int>
bar(ds->v);
}
I'm wondering whether thread local storage can store a bool to indicate a mode for
whether or not to automatically invoke the read barriers. The idea is to get
the convenience most of the time, but have the ability to optimise as required.
Note that access to thread local storage is very fast (making use of a few mov
instructions that access the FS CPU register).
[Daniel Paull]
I have not been able to find an example of a model with a string in it! Looking at
examples/documentation I see "xstring", "vector<int8>" and "string8" used. The
only one that xcpp seems to accept is string8, so I've used that.
The problem I have is that I get an exception thrown in the destructor of my class
when the string is destroyed. It trips at _CrtIsValidHeapPointer() when trying
to free m_buffer from ceda::VectorOfByte.
Consider the follow snippet. As written, the problem arises when the model mixin
is destructed. If the "Filename" member is commented out and the anonymous
mixin uncommented, there is no problem. Is there an obvious problem here (like
I'm not supposed to use string8 in a model)? I am using Visual Studio 2008,
just in case that causes a problem.
model
{
string8 Filename;
}
mixin
[
{
ceda::xstring Filename;
const ceda::xstring& GetFilename() const
{
return Filename;
}
void SetFilename( const ceda::xstring& f )
{
Filename = f;
}
}
...
]
*/
///////////////////////////////////////////////////////////////////////////////////////////////////
/*
Models 1
--------
Generated output:
Models example 1
{
x = X(Y(0),0,
x.i8 = 0
x.i16 = 0
x.i32 = 0
x.i64 = 0
x = X(Y(1000),1,16,32,64,16,32,64,32,64,0,hello)
x.i8 = 8
x.i16 = 16
x.i32 = 32
x.i64 = 64
}
*/
namespace Models1
{
$enum+ EColour
{
red = 0x10, -green, blue
};
$model+ Y
{
ceda::int32 i32;
};
$struct+ X <<multiline>> isa ceda::IObject :
model
{
Y y;
bool b;
ceda::int8 i8;
ceda::int16 i16;
ceda::int32 i32;
ceda::int64 i64;
ceda::uint8 ui8;
ceda::uint16 ui16;
ceda::uint32 ui32;
ceda::uint64 ui64;
ceda::float32 f32;
ceda::float64 f64;
EColour c;
assignable<ceda::string8> s1;
ceda::string8 s2;
}
{
};
void Run()
{
ceda::TraceGroup g("Models example 1");
ceda::CSpaceCreator cspace;
ceda::CSpaceLock lock;
X x;
PyRun_SimpleString(
@strx
(
x = rootnamespace.Models1.X()
print 'x = ' + `x`
print 'x.i8 = ' + `x.i8`
print 'x.i16 = ' + `x.i16`
print 'x.i32 = ' + `x.i32`
print 'x.i64 = ' + `x.i64`
print 'type(x) = ' + `type(x)`
print 'type(x.i8) = ' + `type(x.i8)`
print 'type(x.i16) = ' + `type(x.i16)`
print 'type(x.i32) = ' + `type(x.i32)`
print 'type(x.i64) = ' + `type(x.i64)`
print 'type(x.ui8) = ' + `type(x.ui8)`
print 'type(x.ui16) = ' + `type(x.ui16)`
print 'type(x.ui32) = ' + `type(x.ui32)`
print 'type(x.ui64) = ' + `type(x.ui64)`
print 'type(x.f32) = ' + `type(x.f32)`
print 'type(x.f64) = ' + `type(x.f64)`
print 'type(x.b) = ' + `type(x.b)`
#print 'type(x.y) = ' + `type(x.y)` # todo: crashes
print 'type(x.c) = ' + `type(x.c)`
print 'type(x.s1) = ' + `type(x.s1)`
x.y.i32 = 1000
x.b = 1
x.i8 = 8
x.i16 = 16
x.i32 = 32
x.i64 = 64
x.ui8 = 8
x.ui16 = 16
x.ui32 = 32
x.ui64 = 64
x.f32 = 32
x.f64 = 64
x.s1 = 'hello'
# These generate errors because the string is assignable, so no vector operations
#x.s1[2:2] = ' world'
#x.s1[5:6] = ''
#x.s1.extend('abc')
x.s2 = 'hi'
x.s2[2:2] = ' world'
x.s2[5:6] = ''
x.s2.extend('abc')
print 'x = ' + `x`
print 'x.i8 = ' + `x.i8`
print 'x.i16 = ' + `x.i16`
print 'x.i32 = ' + `x.i32`
print 'x.i64 = ' + `x.i64`
print 'x.s1 = ' + `x.s1`
print 'x.s2 = ' + `x.s2`
));
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
/*
Special support is provided for constructing objects of classes with models.
Consider
$model+ Point
{
int32 X;
int32 Y;
}
Three styles are supported:
1. The default constructor
Example: Point() (same as Point(0,0))
2. Passing the arguments in the same order that the members are declared in the model
Example: Point(3,7)
3. Provide values of any subset of the members in any order using a comma separate list of name=value
pairs, using the same of the member of the model.
Example: Point(X=3) (Y will have default value of 0)
Point(Y=3,X=2)
Point(Y=1) (X will have default value of 0)
*/
namespace ModelConstructors
{
/*
Generated output:
ModelConstructors
{
p = TPicture
{
Name = my picture
Author = P. Hunt
CreationDate = TDateTime(TDate(2006,June,23),TTime(0,0,0))
Colour = magenta
BoundingBox = TRect(TPoint(0,0),TPoint(800,600))
Rectangles = [TRect(TPoint(5,8),TPoint(15,12)),TRect(TPoint(8,5),TPoint(10,17))]
Circles = [TCircle(TPoint(0,0),5),TCircle(TPoint(0,0),2),TCircle(TPoint(100,0),0)]
Lines = []
}
}
*/
void Run()
{
ceda::TraceGroup g("ModelConstructors");
// Make sure lxOperation is linked!
const ceda::ReflectedClass& rc = ceda::GetReflectedClass<geom::TPoint>();
ceda::CSpaceCreator cspace;
ceda::CSpaceLock lock;
PyRun_SimpleString(
@strx
(
s = rootnamespace.geom
dt = rootnamespace.dt
p = s.TPicture(
Name = "my picture",
Author = "P. Hunt",
Colour = s.EColour.magenta,
CreationDate = dt.TDateTime( Date = dt.TDate(2006,dt.TMonth.June,23) ),
BoundingBox = s.TRect( s.TPoint(0,0), s.TPoint(800,600) ),
Rectangles =
[
s.TRect( s.TPoint(X=5,Y=8), s.TPoint(15,12) ),
s.TRect( s.TPoint(Y=5,X=8), s.TPoint(10,17) )
],
Circles =
[
s.TCircle( s.TPoint(), 5 ),
s.TCircle( R=2 ),
s.TCircle( C=s.TPoint(X=100) )
]
)
print 'p = ' + `p`
));
}
}
namespace ModelConstructors2
{
$model+ Point
{
ceda::int32 X;
ceda::int32 Y;
};
$model+ Y
{
ceda::int32 i32;
ceda::string8 s;
ceda::xvector<ceda::int32> L;
};
$struct+ X isa ceda::IObject :
model
{
Y y;
ceda::int32 i32;
ceda::float32 f32;
ceda::xvector<Y> Ys;
ceda::xvector< ceda::ptr<ceda::IObject> > M;
}
{
};
/*
Generated output:
ModelConstructors
{
ns.Point() = Point(0,0)
ns.Point(X=10) = Point(10,0)
ns.Point(Y=10) = Point(0,10)
ns.Point(X=1,Y=2) = Point(1,2)
ns.Point(Y=1,X=2) = Point(2,1)
y = Y(10,x,[1,2,3])
x = X(Y(10,x,[1,2,3]),10,3.14,[Y(1,w,[1,2]),Y(2,e,[])],[ModelConstructors::X:01D7CEF8])
x.M[0].self = X(Y(10,x,[1,2,3]),1,2,[Y(10,x,[1,2,3])],[])
z = X(Y(0,,[0,2,4,6,8]),25,0,[],[ModelConstructors::X:01D907B8,ModelConstructors::X:01D90838])
z.M[0].self = X(Y(0,,[]),1000,0,[],[])
z.M[1].self = X(Y(0,hello,[]),2000,0,[],[])
}
*/
void Run()
{
ceda::TraceGroup g("ModelConstructors2");
ceda::CSpaceCreator cspace;
ceda::CSpaceLock lock;
PyRun_SimpleString(
@strx
(
ns = rootnamespace.ModelConstructors2
print 'ns.Point() = ' + `ns.Point()`
print 'ns.Point(X=10) = ' + `ns.Point(X=10)`
print 'ns.Point(Y=10) = ' + `ns.Point(Y=10)`
print 'ns.Point(X=1,Y=2) = ' + `ns.Point(X=1,Y=2)`
print 'ns.Point(Y=1,X=2) = ' + `ns.Point(Y=1,X=2)`
y = ns.Y(10,"x",[1,2,3])
print 'y = ' + `y`
x = ns.X(
ns.Y(10,"x",[1,2,3]),
10,
3.14,
[
ns.Y(1,"w",[1,2]),
ns.Y(2,"e",[])
],
[
ns.X.create(y,1,2.0,[y],[])
]
)
print 'x = ' + `x`
print 'x.M[0].self = ' + `x.M[0].self`
z = ns.X(
y = ns.Y(L=[2*i for i in range(5)]),
i32 = 25,
M =
[
ns.X.create(i32=1000),
ns.X.create(i32=2000,y=ns.Y(s="hello")),
]
)
print 'z = ' + `z`
print 'z.M[0].self = ' + `z.M[0].self`
print 'z.M[1].self = ' + `z.M[1].self`
));
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
/*
VectorsInModels
---------------
Vectors in models example
{
x = X([])
Demonstration of various read only functions
x.L = = [1,2,3,4,5,6,7,8,9]
bool(x.L) = True
str(x.L) = ' = [1,2,3,4,5,6,7,8,9]'
repr(x.L) = ' = [1,2,3,4,5,6,7,8,9]'
len(x.L) = 9
min(x.L) = 1
max(x.L) = 9
x.L.index(2) = 1
x.L.index(9) = 8
x.L.index(15) = -1
x.L.count(4) = 1
x.L.count(20) = 0
x.L*2 = = [1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9]
x.L[-1] = 9
3 in x.L = True
10 in x.L = False
3 not in x.L = False
10 not in x.L = True
x.L+[100,200] = = [1,2,3,4,5,6,7,8,9,100,200]
x.L[3] = 4
x.L[1:4] = = [2,3,4]
Demonstration of various mutative functions
x.L.extend([10,20,30,40,50])
x.L = = [10,20,30,40,50]
x.L.append(100)
x.L = = [10,20,30,40,50,100]
x.L.insert(0,-1)
x.L = = [-1,10,20,30,40,50,100]
x.L[0] = 4
x.L = = [4,10,20,30,40,50,100]
del x.L[1]
x.L = = [4,20,30,40,50,100]
del x.L[1:3]
x.L = = [4,40,50,100]
x.L[1:1] = [1,2,3,4,5]
x.L = = [4,1,2,3,4,5,40,50,100]
x.L.remove(2)
x.L = = [4,1,3,4,5,40,50,100]
x.L.pop()
x.L = = [4,1,3,4,5,40,50]
x.L.pop(1)
x.L = = [4,3,4,5,40,50]
x = X([4,3,4,5,40,50])
}
*/
namespace VectorsInModels
{
$struct+ X isa ceda::IObject :
model
{
ceda::xvector<ceda::int32> L;
}
{
};
// todo: In Python 2.7, calling
// dir(x.L)
// in Demonstration of various read only functions
// causes a crash (but worked in Python 2.4.4)
void Run()
{
ceda::TraceGroup g("Vectors in models example");
ceda::CSpaceCreator cspace;
ceda::CSpaceLock lock;
PyRun_SimpleString(
@strx
(
x = rootnamespace.VectorsInModels.X()
print 'x = ' + `x`
print 'Demonstration of various read only functions'
x.L.extend([1,2,3,4,5,6,7,8,9])
@for (e in
[
x.L,
bool(x.L),
str(x.L),
repr(x.L),
len(x.L),
min(x.L),
max(x.L),
x.L.index(2),
x.L.index(9),
x.L.index(15),
x.L.count(4),
x.L.count(20),
x.L*2,
x.L[-1],
3 in x.L,
10 in x.L,
3 not in x.L,
10 not in x.L,
x.L+[100,200],
x.L[3],
x.L[1:4]
])
{
print @str( e = ) + `e`
}
print '\nDemonstration of various mutative functions'
del x.L[0:len(x.L)]
@for (e in
[
x.L.extend([10,20,30,40,50]),
x.L.append(100),
x.L.insert(0,-1),
x.L[0] = 4,
del x.L[1],
del x.L[1:3],
x.L[1:1] = [1,2,3,4,5],
x.L.remove(2),
x.L.pop(),
x.L.pop(1)
])
{
print @str( e)
e
print @str( x.L = ) + `x.L`
}
#assignment to vector not supported
#x.L = []
#deletion of vector not supported
#del x.L
#sort not supported
#x.L.sort()
#reverse not supported
#x.L.reverse()
print 'x = ' + `x`
));
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
/*
ArraysInModels
--------------
Arrays in models example
{
x = X([0,0,0,0,0,0,0],[Point(0,0),Point(0,0),Point(0,0)])
Demonstration of various read only functions
x.A = = [1,2,3,2,11,5,5]
bool(x.A) = True
str(x.A) = ' = [1,2,3,2,11,5,5]'
repr(x.A) = ' = [1,2,3,2,11,5,5]'
len(x.A) = 7
min(x.A) = 1
max(x.A) = 11
x.A.index(2) = 1
x.A.index(11) = 4
x.A.index(15) = -1
x.A.count(5) = 2
x.A.count(20) = 0
x.A*2 = = [1,2,3,2,11,5,5,1,2,3,2,11,5,5]
x.A[-1] = 5
3 in x.A = True
10 in x.A = False
3 not in x.A = False
10 not in x.A = True
x.A+[100,200] = = [1,2,3,2,11,5,5,100,200]
x.A[3] = 2
x.A[1:4] = = [2,3,2]
Demonstration of various mutative functions
x.A[0] = 4
x.A = = [4,2,3,2,11,5,5]
x = X([4,2,3,2,11,5,5],[Point(0,0),Point(0,0),Point(10,0)])
}
*/
namespace ArraysInModels
{
$model+ Point
{
ceda::int32 x;
ceda::int32 y;
};
$struct+ X isa ceda::IObject :
model
{
ceda::int32 A[7];
Point P[3];
}
{
};
// todo: In Python 2.7, calling
// dir(x.A)
// in Demonstration of various read only functions
// causes a crash (but worked in Python 2.4.4)
void Run()
{
ceda::TraceGroup g("Arrays in models example");
ceda::CSpaceCreator cspace;
ceda::CSpaceLock lock;
PyRun_SimpleString(
@strx
(
x = rootnamespace.ArraysInModels.X()
print 'x = ' + `x`
x.A[0] = 1
x.A[1] = 2
x.A[2] = 3
x.A[3] = 2
x.A[4] = 11
x.A[5] = 5
x.A[6] = 5
x.P[2].x = 10
print 'Demonstration of various read only functions'
@for (e in
[
x.A,
bool(x.A),
str(x.A),
repr(x.A),
len(x.A),
min(x.A),
max(x.A),
x.A.index(2),
x.A.index(11),
x.A.index(15),
x.A.count(5),
x.A.count(20),
x.A*2,
x.A[-1],
3 in x.A,
10 in x.A,
3 not in x.A,
10 not in x.A,
x.A+[100,200],
x.A[3],
x.A[1:4]
])
{
print @str( e = ) + `e`
}
print '\nDemonstration of various mutative functions'
@for (e in
[
x.A[0] = 4
])
{
print @str( e)
e
print @str( x.A = ) + `x.A`
}
# int32[7] has no member 'remove'
# x.A.remove(2)
# int32[7] has no member 'pop'
# x.A.pop()
# int32[7] has no member 'sort'
#x.A.sort()
# int32[7] has no member 'reverse'
#x.A.reverse()
# Deletion of slice of array int32[7] invalid
# del x.A[1:3]
# Assignment to slice of array int32[7] invalid
# x.A[1:1] = [1,2,3,4,5]
# Deletion of int32 variable not permitted here
# del x.A[1]
#assignment to array not supported
#x.A = []
#deletion of array not supported
#del x.A
print 'x = ' + `x`
));
}
}
/*
namespace Tbu
{
$model CvPoint2D32f
{
ceda::float32 x;
ceda::float32 y;
};
$model ChessboardCornerPoints
{
ceda::xvector<CvPoint2D32f> Points;
};
$model ChessboardCornerPointsVector
{
ceda::xvector< ChessboardCornerPoints > PointSets;
};
void Run()
{
ceda::TraceGroup g("Tbu example");
ceda::CSpaceCreator cspace;
PyRun_SimpleString(
@strx
(
cspace = ceda.GetThreadCSpace()
cspace.Lock( 1 )
points = rootnamespace.Tbu.ChessboardCornerPoints()
print `points`
print `points.Points`
pointsets = rootnamespace.Tbu.ChessboardCornerPointsVector()
print `pointsets`
print `pointsets.PointSets`
cspace.Unlock()
));
}
}
*/
///////////////////////////////////////////////////////////////////////////////////////////////////
namespace Models
{
void Run()
{
Models1::Run();
ModelConstructors::Run();
ModelConstructors2::Run();
VectorsInModels::Run();
ArraysInModels::Run();
//Tbu::Run();
}
}