pontifikas's picture

"Cannot evaluate expression because a thread is stopped at a point where garbage collection is impossible"

Why while on debug mode when I try to browse the contents of Matrix4d objects I get this error:
"Cannot evaluate expression because a thread is stopped at a point where garbage collection is impossible"
??

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
pontifikas's picture

I did some digging and it appears that the problem springs from the fact that Math data structures such as Matrix or Vector are of type "struct".
C# has a limitation for value types saying that they should not exceed 256 bytes of data when passed as arguments to functions,
unless they are passed by reference. Non compliance to that produces uninterruptable code in debug mode.
The problem should be solved if the formentioned data structures are transformed from structs to classes.

Frankly, is there a serious reason for these structs not being classes?? Because I recon that this is a serious problem.

the Fiddler's picture

Thanks for finding the cause of this issue.

Testing revealed that reference types had significant impact on the performance of the math library compared to value types. OpenTK math uses value types, but provides pass-by-reference overloads to unnecessary data copying. These overloads have the form void Op(ref left, ref right, out result) and can be significantly faster than their pass-by-value alternatives.

If possible, I would suggest modeling your math code after this pattern.

nythrix's picture

Math was widely discussed in this old thread. Structs were chosen because of the speed advantage they offer over classes. Some proposals went as far as immutable vectors/matrices but they were eventually scrapped.

Nevertheless, the math implementation is quite conformant to the .NET guidelines, I'd say. The memory limit is somewhat unfortunate but it really isn't possible to build a one size fits all purposes library.

pontifikas's picture

I really don't know if I must continue this thread (it seems you have already set the library's course) but I really want to use the functions provided by Math and I really find this problem annoying. And since you have struggled to add the ref possibility which invalidates this limitation it is a shame for this error to exist. We have to be able to debug the our application.

While operations like Mult and ovverides like "*=" work OK, in my case the problem is created by the presence of CreateTranslation (the same goes for the deprecated Translation). Maybe the Vector4 in its implementation produces this problem, I know not.

Please do sth.

the Fiddler's picture

Can you post the code that causes this issue? (or a simple test case)

pontifikas's picture

Here is my LookAt transformation function:

private void Update_LookAtParameters()
            {
                GL.MatrixMode(MatrixMode.Modelview);
                GL.LoadIdentity();
 
                OpenTK.Graphics.Glu.LookAt(LookAt.eyeX, LookAt.eyeY, LookAt.eyeZ,
                    LookAt.centerX, LookAt.centerY, LookAt.centerZ,
                    LookAt.upX, LookAt.upY, LookAt.upZ);
 
                //Store the LookAt matrix so we can use it again if we must
                LookAt.LookAtMatrix = Matrix4d.LookAt(LookAt.eyeX, LookAt.eyeY, LookAt.eyeZ,
                    LookAt.centerX, LookAt.centerY, LookAt.centerZ,
                    LookAt.upX, LookAt.upY, LookAt.upZ);
 
                GlobalTranslation = Matrix4d.Identity;
 
                ////Translate the screen
                GlobalTranslation *= Matrix4d.CreateTranslation(GlobalTranslationX, GlobalTranslationY, GlobalTranslationZ);
                GL.MultMatrix(ref GlobalTranslation);
 
                //Rotate the screen
                GlobalRotation = Matrix4d.Identity;
                GlobalRotation *= Matrix4d.CreateRotationX(GlobalRotationAngleX);
                GlobalRotation *= Matrix4d.CreateRotationY(GlobalRotationAngleY);
                GL.MultMatrix(ref GlobalRotation);
            }

In the above, if I remove all calls to Create[...] the problem disappears and all objects are viewable during debug mode.

The following is a portion where I render the axis on the screen.
Three tubes and three cones, all of them "Drawable" objects which implement a Draw
and all of them Elements of the Axis object which is "Drawable" as well.

public override void Draw()
        {
            //Check if the quadric can be drawn
            if (ElementCount != 7 || !CanDraw) return;
 
            GL.PushMatrix();
            if (IgnoreGlobalTransformations) GL.LoadIdentity();
 
            GL.MultMatrix(ref ModelviewMatrix);
 
            //XAxis
            Elements[GLObjectName + "_X_Axis_Tube"].ModelviewMatrix = Matrix4d.Identity;
            //Xaxis roatates 90 degrees around Y
            Elements[GLObjectName + "_X_Axis_Tube"].ModelviewMatrix *= Matrix4d.CreateRotationY(90.0);
            Elements[GLObjectName + "_X_Axis_Tube"].Draw();
 
            //YAxis
            Elements[GLObjectName + "_Y_Axis_Tube"].ModelviewMatrix = Matrix4d.Identity;
            //Yaxis roatates 90 degrees around X
            Elements[GLObjectName + "_Y_Axis_Tube"].ModelviewMatrix *= Matrix4d.CreateRotationX(-90.0);
            Elements[GLObjectName + "_Y_Axis_Tube"].Draw();
 
            //ZAxis
            Elements[GLObjectName + "_Z_Axis_Tube"].ModelviewMatrix = Matrix4d.Identity;
            Elements[GLObjectName + "_Z_Axis_Tube"].Draw();
 
            //XAxisCone
            Elements[GLObjectName + "_X_AxisCone"].ModelviewMatrix = Matrix4d.Identity;
            //Must perform the appropriate transformations to place the cone at the correct place
            Elements[GLObjectName + "_X_AxisCone"].ModelviewMatrix *= Matrix4d.CreateTranslation(AxisLength, 0.0, 0.0);
            Elements[GLObjectName + "_X_AxisCone"].ModelviewMatrix *= Matrix4d.CreateRotationY(90.0);
            Elements[GLObjectName + "_X_AxisCone"].Draw();
 
            //YAxisCone
            Elements[GLObjectName + "_Y_AxisCone"].ModelviewMatrix = Matrix4d.Identity;
            //Must perform the appropriate transformations to place the cone at the correct place
            Elements[GLObjectName + "_Y_AxisCone"].ModelviewMatrix *= Matrix4d.CreateTranslation(0.0, AxisLength, 0.0);
            Elements[GLObjectName + "_Y_AxisCone"].ModelviewMatrix *= Matrix4d.CreateRotationX(-90.0);
            Elements[GLObjectName + "_Y_AxisCone"].Draw();
 
            //ZAxisCone
            Elements[GLObjectName + "_Z_AxisCone"].ModelviewMatrix = Matrix4d.Identity;
            //Must perform the appropriate transformations to place the cone at the correct place
            Elements[GLObjectName + "_Z_AxisCone"].ModelviewMatrix *= Matrix4d.CreateTranslation(0.0, 0.0, AxisLength);
            Elements[GLObjectName + "_Z_AxisCone"].Draw();
 
            //Axis Base Sphere
            Elements[GLObjectName + "_AxisBase"].Draw();
            GL.PopMatrix();
        }

The problem the moment one enters the function, regardless of the position of the line that creates the problem.